Skip to content

Commit ac9b97b

Browse files
authored
Improvements to package dependency lists (#463)
* Improvements to Python package dependencies - Add comments noting best practices for dependency management - Format dependency version ranges - Remove transitive (sub) dependencies - Update dependency minimum versions to those distributed by Ubuntu 18.04 where available - Bound version ranges in a consistent manner and leave comments where pins are necessary * Fix lint issues and un-silence linter on several error types * AWS CLI is a development dependency
1 parent 9449014 commit ac9b97b

11 files changed

Lines changed: 65 additions & 34 deletions

File tree

hca/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def add_parser_func(self, func, **kwargs):
3535
self._subparsers = self.add_subparsers()
3636
subparser = self._subparsers.add_parser(func.__name__.replace("_", "-"), **kwargs)
3737
subparser.set_defaults(entry_point=func)
38-
command = subparser.prog[len(self.prog)+1:].replace("-", "_").replace(" ", "_")
38+
command = subparser.prog[len(self.prog) + 1:].replace("-", "_").replace(" ", "_")
3939
subparser.set_defaults(**get_config().get(command, {}))
4040
if subparser.description is None:
4141
subparser.description = kwargs.get("help", func.__doc__)

hca/dss/__init__.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ class DSSClient(SwaggerClient):
7878

7979
def __init__(self, *args, **kwargs):
8080
super(DSSClient, self).__init__(*args, **kwargs)
81-
self.commands += [self.upload, self.download, self.download_manifest, self.create_version, self.download_collection]
81+
self.commands += [self.upload, self.download, self.download_manifest, self.create_version,
82+
self.download_collection]
8283

8384
def create_version(self):
8485
"""
@@ -115,7 +116,8 @@ def upload(self, src_dir, replica, staging_bucket, timeout_seconds=1200, no_prog
115116

116117
logger.info("Uploading %i files from %s to %s", len(files_to_upload), src_dir, staging_bucket)
117118
file_uuids, uploaded_keys, abs_file_paths = upload_to_cloud(files_to_upload, staging_bucket=staging_bucket,
118-
replica=replica, from_cloud=False, log_progress=not no_progress)
119+
replica=replica, from_cloud=False,
120+
log_progress=not no_progress)
119121
for file_handle in files_to_upload:
120122
file_handle.close()
121123
filenames = [object_name_builder(p, src_dir) for p in abs_file_paths]
@@ -636,7 +638,7 @@ def _do_download_file(self, dss_file, fh):
636638
server_start = 0
637639
content_range_header = response.headers.get('Content-Range', None)
638640
if content_range_header is not None:
639-
cre = re.compile("bytes (\d+)-(\d+)")
641+
cre = re.compile(r"bytes (\d+)-(\d+)")
640642
mo = cre.search(content_range_header)
641643
if mo is not None:
642644
server_start = int(mo.group(1))
@@ -651,13 +653,13 @@ def _do_download_file(self, dss_file, fh):
651653
dss_file.uuid, server_start, consume_bytes))
652654

653655
while consume_bytes > 0:
654-
bytes_to_read = min(consume_bytes, 1024*1024)
656+
bytes_to_read = min(consume_bytes, 1024 * 1024)
655657
content = response.iter_content(chunk_size=bytes_to_read)
656658
chunk = next(content)
657659
if chunk:
658660
consume_bytes -= len(chunk)
659661

660-
for chunk in response.iter_content(chunk_size=1024*1024):
662+
for chunk in response.iter_content(chunk_size=1024 * 1024):
661663
if chunk:
662664
fh.write(chunk)
663665
hasher.update(chunk)

hca/dss/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from . import DSSClient
22

3+
34
def add_commands(subparsers, help_menu=False):
45
dss_parser = subparsers.add_parser('dss', help="Interact with the HCA Data Storage System")
56

hca/query/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from . import DCPQueryClient
22

3+
34
def add_commands(subparsers, help_menu=False):
45
query_parser = subparsers.add_parser('query', help="Interact with the HCA DCP Query Service")
56

hca/upload/cli/upload_command.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ def add_parser(cls, upload_subparsers):
2323
upload_parser.add_argument('upload_paths', nargs='+', metavar="<upload_path>",
2424
help="Path to files or directories to be uploaded.")
2525
upload_parser.add_argument('-t', '--target-filename', metavar="<filename>", default=None,
26-
help="Filename to use in upload area (if you wish to change it during upload)." +
27-
" Only valid when one file is being uploaded.")
26+
help=("Filename to use in upload area (if you wish to change it during upload)."
27+
" Only valid when one file is being uploaded."))
2828
upload_parser.add_argument('--file-extension', metavar="<fileextension>", default=None,
29-
help="File extension to limit which files should be uploaded" +
30-
" Only valid when directories are targeted for upload.")
29+
help=("File extension to limit which files should be uploaded"
30+
" Only valid when directories are targeted for upload."))
3131
upload_parser.add_argument('--no-transfer-acceleration', action='store_true',
3232
help="""Don't use Amazon S3 Transfer Acceleration.
3333
By default we using the aforementioned service to upload via an endpoint
@@ -65,7 +65,7 @@ def __init__(self, args):
6565
def _load_config(self):
6666
self.config = UploadService.config()
6767
if not self.config.current_area:
68-
sys.stderr.write("\nThere is no upload area selected.\n" +
68+
sys.stderr.write("\nThere is no upload area selected.\n"
6969
"Please select one with \"{cmdname} upload select <uri_or_alias>\"\n\n".format(
7070
cmdname=sys.argv[0]))
7171
exit(1)

hca/util/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,10 @@ def _parse_properties(properties, schema):
472472
anno = typing.Optional[anno]
473473
param = Parameter(prop_name, Parameter.POSITIONAL_OR_KEYWORD, default=prop_data.get("default"),
474474
annotation=anno)
475-
method_args.setdefault(prop_name, {}).update(dict(param=param, doc=prop_data.get("description"),
476-
choices=enum_values,
477-
required=prop_name in body_json_schema.get("required", [])))
475+
method_args.setdefault(prop_name, {}).update(param=param,
476+
doc=prop_data.get("description"),
477+
choices=enum_values,
478+
required=prop_name in body_json_schema.get("required", []))
478479
body_props[prop_name] = _merge_dict(schema, body_props.get('prop_name', {}))
479480

480481
if body_json_schema.get('properties', {}):

hca/util/_docs.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
``{client_name}.{method_name}()`` listed here.
4242
"""
4343

44+
4445
def _md2rst(docstring):
4546
parser = commonmark.Parser()
4647
ast = parser.parse(docstring)
@@ -89,9 +90,9 @@ def get_params(field_list_node, params):
8990

9091
method_args = {'summary': '', 'params': dict(), 'description': ''}
9192
for node in document.children:
92-
if node.tagname is 'paragraph' and method_args['summary'] == '':
93+
if node.tagname == 'paragraph' and method_args['summary'] == '':
9394
method_args['summary'] = node.astext()
94-
elif node.tagname is 'field_list':
95+
elif node.tagname == 'field_list':
9596
get_params(node, method_args['params'])
9697
else:
9798
method_args['description'] += '\n' + node.astext()

hca/util/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from requests.exceptions import HTTPError
22

3+
34
class SwaggerAPIException(HTTPError):
45
"""
56
Exception raised by SwaggerClient when an HTTP error is received from a Swagger API server.
@@ -26,5 +27,6 @@ def __str__(self):
2627
return "{}: {} (HTTP {}). Details:\n{}".format(self.reason, self.title, self.code, self.response.text)
2728
return "{}, code {}".format(self.response.reason, self.response.status_code)
2829

30+
2931
class SwaggerClientInternalError(Exception):
3032
pass

requirements-dev.txt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
# List development (test or documentation) dependencies here.
2+
# Runtime dependencies should be listed in requirements.txt.
3+
# See the comment in requirements.txt on managing dependencies and their versions.
4+
5+
awscli
16
coverage
2-
flake8==3.5.0
7+
flake8
38
mock
4-
moto>1.3.3
9+
10+
# Old versions of moto do not mock boto3 objects with sufficient fidelity.
11+
moto > 1.3.3
12+
513
pyyaml
614
responses
715
Sphinx

requirements.txt

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,37 @@
1+
# List runtime dependencies here.
2+
# Do not pin specific versions of dependencies unless absolutely necessary.
3+
# Instead, set bounds on major version ranges of dependencies in accordance with SemVer (https://semver.org).
4+
# If you must pin a specific version of a dependency, note the reason to do so in a comment line
5+
# immediately preceding the dependency.
6+
7+
# Only dependencies which are directly imported by this library should be listed here. Dependencies
8+
# should manage their sub-dependencies. (If a sub-dependency must be restricted to a specific version
9+
# range, and upstream won't do so, note this in a comment.)
10+
111
argcomplete >= 1.9.3, < 2
2-
atomicwrites >=1.3.0, <2
3-
awscli>1.15.70
4-
boto3 > 1.8
5-
botocore>=1.12.13
12+
atomicwrites >= 1.3.0, < 2
13+
boto3 >= 1.9.86, < 2
14+
botocore >= 1.12.208, < 2
615
commonmark >= 0.9.0, < 1
716
cryptography >= 2.6.1, < 3
817
dcplib >= 2.0.2, < 3
9-
docutils==0.14
10-
google-auth >= 1.0.2, < 2
11-
google-auth-oauthlib >= 0.1, < 2
12-
Jinja2 >= 2.9, < 3
18+
19+
# The version range of docutils is pinned by botocore. Pinning it here can cause a version conflict.
20+
# See https://github.com/boto/botocore/pull/1802, https://github.com/HumanCellAtlas/dcp-cli/issues/418
21+
docutils
22+
23+
google-auth >= 1.3.0, < 2
24+
google-auth-oauthlib >= 0.4.1, < 2
25+
Jinja2 >= 2.10, < 3
1326
jsonpointer >= 1.10, < 2
1427
jsonschema >= 2.6, < 3
15-
puremagic < 1.5
16-
PyJWT >= 1.6.4
28+
29+
# Pinned due to an incompatibility with later versions of puremagic.
30+
# See https://github.com/HumanCellAtlas/dcp-cli/pull/245.
31+
puremagic==1.5
32+
33+
PyJWT >= 1.6.4, < 2
1734
requests >= 2.20.0, < 3
18-
rsa<=3.5.0,>=3.1.2
19-
s3transfer<0.3.0,>=0.2.0
20-
tenacity >=5.0.2, < 5.1
21-
tqdm >=4.33.0, < 5
22-
tweak >= 1.0.2, < 2
35+
tenacity >= 5.0.2, < 5.1
36+
tqdm >= 4.33.0, < 5
37+
tweak >= 1.0.3, < 2

0 commit comments

Comments
 (0)