Skip to content

Commit c128f7f

Browse files
h-vetinarijreback
authored andcommitted
CI for boto: fix errors; add coverage; add skip for uncatchable ResourceWarning (#23731)
1 parent a7bc7eb commit c128f7f

File tree

7 files changed

+85
-41
lines changed

7 files changed

+85
-41
lines changed

.travis.yml

+6
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ before_install:
9090
- uname -a
9191
- git --version
9292
- git tag
93+
# Because travis runs on Google Cloud and has a /etc/boto.cfg,
94+
# it breaks moto import, see:
95+
# https://github.com/spulec/moto/issues/1771
96+
# https://github.com/boto/boto/issues/3741
97+
# This overrides travis and tells it to look nowhere.
98+
- export BOTO_CONFIG=/dev/null
9399

94100
install:
95101
- echo "install start"

ci/deps/travis-36.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ channels:
44
- conda-forge
55
dependencies:
66
- beautifulsoup4
7+
- botocore>=1.11
78
- cython>=0.28.2
89
- dask
910
- fastparquet
@@ -35,10 +36,10 @@ dependencies:
3536
- pytest
3637
- pytest-xdist
3738
- pytest-cov
38-
- moto
3939
- hypothesis>=3.58.0
4040
- pip:
4141
- brotlipy
4242
- coverage
43+
- moto
4344
- pandas-datareader
4445
- python-dateutil

ci/deps/travis-37.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ channels:
55
- c3i_test
66
dependencies:
77
- python=3.7
8+
- botocore>=1.11
89
- cython>=0.28.2
910
- numpy
1011
- python-dateutil
@@ -14,3 +15,6 @@ dependencies:
1415
- pytest
1516
- pytest-xdist
1617
- hypothesis>=3.58.0
18+
- s3fs
19+
- pip:
20+
- moto

environment.yml

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ dependencies:
2727
# optional
2828
- beautifulsoup4>=4.2.1
2929
- blosc
30+
- botocore>=1.11
31+
- boto3
3032
- bottleneck>=1.2.0
3133
- fastparquet>=0.1.2
3234
- html5lib
@@ -42,6 +44,7 @@ dependencies:
4244
- pytables>=3.4.2
4345
- pytest-cov
4446
- pytest-xdist
47+
- s3fs
4548
- scipy>=1.1
4649
- seaborn
4750
- sqlalchemy

pandas/tests/io/conftest.py

+51-40
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
from distutils.version import LooseVersion
2+
import os
3+
14
import pytest
5+
6+
import pandas.util.testing as tm
7+
28
from pandas.io.parsers import read_csv
39

410

@@ -37,43 +43,48 @@ def s3_resource(tips_file, jsonl_file):
3743
"""
3844
pytest.importorskip('s3fs')
3945
boto3 = pytest.importorskip('boto3')
40-
# GH-24092. See if boto.plugin skips the test or fails.
41-
try:
42-
pytest.importorskip("boto.plugin")
43-
except AttributeError:
44-
raise pytest.skip("moto/moto error")
45-
moto = pytest.importorskip('moto')
46-
47-
test_s3_files = [
48-
('tips.csv', tips_file),
49-
('tips.csv.gz', tips_file + '.gz'),
50-
('tips.csv.bz2', tips_file + '.bz2'),
51-
('items.jsonl', jsonl_file),
52-
]
53-
54-
def add_tips_files(bucket_name):
55-
for s3_key, file_name in test_s3_files:
56-
with open(file_name, 'rb') as f:
57-
conn.Bucket(bucket_name).put_object(
58-
Key=s3_key,
59-
Body=f)
60-
61-
try:
62-
63-
s3 = moto.mock_s3()
64-
s3.start()
65-
66-
# see gh-16135
67-
bucket = 'pandas-test'
68-
conn = boto3.resource("s3", region_name="us-east-1")
69-
70-
conn.create_bucket(Bucket=bucket)
71-
add_tips_files(bucket)
72-
73-
conn.create_bucket(Bucket='cant_get_it', ACL='private')
74-
add_tips_files('cant_get_it')
75-
yield conn
76-
except: # noqa: flake8
77-
pytest.skip("failure to use s3 resource")
78-
finally:
79-
s3.stop()
46+
botocore = pytest.importorskip('botocore')
47+
48+
if LooseVersion(botocore.__version__) < LooseVersion("1.11.0"):
49+
# botocore leaks an uncatchable ResourceWarning before 1.11.0;
50+
# see GH 23731 and https://github.com/boto/botocore/issues/1464
51+
pytest.skip("botocore is leaking resources before 1.11.0")
52+
53+
with tm.ensure_safe_environment_variables():
54+
# temporary workaround as moto fails for botocore >= 1.11 otherwise,
55+
# see https://github.com/spulec/moto/issues/1924 & 1952
56+
os.environ.setdefault("AWS_ACCESS_KEY_ID", "foobar_key")
57+
os.environ.setdefault("AWS_SECRET_ACCESS_KEY", "foobar_secret")
58+
59+
moto = pytest.importorskip('moto')
60+
61+
test_s3_files = [
62+
('tips.csv', tips_file),
63+
('tips.csv.gz', tips_file + '.gz'),
64+
('tips.csv.bz2', tips_file + '.bz2'),
65+
('items.jsonl', jsonl_file),
66+
]
67+
68+
def add_tips_files(bucket_name):
69+
for s3_key, file_name in test_s3_files:
70+
with open(file_name, 'rb') as f:
71+
conn.Bucket(bucket_name).put_object(
72+
Key=s3_key,
73+
Body=f)
74+
75+
try:
76+
s3 = moto.mock_s3()
77+
s3.start()
78+
79+
# see gh-16135
80+
bucket = 'pandas-test'
81+
conn = boto3.resource("s3", region_name="us-east-1")
82+
83+
conn.create_bucket(Bucket=bucket)
84+
add_tips_files(bucket)
85+
86+
conn.create_bucket(Bucket='cant_get_it', ACL='private')
87+
add_tips_files('cant_get_it')
88+
yield conn
89+
finally:
90+
s3.stop()

pandas/util/testing.py

+16
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,22 @@ def ensure_clean_dir():
782782
pass
783783

784784

785+
@contextmanager
786+
def ensure_safe_environment_variables():
787+
"""
788+
Get a context manager to safely set environment variables
789+
790+
All changes will be undone on close, hence environment variables set
791+
within this contextmanager will neither persist nor change global state.
792+
"""
793+
saved_environ = dict(os.environ)
794+
try:
795+
yield
796+
finally:
797+
os.environ.clear()
798+
os.environ.update(saved_environ)
799+
800+
785801
# -----------------------------------------------------------------------------
786802
# Comparators
787803

requirements-dev.txt

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ sphinxcontrib-spelling
1616
numpydoc
1717
beautifulsoup4>=4.2.1
1818
blosc
19+
botocore>=1.11
20+
boto3
1921
bottleneck>=1.2.0
2022
fastparquet>=0.1.2
2123
html5lib
@@ -31,6 +33,7 @@ pyarrow>=0.7.0
3133
tables>=3.4.2
3234
pytest-cov
3335
pytest-xdist
36+
s3fs
3437
scipy>=1.1
3538
seaborn
3639
sqlalchemy

0 commit comments

Comments
 (0)