1- import shlex
2- import subprocess
3- import time
41import uuid
52
63import pytest
@@ -50,93 +47,77 @@ def xml_file(datapath):
5047 return datapath ("io" , "data" , "xml" , "books.xml" )
5148
5249
53- @pytest .fixture
54- def s3_base (worker_id , monkeypatch ):
55- """
56- Fixture for mocking S3 interaction.
50+ @pytest .fixture (scope = "session" )
51+ def aws_credentials (monkeysession ):
52+ """Mocked AWS Credentials for moto."""
53+ monkeysession .setenv ("AWS_ACCESS_KEY_ID" , "testing" )
54+ monkeysession .setenv ("AWS_SECRET_ACCESS_KEY" , "testing" )
55+ monkeysession .setenv ("AWS_SECURITY_TOKEN" , "testing" )
56+ monkeysession .setenv ("AWS_SESSION_AWS_SESSION_TOKEN" , "testing" )
57+ monkeysession .setenv ("AWS_DEFAULT_REGION" , "us-east-1" )
5758
58- Sets up moto server in separate process locally
59- Return url for motoserver/moto CI service
60- """
61- pytest .importorskip ("s3fs" )
62- pytest .importorskip ("boto3" )
63-
64- # temporary workaround as moto fails for botocore >= 1.11 otherwise,
65- # see https://github.com/spulec/moto/issues/1924 & 1952
66- monkeypatch .setenv ("AWS_ACCESS_KEY_ID" , "foobar_key" )
67- monkeypatch .setenv ("AWS_SECRET_ACCESS_KEY" , "foobar_secret" )
68- if is_ci_environment ():
69- if is_platform_arm () or is_platform_mac () or is_platform_windows ():
70- # NOT RUN on Windows/macOS, only Ubuntu
71- # - subprocess in CI can cause timeouts
72- # - GitHub Actions do not support
73- # container services for the above OSs
74- pytest .skip (
75- "S3 tests do not have a corresponding service on "
76- "Windows or macOS platforms"
77- )
78- else :
79- # set in .github/workflows/unit-tests.yml
80- yield "http://localhost:5000"
59+
60+ @pytest .fixture (scope = "session" )
61+ def moto_server (aws_credentials ):
62+ # use service container for Linux on GitHub Actions
63+ if is_ci_environment () and not (
64+ is_platform_mac () or is_platform_arm () or is_platform_windows ()
65+ ):
66+ yield "http://localhost:5000"
8167 else :
82- requests = pytest .importorskip ("requests" )
83- pytest .importorskip ("moto" )
84- pytest .importorskip ("flask" ) # server mode needs flask too
85-
86- # Launching moto in server mode, i.e., as a separate process
87- # with an S3 endpoint on localhost
88-
89- worker_id = "5" if worker_id == "master" else worker_id .lstrip ("gw" )
90- endpoint_port = f"555{ worker_id } "
91- endpoint_uri = f"http://127.0.0.1:{ endpoint_port } /"
92-
93- # pipe to null to avoid logging in terminal
94- with subprocess .Popen (
95- shlex .split (f"moto_server s3 -p { endpoint_port } " ),
96- stdout = subprocess .DEVNULL ,
97- stderr = subprocess .DEVNULL ,
98- ) as proc :
99- timeout = 5
100- while timeout > 0 :
101- try :
102- # OK to go once server is accepting connections
103- r = requests .get (endpoint_uri )
104- if r .ok :
105- break
106- except Exception :
107- pass
108- timeout -= 0.1
109- time .sleep (0.1 )
110- yield endpoint_uri
111-
112- proc .terminate ()
68+ moto_server = pytest .importorskip ("moto.server" )
69+ server = moto_server .ThreadedMotoServer (port = 0 )
70+ server .start ()
71+ host , port = server .get_host_and_port ()
72+ yield f"http://{ host } :{ port } "
73+ server .stop ()
11374
11475
11576@pytest .fixture
116- def s3so (s3_base ):
117- return {"client_kwargs" : {"endpoint_url" : s3_base }}
77+ def moto_s3_resource (moto_server ):
78+ boto3 = pytest .importorskip ("boto3" )
79+ s3 = boto3 .resource ("s3" , endpoint_url = moto_server )
80+ return s3
11881
11982
120- @pytest .fixture
121- def s3_resource (s3_base ):
122- import boto3
83+ @pytest .fixture (scope = "session" )
84+ def s3so (moto_server ):
85+ return {
86+ "client_kwargs" : {
87+ "endpoint_url" : moto_server ,
88+ }
89+ }
12390
124- s3 = boto3 .resource ("s3" , endpoint_url = s3_base )
125- return s3
91+
92+ @pytest .fixture
93+ def s3_bucket_public (moto_s3_resource ):
94+ """
95+ Create a public S3 bucket using moto.
96+ """
97+ bucket_name = f"pandas-test-{ uuid .uuid4 ()} "
98+ bucket = moto_s3_resource .Bucket (bucket_name )
99+ bucket .create (ACL = "public-read" )
100+ yield bucket
101+ bucket .objects .delete ()
102+ bucket .delete ()
126103
127104
128105@pytest .fixture
129- def s3_public_bucket (s3_resource ):
130- bucket = s3_resource .Bucket (f"pandas-test-{ uuid .uuid4 ()} " )
131- bucket .create ()
106+ def s3_bucket_private (moto_s3_resource ):
107+ """
108+ Create a private S3 bucket using moto.
109+ """
110+ bucket_name = f"cant_get_it-{ uuid .uuid4 ()} "
111+ bucket = moto_s3_resource .Bucket (bucket_name )
112+ bucket .create (ACL = "private" )
132113 yield bucket
133114 bucket .objects .delete ()
134115 bucket .delete ()
135116
136117
137118@pytest .fixture
138- def s3_public_bucket_with_data (
139- s3_public_bucket , tips_file , jsonl_file , feather_file , xml_file
119+ def s3_bucket_public_with_data (
120+ s3_bucket_public , tips_file , jsonl_file , feather_file , xml_file
140121):
141122 """
142123 The following datasets
@@ -158,22 +139,13 @@ def s3_public_bucket_with_data(
158139 ]
159140 for s3_key , file_name in test_s3_files :
160141 with open (file_name , "rb" ) as f :
161- s3_public_bucket .put_object (Key = s3_key , Body = f )
162- return s3_public_bucket
163-
164-
165- @pytest .fixture
166- def s3_private_bucket (s3_resource ):
167- bucket = s3_resource .Bucket (f"cant_get_it-{ uuid .uuid4 ()} " )
168- bucket .create (ACL = "private" )
169- yield bucket
170- bucket .objects .delete ()
171- bucket .delete ()
142+ s3_bucket_public .put_object (Key = s3_key , Body = f )
143+ return s3_bucket_public
172144
173145
174146@pytest .fixture
175- def s3_private_bucket_with_data (
176- s3_private_bucket , tips_file , jsonl_file , feather_file , xml_file
147+ def s3_bucket_private_with_data (
148+ s3_bucket_private , tips_file , jsonl_file , feather_file , xml_file
177149):
178150 """
179151 The following datasets
@@ -195,8 +167,8 @@ def s3_private_bucket_with_data(
195167 ]
196168 for s3_key , file_name in test_s3_files :
197169 with open (file_name , "rb" ) as f :
198- s3_private_bucket .put_object (Key = s3_key , Body = f )
199- return s3_private_bucket
170+ s3_bucket_private .put_object (Key = s3_key , Body = f )
171+ return s3_bucket_private
200172
201173
202174_compression_formats_params = [
0 commit comments