Skip to content

Commit 3763697

Browse files
authored
Add tox.ini and configure coverage and flake runs (#80)
* Add tox.ini and configure coverage and flake runs * Add more unit tests * Configure unit tests to run with both py2 and py3 * Add flake checks * Fix broken integ tests * Add import style check * Add .flake8 * Add source module in coverage command * Add newlines
1 parent c93d034 commit 3763697

File tree

18 files changed

+210
-62
lines changed

18 files changed

+210
-62
lines changed

.coveragerc_py27

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[run]
2+
branch = True
3+
timid = True
4+
5+
[report]
6+
exclude_lines =
7+
pragma: no cover
8+
pragma: py2 no cover
9+
if six.PY3
10+
elif six.PY3
11+
12+
partial_branches =
13+
pragma: no cover
14+
pragma: py2 no cover
15+
if six.PY3
16+
elif six.PY3
17+
18+
show_missing = True
19+
20+
fail_under = 90

.coveragerc_py36

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[run]
2+
branch = True
3+
timid = True
4+
5+
[report]
6+
exclude_lines =
7+
pragma: no cover
8+
pragma: py3 no cover
9+
if six.PY2
10+
elif six.PY2
11+
12+
partial_branches =
13+
pragma: no cover
14+
pragma: py3 no cover
15+
if six.PY3
16+
elif six.PY3
17+
18+
show_missing = True
19+
20+
fail_under = 90

.flake8

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[flake8]
2+
application_import_names = sagemaker_tensorflow_container, test
3+
import-order-style = google

docker/1.10.0/Dockerfile.cpu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,4 @@ RUN framework_installable_local=$(basename $framework_installable) \
7070
&& rm $framework_installable_local \
7171
&& rm $framework_support_installable_local
7272

73-
ENV SAGEMAKER_TRAINING_MODULE tf_container.training:main
73+
ENV SAGEMAKER_TRAINING_MODULE sagemaker_tensorflow_container.training:main

docker/1.10.0/Dockerfile.gpu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,4 @@ RUN framework_installable_local=$(basename $framework_installable) && \
6969
rm $framework_installable_local && \
7070
rm $framework_support_installable_local
7171

72-
ENV SAGEMAKER_TRAINING_MODULE tf_container.training:main
72+
ENV SAGEMAKER_TRAINING_MODULE sagemaker_tensorflow_container.training:main

setup.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
1-
import os
1+
# Copyright 2017-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
from __future__ import absolute_import
14+
215
from glob import glob
16+
import os
317
from os.path import basename
418
from os.path import splitext
519

6-
from setuptools import setup, find_packages
20+
from setuptools import find_packages, setup
721

822

923
def read(fname):
@@ -13,7 +27,8 @@ def read(fname):
1327
setup(
1428
name='sagemaker_tensorflow_container',
1529
version='2.0.0',
16-
description='Open source library for creating TensorFlow containers to run on Amazon SageMaker.',
30+
description='Open source library for creating '
31+
'TensorFlow containers to run on Amazon SageMaker.',
1732

1833
packages=find_packages(where='src', exclude=('test',)),
1934
package_dir={'': 'src'},
@@ -34,7 +49,8 @@ def read(fname):
3449
'Programming Language :: Python :: 3.6',
3550
],
3651

37-
install_requires=['sagemaker-containers==2.1', 'numpy', 'scipy', 'sklearn', 'pandas', 'Pillow', 'h5py'],
52+
install_requires=['sagemaker-containers==2.1', 'numpy', 'scipy', 'sklearn',
53+
'pandas', 'Pillow', 'h5py'],
3854
extras_require={
3955
'test': ['tox', 'flake8', 'pytest', 'pytest-cov', 'pytest-xdist', 'mock',
4056
'sagemaker', 'tensorflow', 'docker-compose']

src/tf_container/training.py renamed to src/sagemaker_tensorflow_container/training.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from __future__ import absolute_import
1515

1616
import logging
17+
1718
import sagemaker_containers.beta.framework as framework
1819

1920
logger = logging.getLogger(__name__)

test/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License").
44
# You may not use this file except in compliance with the License.
55
# A copy of the License is located at
6-
#
6+
#
77
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# or in the "license" file accompanying this file. This file is distributed
10-
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11-
# express or implied. See the License for the specific language governing
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
1212
# permissions and limitations under the License.
1313
from __future__ import absolute_import

test/conftest.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License").
44
# You may not use this file except in compliance with the License.
55
# A copy of the License is located at
6-
#
6+
#
77
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# or in the "license" file accompanying this file. This file is distributed
10-
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11-
# express or implied. See the License for the specific language governing
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
1212
# permissions and limitations under the License.
1313
from __future__ import absolute_import
1414

@@ -17,7 +17,6 @@
1717

1818
import boto3
1919
import pytest
20-
2120
from sagemaker import LocalSession, Session
2221

2322
logger = logging.getLogger(__name__)
@@ -92,4 +91,3 @@ def skip_by_device_type(request, processor):
9291
@pytest.fixture(scope='session')
9392
def docker_image(docker_base_name, tag):
9493
return '{}:{}'.format(docker_base_name, tag)
95-

test/integration/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License").
44
# You may not use this file except in compliance with the License.
55
# A copy of the License is located at
6-
#
6+
#
77
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# or in the "license" file accompanying this file. This file is distributed
10-
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11-
# express or implied. See the License for the specific language governing
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
1212
# permissions and limitations under the License.
1313
from __future__ import absolute_import
1414

1515
import logging
1616

1717
logging.getLogger('boto3').setLevel(logging.INFO)
18-
logging.getLogger('botocore').setLevel(logging.INFO)
18+
logging.getLogger('botocore').setLevel(logging.INFO)

test/integration/docker_utils.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License").
44
# You may not use this file except in compliance with the License.
55
# A copy of the License is located at
6-
#
6+
#
77
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# or in the "license" file accompanying this file. This file is distributed
10-
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11-
# express or implied. See the License for the specific language governing
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
1212
# permissions and limitations under the License.
1313
from __future__ import absolute_import
1414

@@ -92,13 +92,13 @@ def execute_command(self, cmd):
9292
lines = []
9393
process = subprocess.Popen(docker_cmd, stdout=subprocess.PIPE)
9494
print(
95-
'{}============================= container output ============================='.format(
96-
CYAN_COLOR))
95+
'{}========================= container output ========================='.format(
96+
CYAN_COLOR))
9797
for line in iter(process.stdout.readline, b''):
9898
sys.stdout.write(line.decode('utf-8'))
9999
sys.stdout.flush()
100100
lines.append(line.decode('utf-8'))
101-
msg = '\n{}============================= end of container output ============================='
101+
msg = '\n{}========================= end of container output ========================='
102102
print(msg.format(CYAN_COLOR))
103103

104104
process.wait()

test/integration/local/test_training.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
from __future__ import absolute_import
1414

1515
import os
16-
import pytest
1716

17+
import pytest
1818
from sagemaker.tensorflow import TensorFlow
19+
1920
from test.integration.docker_utils import Container
2021

2122

@@ -40,7 +41,8 @@ def test_mnist_cpu(sagemaker_local_session, docker_image):
4041
instance_type='local',
4142
sagemaker_local_session=sagemaker_local_session,
4243
docker_image=docker_image,
43-
training_data_path='file://{}'.format(os.path.join(resource_path, 'data')))
44+
training_data_path='file://{}'.format(
45+
os.path.join(resource_path, 'data')))
4446
assert os.path.exists(os.path.join(output_path, 'my_model.h5')), 'model file not found'
4547

4648

@@ -51,10 +53,12 @@ def test_gpu(sagemaker_local_session, docker_image):
5153
instance_type='local_gpu',
5254
sagemaker_local_session=sagemaker_local_session,
5355
docker_image=docker_image,
54-
training_data_path='file://{}'.format(os.path.join(resource_path, 'mnist', 'data')))
56+
training_data_path='file://{}'.format(
57+
os.path.join(resource_path, 'mnist', 'data')))
5558

5659

57-
def run_tf_single_training(script, instance_type, sagemaker_local_session, docker_image, training_data_path):
60+
def run_tf_single_training(script, instance_type, sagemaker_local_session,
61+
docker_image, training_data_path):
5862
estimator = TensorFlow(entry_point=script,
5963
role='SageMakerRole',
6064
training_steps=1,
@@ -66,4 +70,5 @@ def run_tf_single_training(script, instance_type, sagemaker_local_session, docke
6670
base_job_name='test-tf-single')
6771

6872
estimator.fit(training_data_path)
69-
return estimator.sagemaker_session.sagemaker_client.s3_model_artifacts
73+
model = estimator.create_model()
74+
return model.model_data

test/resources/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License").
44
# You may not use this file except in compliance with the License.
55
# A copy of the License is located at
6-
#
6+
#
77
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# or in the "license" file accompanying this file. This file is distributed
10-
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11-
# express or implied. See the License for the specific language governing
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
1212
# permissions and limitations under the License.
1313
from __future__ import absolute_import

test/resources/mnist/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License").
44
# You may not use this file except in compliance with the License.
55
# A copy of the License is located at
6-
#
6+
#
77
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# or in the "license" file accompanying this file. This file is distributed
10-
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11-
# express or implied. See the License for the specific language governing
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
1212
# permissions and limitations under the License.
1313
from __future__ import absolute_import

test/unit/__init__.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License").
44
# You may not use this file except in compliance with the License.
55
# A copy of the License is located at
6-
#
6+
#
77
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# or in the "license" file accompanying this file. This file is distributed
10-
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11-
# express or implied. See the License for the specific language governing
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
1212
# permissions and limitations under the License.
1313
from __future__ import absolute_import
14-

test/unit/test_training.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
# language governing permissions and limitations under the License.
1313
from __future__ import absolute_import
1414

15-
import pytest
1615
from mock import MagicMock, patch
16+
import pytest
1717

18-
from tf_container import training
18+
from sagemaker_tensorflow_container import training
1919

2020
MODULE_DIR = 's3://my/bucket'
2121
MODULE_NAME = 'script_name'
22+
LOG_LEVEL = 'Debug'
23+
2224

2325
@pytest.fixture
2426
def single_machine_training_env():
@@ -27,11 +29,26 @@ def single_machine_training_env():
2729
env.module_dir = MODULE_DIR
2830
env.module_name = MODULE_NAME
2931
env.hyperparameters = {}
32+
env.log_level = LOG_LEVEL
3033

3134
return env
3235

36+
3337
@patch('sagemaker_containers.beta.framework.modules.run_module')
3438
def test_single_machine(run_module, single_machine_training_env):
3539
training.train(single_machine_training_env)
3640
run_module.assert_called_with(MODULE_DIR, single_machine_training_env.to_cmd_args(),
3741
single_machine_training_env.to_env_vars(), MODULE_NAME)
42+
43+
44+
@patch('sagemaker_tensorflow_container.training.train')
45+
@patch('logging.Logger.setLevel')
46+
@patch('sagemaker_containers.beta.framework.training_env')
47+
@patch('sagemaker_containers.beta.framework.env.read_hyperparameters', return_value={})
48+
def test_main(read_hyperparameters, training_env, set_level, train, single_machine_training_env):
49+
training_env.return_value = single_machine_training_env
50+
training.main()
51+
read_hyperparameters.assert_called_once_with()
52+
training_env.assert_called_once_with(hyperparameters={})
53+
set_level.assert_called_once_with(LOG_LEVEL)
54+
train.assert_called_once_with(single_machine_training_env)

0 commit comments

Comments
 (0)