From 9716ea93e0929a2028b753b72528b647e93401e5 Mon Sep 17 00:00:00 2001 From: Hal Wine Date: Thu, 24 Sep 2020 16:01:52 -0700 Subject: [PATCH] Update code to py36 syntax Work done by pyupgrade pre-commit plugin. Included: - conversion to f-strings where possible - removal of redundant syntax - application of Exception hierarchy changes in py 3.3 (IOError is now a subclass of OSError, and need not be listed separately) This was done to get a baseline before updating to py38 syntax --- aws/client.py | 29 +++++----- aws/ec2/helpers.py | 57 +++++++------------ ...tance_not_publicly_accessible_by_vpc_sg.py | 10 ++-- cache.py | 24 ++++---- custom_config.py | 2 +- gcp/iam/resources.py | 6 +- gcp/iam/test_only_allowed_org_accounts.py | 13 +++-- github/branches/retrieve_github_data.py | 25 ++++---- github/branches/test_branch_protection.py | 1 - github/branches/validate_compliance.py | 9 +-- github/conftest.py | 7 +-- github/manage_issues.py | 28 ++++----- github/orgs/__init__.py | 1 - github/orgs/test_two_factor_required.py | 1 - github/orgs/validate_compliance.py | 9 +-- github/vscode-debug-wrapper.py | 1 - heroku/client.py | 15 ++--- service_report_generator.py | 7 +-- setup.py | 2 +- 19 files changed, 98 insertions(+), 149 deletions(-) diff --git a/aws/client.py b/aws/client.py index 2e7e61b..87a26a1 100644 --- a/aws/client.py +++ b/aws/client.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import os from collections import namedtuple import functools @@ -34,7 +32,8 @@ def get_session(profile=None): @functools.lru_cache() def get_client(profile, region, service): - """Returns a new or cached botocore service client for the AWS profile, region, and service. + """Returns a new or cached botocore service client for the AWS profile, + region, and service. Warns when a service is not available for a region, which means we need to update botocore or skip that call for that region. @@ -42,7 +41,7 @@ def get_client(profile, region, service): session = get_session(profile) if region not in session.get_available_regions(service): - warnings.warn("service {} not available in {}".format(service, region)) + warnings.warn(f"service {service} not available in {region}") return session.create_client(service, region_name=region) @@ -63,7 +62,10 @@ def get_available_services(profile=None): def full_results(client, method, args, kwargs): - """Returns JSON results for an AWS botocore call. Flattens paginated results (if any).""" + """Returns JSON results for an AWS botocore call. + + Flattens paginated results (if any). + """ if client.can_paginate(method): paginator = client.get_paginator(method) return paginator.paginate(*args, **kwargs).build_full_result() @@ -96,7 +98,7 @@ def cache_key(call): str(call.service), str(call.method), ",".join(call.args), - ",".join("{}={}".format(k, v) for (k, v) in call.kwargs.items()), + ",".join(f"{k}={v}" for (k, v) in call.kwargs.items()), ] ) + ".json" @@ -115,9 +117,8 @@ def get_aws_resource( debug_calls=False, debug_cache=False, ): - """ - Fetches and yields AWS API JSON responses for all profiles and regions (list params) - """ + """Fetches and yields AWS API JSON responses for all profiles and regions + (list params)""" for profile, region in itertools.product(profiles, regions): call = default_call._replace( profile=profile, @@ -224,7 +225,7 @@ def get( return self def values(self): - """Returns the wrapped value + """Returns the wrapped value. >>> c = BotocoreClient([None], None, None, None, offline=True) >>> c.results = [] @@ -234,9 +235,8 @@ def values(self): return self.results def extract_key(self, key, default=None): - """ - From an iterable of dicts returns the value with the given - keys discarding other values: + """From an iterable of dicts returns the value with the given keys + discarding other values: >>> c = BotocoreClient([None], None, None, None, offline=True) >>> c.results = [{'id': 1}, {'id': 2}] @@ -299,8 +299,7 @@ def extract_key(self, key, default=None): return self def flatten(self): - """ - Flattens one level of a nested list: + """Flattens one level of a nested list: >>> c = BotocoreClient([None], None, None, None, offline=True) >>> c.results = [['A', 1], ['B']] diff --git a/aws/ec2/helpers.py b/aws/ec2/helpers.py index a924c77..eb84245 100644 --- a/aws/ec2/helpers.py +++ b/aws/ec2/helpers.py @@ -1,7 +1,6 @@ def ip_permission_opens_all_ports(ipp): - """ - Returns True if an EC2 security group IP permission opens all - ports and False otherwise. + """Returns True if an EC2 security group IP permission opens all ports and + False otherwise. >>> ip_permission_opens_all_ports({'FromPort': 1, 'ToPort': 65535}) True @@ -31,10 +30,8 @@ def ip_permission_opens_all_ports(ipp): def ip_permission_cidr_allows_all_ips(ipp): - """ - Returns True if any IPv4 or IPv6 range for an EC2 security group - IP permission opens allows access to or from all IPs and False - otherwise. + """Returns True if any IPv4 or IPv6 range for an EC2 security group IP + permission opens allows access to or from all IPs and False otherwise. >>> ip_permission_cidr_allows_all_ips({'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}) True @@ -60,9 +57,8 @@ def ip_permission_cidr_allows_all_ips(ipp): def ip_permission_grants_access_to_group_with_id(ipp, security_group_id): - """ - Returns True if an EC2 security group IP permission opens access to - a security with the given ID and False otherwise. + """Returns True if an EC2 security group IP permission opens access to a + security with the given ID and False otherwise. >>> ip_permission_grants_access_to_group_with_id( ... {'UserIdGroupPairs': [{'GroupId': 'test-sgid'}]}, 'test-sgid') @@ -81,10 +77,8 @@ def ip_permission_grants_access_to_group_with_id(ipp, security_group_id): def ec2_security_group_opens_all_ports(ec2_security_group): - """ - Returns True if an ec2 security group includes a permission - allowing inbound access on all ports and False otherwise - or if protocol is ICMP. + """Returns True if an ec2 security group includes a permission allowing + inbound access on all ports and False otherwise or if protocol is ICMP. >>> ec2_security_group_opens_all_ports( ... {'IpPermissions': [{}, {'FromPort': -1,'ToPort': 65536}]}) @@ -109,10 +103,8 @@ def ec2_security_group_opens_all_ports(ec2_security_group): def ec2_security_group_opens_all_ports_to_self(ec2_security_group): - """ - Returns True if an ec2 security group includes a permission - allowing all IPs inbound access on all ports and False otherwise - or if protocol is ICMP. + """Returns True if an ec2 security group includes a permission allowing all + IPs inbound access on all ports and False otherwise or if protocol is ICMP. >>> ec2_security_group_opens_all_ports_to_self({ ... 'GroupId': 'test-sgid', @@ -166,10 +158,8 @@ def ec2_security_group_opens_all_ports_to_self(ec2_security_group): def ec2_security_group_opens_all_ports_to_all(ec2_security_group): - """ - Returns True if an ec2 security group includes a permission - allowing all IPs inbound access on all ports and False otherwise - or if protocol is ICMP. + """Returns True if an ec2 security group includes a permission allowing all + IPs inbound access on all ports and False otherwise or if protocol is ICMP. >>> ec2_security_group_opens_all_ports_to_all({'IpPermissions': [ ... {'FromPort': -1,'ToPort': 65535,'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}, @@ -208,10 +198,9 @@ def ec2_security_group_opens_all_ports_to_all(ec2_security_group): def ec2_security_group_opens_specific_ports_to_all( ec2_security_group, whitelisted_ports=None ): - """ - Returns True if an ec2 security group includes a permission - allowing all IPs inbound access on specific unsafe ports and False - otherwise or if protocol is ICMP. + """Returns True if an ec2 security group includes a permission allowing all + IPs inbound access on specific unsafe ports and False otherwise or if + protocol is ICMP. >>> ec2_security_group_opens_specific_ports_to_all({'IpPermissions': [ ... {'FromPort': 22,'ToPort': 22,'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}, @@ -260,18 +249,17 @@ def ec2_security_group_opens_specific_ports_to_all( def ec2_instance_test_id(ec2_instance): - """A getter fn for test ids for EC2 instances""" + """A getter fn for test ids for EC2 instances.""" return "{0[InstanceId]}".format(ec2_instance) def ec2_security_group_test_id(ec2_security_group): - """A getter fn for test ids for EC2 security groups""" + """A getter fn for test ids for EC2 security groups.""" return "{0[GroupId]} {0[GroupName]}".format(ec2_security_group) def is_ebs_volume_encrypted(ebs): - """ - Checks the EBS volume 'Encrypted' value. + """Checks the EBS volume 'Encrypted' value. >>> is_ebs_volume_encrypted({'Encrypted': True}) True @@ -294,8 +282,8 @@ def is_ebs_volume_encrypted(ebs): def is_ebs_snapshot_public(ebs_snapshot): - """ - Checks if the EBS snapshot's 'CreateVolumePermissions' attribute allows for public creation. + """Checks if the EBS snapshot's 'CreateVolumePermissions' attribute allows + for public creation. >>> is_ebs_snapshot_public({'CreateVolumePermissions':[{'Group': 'all'}]}) True @@ -315,8 +303,7 @@ def is_ebs_snapshot_public(ebs_snapshot): def ec2_instance_missing_tag_names(ec2_instance, required_tag_names): - """ - Returns any tag names that are missing from an EC2 Instance. + """Returns any tag names that are missing from an EC2 Instance. >>> ec2_instance_missing_tag_names({'Tags': [{'Key': 'Name'}]}, frozenset(['Name'])) frozenset() @@ -325,5 +312,5 @@ def ec2_instance_missing_tag_names(ec2_instance, required_tag_names): frozenset({'Name'}) """ tags = ec2_instance.get("Tags", []) - instance_tag_names = set(tag["Key"] for tag in tags if "Key" in tag) + instance_tag_names = {tag["Key"] for tag in tags if "Key" in tag} return required_tag_names - instance_tag_names diff --git a/aws/rds/test_rds_db_instance_not_publicly_accessible_by_vpc_sg.py b/aws/rds/test_rds_db_instance_not_publicly_accessible_by_vpc_sg.py index b13d268..e197ff1 100644 --- a/aws/rds/test_rds_db_instance_not_publicly_accessible_by_vpc_sg.py +++ b/aws/rds/test_rds_db_instance_not_publicly_accessible_by_vpc_sg.py @@ -16,16 +16,14 @@ def test_rds_db_instance_not_publicly_accessible_by_vpc_security_group( rds_db_instance, ec2_security_groups ): - """ - Checks whether any VPC/EC2 security groups that are attached to an RDS instance - allow for access from the public internet. - """ + """Checks whether any VPC/EC2 security groups that are attached to an RDS + instance allow for access from the public internet.""" if not ec2_security_groups: assert not rds_db_instance["VpcSecurityGroups"] else: - assert set(sg["GroupId"] for sg in ec2_security_groups) == set( + assert {sg["GroupId"] for sg in ec2_security_groups} == { sg["VpcSecurityGroupId"] for sg in rds_db_instance["VpcSecurityGroups"] - ) + } assert not any( does_vpc_security_group_grant_public_access(sg) diff --git a/cache.py b/cache.py index b5ce7d4..1bf81a2 100644 --- a/cache.py +++ b/cache.py @@ -1,6 +1,4 @@ -""" -Patch for pytest cache to serialize datetime.datetime -""" +"""Patch for pytest cache to serialize datetime.datetime.""" import datetime import functools @@ -11,8 +9,7 @@ def json_iso_datetimes(obj): - """JSON serializer for objects not serializable by default json - module.""" + """JSON serializer for objects not serializable by default json module.""" if isinstance(obj, datetime.datetime): return obj.isoformat() @@ -20,8 +17,8 @@ def json_iso_datetimes(obj): def json_iso_datetime_string_to_datetime(obj): - """JSON object hook that converts object vals from ISO datetime - strings to python datetime.datetime`s if possible.""" + """JSON object hook that converts object vals from ISO datetime strings to + python datetime.datetime`s if possible.""" for k, v in obj.items(): if not isinstance(v, str): @@ -36,7 +33,7 @@ def json_iso_datetime_string_to_datetime(obj): def datetime_encode_set(self, key, value): - """ save value for the given key. + """save value for the given key. :param key: must be a ``/`` separated value. Usually the first name is the name of your plugin or your application. @@ -47,12 +44,12 @@ def datetime_encode_set(self, key, value): path = self._getvaluepath(key) try: path.parent.mkdir(exist_ok=True, parents=True) - except (IOError, OSError): + except OSError: self.warn("could not create cache path {path}", path=path) return try: f = path.open("w") - except (IOError, OSError): + except OSError: self.warn("cache could not write path {path}", path=path) else: with f: @@ -61,9 +58,8 @@ def datetime_encode_set(self, key, value): def datetime_encode_get(self, key, default): - """ return cached value for the given key. If no value - was yet cached or the value cannot be read, the specified - default is returned. + """return cached value for the given key. If no value was yet cached or + the value cannot be read, the specified default is returned. :param key: must be a ``/`` separated value. Usually the first name is the name of your plugin or your application. @@ -74,7 +70,7 @@ def datetime_encode_get(self, key, default): try: with path.open("r") as f: return json.load(f, object_hook=json_iso_datetime_string_to_datetime) - except (ValueError, IOError, OSError): + except (ValueError, OSError): return default diff --git a/custom_config.py b/custom_config.py index e958e6c..7a58fc9 100644 --- a/custom_config.py +++ b/custom_config.py @@ -89,7 +89,7 @@ def get_whitelisted_ports_from_test_id(self, test_id): if test_id == rule["test_param_id"]: return set(rule["ports"]) - return set([]) + return set() def get_access_key_expiration_date(self): if self.access_key_expires_after is None: diff --git a/gcp/iam/resources.py b/gcp/iam/resources.py index 07843f2..7b882d0 100644 --- a/gcp/iam/resources.py +++ b/gcp/iam/resources.py @@ -21,11 +21,9 @@ def service_account_keys(service_account): def all_service_account_keys(): for sa in service_accounts(): - for key in service_account_keys(sa): - yield key + yield from service_account_keys(sa) def project_iam_bindings(): policy = gcp_client.get_project_iam_policy() - for binding in policy.get("bindings", []): - yield binding + yield from policy.get("bindings", []) diff --git a/gcp/iam/test_only_allowed_org_accounts.py b/gcp/iam/test_only_allowed_org_accounts.py index 979e9ff..37dfa40 100644 --- a/gcp/iam/test_only_allowed_org_accounts.py +++ b/gcp/iam/test_only_allowed_org_accounts.py @@ -14,11 +14,12 @@ def allowed_org_domains(pytestconfig): @pytest.mark.gcp_iam @pytest.mark.parametrize("iam_binding", project_iam_bindings(), ids=lambda r: r["role"]) def test_only_allowed_org_accounts(iam_binding, allowed_org_domains): - """ - Only allow specified org domains as members within this project, with a few exceptions. - * Service Accounts are excluded - * The following roles are excluded: - - roles/logging.viewer + """Only allow specified org domains as members within this project, with a + few exceptions. + + * Service Accounts are excluded + * The following roles are excluded: + - roles/logging.viewer """ if len(allowed_org_domains) == 0: assert False, "No allowed org domains specified" @@ -28,4 +29,4 @@ def test_only_allowed_org_accounts(iam_binding, allowed_org_domains): if not member.startswith("serviceAccount"): assert ( member.split("@")[-1] in allowed_org_domains - ), "{} was found and is not in the allowed_org_domains".format(member) + ), f"{member} was found and is not in the allowed_org_domains" diff --git a/github/branches/retrieve_github_data.py b/github/branches/retrieve_github_data.py index bf8fbe6..6a88507 100644 --- a/github/branches/retrieve_github_data.py +++ b/github/branches/retrieve_github_data.py @@ -2,11 +2,8 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. -""" -Collect Information about branches sufficient to check for all branch -protection guideline compliance. - -""" +"""Collect Information about branches sufficient to check for all branch +protection guideline compliance.""" # TODO add doctests import csv @@ -136,7 +133,7 @@ def csv_row(self) -> List[str]: def _add_protection_fields(node) -> None: - """ Build in fields we want to query + """Build in fields we want to query. In normal gQuery, this would be a fragment """ @@ -146,7 +143,7 @@ def _add_protection_fields(node) -> None: def create_operation(owner, name): - """ Create the default Query operation + """Create the default Query operation. We build the structure for: repository: @@ -195,7 +192,7 @@ def create_operation(owner, name): def create_rule_query(): - """ Create a query object for additional branch protection entries + """Create a query object for additional branch protection entries. Used to fetch subsequent pages. End Cursor is passed as a variable """ @@ -224,7 +221,7 @@ def get_nested_branch_data(endpoint, reponame): repodata = (op + d).repository def _more_to_do(cur_result, fake_new_page=False): - """ Determine if we need another query + """Determine if we need another query. There are two nested repeating elements in the query - if either is not yet exhausted, we have to do another query @@ -289,9 +286,7 @@ def _more_to_do(cur_result, fake_new_page=False): def extract_branch_data(repodata) -> RepoBranchProtections: - """ extract relevant data from sgqlc structure - - """ + """extract relevant data from sgqlc structure.""" repo_data = RepoBranchProtections( name_with_owner=repodata.name_with_owner, default_branch_ref=repodata.default_branch_ref.name, @@ -392,14 +387,14 @@ def _compact_fmt(d): lst.append(_compact_fmt(e)) else: lst.append(repr(e)) - s.append("%s=[%s]" % (k, ", ".join(lst))) + s.append("{}=[{}]".format(k, ", ".join(lst))) continue - s.append("%s=%r" % (k, v)) + s.append(f"{k}={v!r}") return "(" + ", ".join(s) + ")" def _report_download_errors(errors): - """ error handling for graphql comms """ + """error handling for graphql comms.""" logger.error("Document contain %d errors", len(errors)) for i, e in enumerate(errors): msg = e.pop("message") diff --git a/github/branches/test_branch_protection.py b/github/branches/test_branch_protection.py index a6981ec..ae532ae 100644 --- a/github/branches/test_branch_protection.py +++ b/github/branches/test_branch_protection.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/github/branches/validate_compliance.py b/github/branches/validate_compliance.py index 5c94c28..2c13696 100644 --- a/github/branches/validate_compliance.py +++ b/github/branches/validate_compliance.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -19,8 +18,7 @@ class Criteria: @staticmethod def idfn(val: Any) -> Optional[str]: - """ provide ID for pytest Parametrization - """ + """provide ID for pytest Parametrization.""" if isinstance(val, (Criteria,)): return f"{val.standard_number}-{val.slug}" return None @@ -75,10 +73,7 @@ def meets_criteria(protections: List[BranchProtectionRule], criteria: Criteria) def validate_branch_protections( data: RepoBranchProtections, branch: str, criteria: Criteria, ) -> List[str]: - """ - Validate the protections - - """ + """Validate the protections.""" results = [] diff --git a/github/conftest.py b/github/conftest.py index 78c5749..98ccf24 100755 --- a/github/conftest.py +++ b/github/conftest.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -62,14 +61,14 @@ def _compact_fmt(d): lst.append(_compact_fmt(e)) else: lst.append(repr(e)) - s.append("%s=[%s]" % (k, ", ".join(lst))) + s.append("{}=[{}]".format(k, ", ".join(lst))) continue - s.append("%s=%r" % (k, v)) + s.append(f"{k}={v!r}") return "(" + ", ".join(s) + ")" def _report_download_errors(errors): - """ error handling for graphql comms """ + """error handling for graphql comms.""" logger.error("Document contain %d errors", len(errors)) for i, e in enumerate(errors): msg = e.pop("message") diff --git a/github/manage_issues.py b/github/manage_issues.py index 631c32c..d9eb583 100755 --- a/github/manage_issues.py +++ b/github/manage_issues.py @@ -1,11 +1,10 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # PYTHON_ARGCOMPLETE_OK # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. -"""Perform actions based on frost results""" +"""Perform actions based on frost results.""" import argparse import json @@ -75,19 +74,16 @@ class Action: def parse_action_string(name: str) -> Optional[Sequence[str]]: - """ - comment - """ + """comment.""" matches = SPEC_DECODER_RE.match(name) return matches.groups() if matches else None def infer_resource_type(path: str) -> str: - """infer object type + """infer object type. - This relies on the file system structure of the tests - We currently assume it is: - "github/" resource_type "/.*" + This relies on the file system structure of the tests We currently + assume it is: "github/" resource_type "/.*" """ prefix = "github/" start = path.find(prefix) + len(prefix) @@ -98,7 +94,7 @@ def infer_resource_type(path: str) -> str: def create_branch_action(action_spec: dict) -> Action: """Parse pytest info into information needed to open an issue against a - specific branch""" + specific branch.""" # most information comes from the (parametrized) name of the test test_info = action_spec["name"] @@ -142,9 +138,7 @@ def get_status(action_spec: dict) -> Tuple[str, str]: def create_org_action(action_spec: dict) -> Action: - """ - Break out the org info from the json - """ + """Break out the org info from the json.""" # TODO check for outcome of xfailed (means exemption no longer needed) # most information comes from the (parametrized) name of the test test_info = action_spec["name"] @@ -180,7 +174,7 @@ def create_action_spec(action_spec: dict) -> Action: def _open_issue(action: Action) -> bool: - """ Report status via a GitHub issue + """Report status via a GitHub issue. Used for actions which relate to a specific repository TODO support grouping actions for same main issue. @@ -199,7 +193,7 @@ def _open_issue(action: Action) -> bool: def _alert_owners(action: Action) -> bool: - """ Contact org owners + """Contact org owners. Unsure how to do this - may be slack or email to secops. There is no good native way in GitHub. @@ -224,7 +218,7 @@ def _alert_owners(action: Action) -> bool: def perform_action(action: Action) -> bool: - """ Initiate the appropriate action + """Initiate the appropriate action. Args: action (Action): All the data needed to perform the action @@ -251,7 +245,7 @@ def parse_args(): logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s") args = parse_args() - with open(args.json_file, "r") as jf: + with open(args.json_file) as jf: pytest_report = json.loads(jf.read()) issue_actions = pytest_report["report"]["tests"] diff --git a/github/orgs/__init__.py b/github/orgs/__init__.py index 8b13789..e69de29 100644 --- a/github/orgs/__init__.py +++ b/github/orgs/__init__.py @@ -1 +0,0 @@ - diff --git a/github/orgs/test_two_factor_required.py b/github/orgs/test_two_factor_required.py index c24b25e..2bd545f 100755 --- a/github/orgs/test_two_factor_required.py +++ b/github/orgs/test_two_factor_required.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/github/orgs/validate_compliance.py b/github/orgs/validate_compliance.py index 66973c8..d9b33dd 100644 --- a/github/orgs/validate_compliance.py +++ b/github/orgs/validate_compliance.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -19,8 +18,7 @@ class Criteria: @staticmethod def idfn(val: Any) -> Optional[str]: - """ provide ID for pytest Parametrization - """ + """provide ID for pytest Parametrization.""" if isinstance(val, (Criteria,)): return f"{val.standard_number}-{val.slug}" return None @@ -51,10 +49,7 @@ def meets_criteria(org_info: OrgInfo, criteria: Criteria) -> bool: def validate_org_info(data: OrgInfo, criteria: Criteria) -> Tuple[bool, str]: - """ - Validate the protections - - """ + """Validate the protections.""" results = [] diff --git a/github/vscode-debug-wrapper.py b/github/vscode-debug-wrapper.py index 7290e44..ffb9745 100755 --- a/github/vscode-debug-wrapper.py +++ b/github/vscode-debug-wrapper.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/heroku/client.py b/heroku/client.py index 47ae650..ad12d39 100644 --- a/heroku/client.py +++ b/heroku/client.py @@ -20,7 +20,7 @@ def cache_key(organization, method, *args, **kwargs): str(organization), str(method), ",".join(args), - ",".join("{}={}".format(k, v) for (k, v) in kwargs.items()), + ",".join(f"{k}={v}" for (k, v) in kwargs.items()), ] ) + ".json" @@ -37,8 +37,7 @@ def get_heroku_resource( debug_calls=False, debug_cache=False, ): - """ - Fetches and return final data + """Fetches and return final data. TODO: more refactoring of herokuadmintools needed, so can: - cache all members @@ -126,7 +125,7 @@ def find_affected_apps(self): return self.extract_key(HerokuDataSets.APP_USER, {}) def values(self): - """Returns the wrapped value + """Returns the wrapped value. >>> c = HerokuAdminClient([None], None, None, None, offline=True) >>> c.results = [] @@ -136,9 +135,8 @@ def values(self): return self.results def extract_key(self, key, default=None): - """ - From an iterable of dicts returns the value with the given - keys discarding other values: + """From an iterable of dicts returns the value with the given keys + discarding other values: >>> c = HerokuAdminClient([None], None, None, None, offline=True) >>> c.results = [{'id': 1}, {'id': 2}] @@ -171,8 +169,7 @@ def extract_key(self, key, default=None): return self def flatten(self): - """ - Flattens one level of a nested list: + """Flattens one level of a nested list: >>> c = HerokuAdminClient([None], None, None, None, offline=True) >>> c.results = [['A', 1], ['B']] diff --git a/service_report_generator.py b/service_report_generator.py index 680ed84..a5095e8 100644 --- a/service_report_generator.py +++ b/service_report_generator.py @@ -1,5 +1,5 @@ -""" -Transform results and metadata from a pytest report JSON output and writes Service JSON reports. +"""Transform results and metadata from a pytest report JSON output and writes +Service JSON reports. Pytest Service JSON format: @@ -45,7 +45,6 @@ ... ] } - """ import json @@ -153,7 +152,7 @@ def pytest_json_to_service_json(pytest_json): if __name__ == "__main__": args = parse_args() - pytest_json = json.load(open(args.pytest_json, "r")) + pytest_json = json.load(open(args.pytest_json)) service_json = pytest_json_to_service_json(pytest_json) diff --git a/setup.py b/setup.py index 37cf1ab..956b925 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import setuptools -with open("README.md", "r") as fh: +with open("README.md") as fh: long_description = fh.read() setuptools.setup(