From cdd7c69730af2cb3a8225e75facc3456cd375dfb Mon Sep 17 00:00:00 2001 From: Kyle Hornberg Date: Mon, 13 Apr 2020 16:29:41 -0500 Subject: [PATCH] Refactor and restyle --- pyproject.toml | 16 +++++ setup.cfg | 6 -- setup.py | 8 +-- src/octokit/__init__.py | 52 ++++---------- src/octokit/base.py | 59 ++++------------ src/octokit/utils.py | 8 +-- src/octokit/webhook.py | 8 +-- tests/test_auth.py | 45 +++--------- tests/test_methods.py | 147 +++++++++------------------------------ tests/test_validation.py | 48 +++---------- tests/test_webhook.py | 29 ++------ 11 files changed, 105 insertions(+), 321 deletions(-) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a4840f4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[tool.black] +line-length = 120 +target-version = ['py36'] + +[tool.isort] +force_single_line = true +line_length = 120 +known_first_party = 'octokit.py' +default_section = 'THIRDPARTY' +forced_separate = 'test_octokit.py' +not_skip = '__init__.py' +skip = 'migrations' +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true diff --git a/setup.cfg b/setup.cfg index 3dc0b7f..2a4b28c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,9 +29,3 @@ default_section = THIRDPARTY forced_separate = test_octokit.py not_skip = __init__.py skip = migrations - -[yapf] -based_on_style = facebook -COLUMN_LIMIT = 120 -BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF = true -ALLOW_SPLIT_BEFORE_DICT_VALUE = false diff --git a/setup.py b/setup.py index c1e6296..6574b0c 100644 --- a/setup.py +++ b/setup.py @@ -16,9 +16,7 @@ from setuptools import setup def read(*names, **kwargs): - return io.open( - join(dirname(__file__), *names), encoding=kwargs.get("encoding", "utf8") - ).read() + return io.open(join(dirname(__file__), *names), encoding=kwargs.get("encoding", "utf8")).read() setup( @@ -28,9 +26,7 @@ setup( description="Python client for GitHub API", long_description="%s\n%s" % ( - re.compile("^.. start-badges.*^.. end-badges", re.M | re.S).sub( - "", read("README.rst") - ), + re.compile("^.. start-badges.*^.. end-badges", re.M | re.S).sub("", read("README.rst")), re.sub(":[a-z]+:`~?(.*?)`", r"``\1``", read("CHANGELOG.rst")), ), author="Kyle Hornberg", diff --git a/src/octokit/__init__.py b/src/octokit/__init__.py index f8e68a2..44707f7 100644 --- a/src/octokit/__init__.py +++ b/src/octokit/__init__.py @@ -27,13 +27,7 @@ class Octokit(Base): class_attributes = defaultdict(dict) for path, path_object in definitions["paths"].items(): for method, method_object in path_object.items(): - cls_name, method_id_name = self._get_names_from_operation_id( - method_object - ) - method_name = utils.snake_case(str(method_object.get("summary"))) - methods = self._get_class_methods( - method_id_name, method_name, method_object, method, path - ) + cls_name, methods = self._get_class_methods(method_object, method, path) class_attributes[cls_name].update(methods) return class_attributes @@ -72,39 +66,27 @@ class Octokit(Base): if method_object.get("x-changes"): for change in method_object["x-changes"]: if change.get("type") == "operation": - before_cls, before_name = self._get_names_from_operation_id( - change.get("before") - ) - after_cls, after_name = self._get_names_from_operation_id( - change.get("after") - ) + before_cls, before_name = self._get_names_from_operation_id(change.get("before")) + after_cls, after_name = self._get_names_from_operation_id(change.get("after")) if before_cls == after_cls and methods.get(after_name): deprecated_methods.update({before_name: methods[after_name]}) return deprecated_methods - def _get_class_methods( - self, method_id_name, method_name, method_object, method, path - ): + def _get_class_methods(self, method_object, method, path): + cls_name, method_id_name = self._get_names_from_operation_id(method_object) + method_name = utils.snake_case(str(method_object.get("summary"))) methods = { - method_id_name: self._create_method( - method_id_name, method_object, method, path - ), + method_id_name: self._create_method(method_id_name, method_object, method, path), method_name: self._create_method(method_name, method_object, method, path), } methods.update(self._get_deprecated_methods(methods, method_object)) - return methods + return cls_name, methods def _convert_to_object(self, item): if isinstance(item, dict): - return type( - "ResponseData", - (object,), - {k: self._convert_to_object(v) for k, v in item.items()}, - ) + return type("ResponseData", (object,), {k: self._convert_to_object(v) for k, v in item.items()}) if isinstance(item, list): - return list( - (self._convert_to_object(value) for index, value in enumerate(item)) - ) + return list((self._convert_to_object(value) for index, value in enumerate(item))) else: return item @@ -116,15 +98,9 @@ class Octokit(Base): if matches: for page, kind in matches: setattr(obj, "{}_page".format(kind), int(page)) - setattr( - obj, "pages", getattr(obj, "last_page", previous_page_requested) - ) + setattr(obj, "pages", getattr(obj, "last_page", previous_page_requested)) setattr(obj, "has_pages", True) - setattr( - obj, - "current_page", - previous_page_requested or getattr(obj, "next_page") - 1, - ) + setattr(obj, "current_page", previous_page_requested or getattr(obj, "next_page") - 1) setattr(obj, "is_last_page", obj.pages == obj.current_page) else: setattr(obj, "has_pages", False) @@ -135,7 +111,5 @@ class Octokit(Base): yield response.json if hasattr(response, "is_last_page"): while not response.is_last_page: - response = self.set_pages( - obj(page=response.next_page, **kwargs), response.next_page - ) + response = self.set_pages(obj(page=response.next_page, **kwargs), response.next_page) yield response.json diff --git a/src/octokit/base.py b/src/octokit/base.py index 035750b..92314ca 100644 --- a/src/octokit/base.py +++ b/src/octokit/base.py @@ -15,10 +15,7 @@ class Base(object): base_url = "https://api.github.com" def __init__(self): - self.headers = { - "accept": "application/vnd.github.v3+json", - "Content-Type": "application/json", - } + self.headers = {"accept": "application/vnd.github.v3+json", "Content-Type": "application/json"} self._attribute_cache = defaultdict(dict) def _get_headers(self, method_headers): @@ -30,17 +27,13 @@ class Base(object): return required_params def validate(self, parameters, definition): - self.validate_required_parameters( - parameters, self.get_required_parameters(definition) - ) + self.validate_required_parameters(parameters, self.get_required_parameters(definition)) schema = {} if definition.get("requestBody"): schema = definition["requestBody"]["content"]["application/json"]["schema"] self.validate_schema(parameters, schema) properties = schema.get("properties", {}) - valid_parameters = [p["name"] for p in definition.get("parameters")] + list( - properties.keys() - ) + valid_parameters = [p["name"] for p in definition.get("parameters")] + list(properties.keys()) self.validate_other_parameters(parameters, valid_parameters, properties) return True @@ -55,9 +48,7 @@ class Base(object): self.validate_enum(parameter, value, properties) def validate_enum(self, parameter, value, properties): - if properties.get(parameter).get("enum") and value not in properties.get( - parameter - ).get("enum"): + if properties.get(parameter).get("enum") and value not in properties.get(parameter).get("enum"): message = "{} is not a valid option for {}; must be one of {}".format( value, parameter, properties.get(parameter).get("enum") ) @@ -68,9 +59,7 @@ class Base(object): self.validate_list(parameters, schema) if isinstance(parameters, dict): self.validate_dict(parameters, schema) - self.validate_required_parameters( - parameters, self.get_required_schema_properties(schema) - ) + self.validate_required_parameters(parameters, self.get_required_schema_properties(schema)) self.type_match(parameters, schema.get("type")) def validate_dict(self, parameters, schema): @@ -99,11 +88,7 @@ class Base(object): return schema.get("required") def get_required_parameters(self, definition): - return [ - p.get("name") - for p in definition.get("parameters") - if p.get("required") and p.get("in") in ["path"] - ] + return [p.get("name") for p in definition.get("parameters") if p.get("required") and p.get("in") in ["path"]] def validate_required_parameters(self, parameters, required_parameters): for required_parameter in required_parameters or []: @@ -145,9 +130,7 @@ class Base(object): data = {} if parameter.get("in") in ["query", "body"] and not kwargs.get(parameter_name): if parameter.get("schema", parameter).get("default") is not None: - data[parameter_name] = self._get_parameter_for_type( - parameter.get("schema", parameter) - ) + data[parameter_name] = self._get_parameter_for_type(parameter.get("schema", parameter)) return data def _get_array_data(self, parameter_name, parameter, kwargs): @@ -199,9 +182,7 @@ class Base(object): def _setup_installation_authentication(self, kwargs): assert kwargs["app_id"] assert kwargs["private_key"] - self.token, self.expires_at = self._app_auth_get_token( - kwargs["app_id"], kwargs["private_key"] - ) + self.token, self.expires_at = self._app_auth_get_token(kwargs["app_id"], kwargs["private_key"]) self.auth = kwargs["auth"] self.headers["accept"] = "application/vnd.github.machine-man-preview+json" @@ -219,12 +200,8 @@ class Base(object): } installation_url = "{}/app/installations".format(self.base_url) installations = requests.get(installation_url, headers=headers).json() - self.installation_id = [ - x.get("id") for x in installations if str(x.get("app_id")) == app_id - ].pop() - installation_token_url = "{}/installations/{}/access_tokens".format( - self.base_url, self.installation_id - ) + self.installation_id = [x.get("id") for x in installations if str(x.get("app_id")) == app_id].pop() + installation_token_url = "{}/installations/{}/access_tokens".format(self.base_url, self.installation_id) response = requests.post(installation_token_url, headers=headers).json() return response["token"], response["expires_at"] @@ -241,15 +218,9 @@ class Base(object): return {"auth": (self.username, self.password)} if getattr(self, "auth", None) in ["app", "token", "installation"]: _headers = { - "app": { - "Authorization": "Bearer {}".format(getattr(self, "jwt", None)) - }, - "token": { - "Authorization": "token {}".format(getattr(self, "token", None)) - }, - "installation": { - "Authorization": "token {}".format(getattr(self, "token", None)) - }, + "app": {"Authorization": "Bearer {}".format(getattr(self, "jwt", None))}, + "token": {"Authorization": "token {}".format(getattr(self, "token", None))}, + "installation": {"Authorization": "token {}".format(getattr(self, "token", None))}, } headers = requests_kwargs["headers"] headers.update(_headers.get(getattr(self, "auth", None))) @@ -259,9 +230,7 @@ class Base(object): def _get_parameters(self, definition, method): p = {} if definition.get("requestBody"): - schema = definition.get("requestBody")["content"]["application/json"][ - "schema" - ] + schema = definition.get("requestBody")["content"]["application/json"]["schema"] if schema["type"] == "object": body_parameters = {} for k, v in schema["properties"].items(): diff --git a/src/octokit/utils.py b/src/octokit/utils.py index dbedb3b..f577af0 100644 --- a/src/octokit/utils.py +++ b/src/octokit/utils.py @@ -5,13 +5,7 @@ import re def snake_case(string): # From https://gist.github.com/jaytaylor/3660565#gistcomment-2271689 - return ( - re.compile(r"(?!^)(?