From b5f22247ee4a87626817630aef2784457a5cd803 Mon Sep 17 00:00:00 2001 From: Derek Visch Date: Thu, 11 Nov 2021 16:34:04 -0500 Subject: [PATCH 1/7] Almost there --- meltano.yml | 2 +- pyproject.toml | 3 +++ tap_clickup/client.py | 18 ++++++++++++++++++ tap_clickup/streams.py | 20 +++++++++++++++++++- tap_clickup/tests/test_core.py | 1 - 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/meltano.yml b/meltano.yml index 6ae4841..7ca070d 100644 --- a/meltano.yml +++ b/meltano.yml @@ -15,7 +15,7 @@ plugins: - name: api_token kind: password select: - - '*.*' + - 'space.*' config: start_date: '2010-01-01T00:00:00Z' loaders: diff --git a/pyproject.toml b/pyproject.toml index 0c5c25e..267889d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,9 @@ tox = "^3.23.1" codecov = "^2.1.11" pylint = "2.10.2" +[tool.pytest.ini_options] +log_cli = 1 + [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" diff --git a/tap_clickup/client.py b/tap_clickup/client.py index 58bd785..b41e1b8 100644 --- a/tap_clickup/client.py +++ b/tap_clickup/client.py @@ -114,3 +114,21 @@ def _request_with_backoff( def parse_response(self, response: requests.Response) -> Iterable[dict]: """Parse the response and return an iterator of result rows.""" yield from extract_jsonpath(self.records_jsonpath, input=response.json()) + + def from_parent_context(self, context: dict): + """Default is to return the dict passed in""" + if(self.partitions is None): return context + else: + #Was going to copy the partitions, but the _sync call, forces us + #To use partitions, instead of being able to provide a list of contexts + #Ideally we wouldn't mutate partitions here, and we'd just provide + #A copy of partitions with context merged so we don't have side effects + for partition in self.partitions: + partition.update(context.copy()) #Add copy of context to partition + return None #Context now handled at the partition level + + def _sync_children(self, child_context: dict) -> None: + for child_stream in self.child_streams: + if child_stream.selected or child_stream.has_selected_descendents: + child_stream.sync(child_stream.from_parent_context(context=child_context)) + diff --git a/tap_clickup/streams.py b/tap_clickup/streams.py index faf6af0..24689ed 100644 --- a/tap_clickup/streams.py +++ b/tap_clickup/streams.py @@ -1,6 +1,6 @@ """Stream type classes for tap-clickup.""" from pathlib import Path -from typing import Optional, Any, Dict, cast +from typing import Optional, Any, Dict, cast, Iterable import datetime import pendulum import requests @@ -39,6 +39,8 @@ class SpacesStream(ClickUpStream): schema_filepath = SCHEMAS_DIR / "space.json" records_jsonpath = "$.spaces[*]" parent_stream_type = TeamsStream + partitions = [{"archived":"yep"},{"archived":"nope"}] + def get_child_context(self, record: dict, context: Optional[dict]) -> dict: """Return a context dictionary for child streams.""" @@ -46,6 +48,22 @@ def get_child_context(self, record: dict, context: Optional[dict]) -> dict: "space_id": record["id"], } + + def get_records(self, context: Optional[dict]) -> Iterable[Dict[str, Any]]: + """Return a generator of row-type dictionary objects. + + Each row emitted should be a dictionary of property names to their values. + + Args: + context: Stream partition or context dictionary. + + Yields: + One item per (possibly processed) record in the API. + """ + self.logger.info(f"CONTEXT: {context}") + for row in self.request_records(context): + row = self.post_process(row, context) + yield row class FoldersStream(ClickUpStream): """Folders""" diff --git a/tap_clickup/tests/test_core.py b/tap_clickup/tests/test_core.py index 239aac7..35e28ac 100644 --- a/tap_clickup/tests/test_core.py +++ b/tap_clickup/tests/test_core.py @@ -10,7 +10,6 @@ SAMPLE_CONFIG = { "start_date": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d"), "api_token": os.environ["TAP_CLICKUP_API_TOKEN"], - "team_ids": os.environ["TAP_CLICKUP_TEAM_IDS"], } From c544f7a441a6223c90d77332d21d447e84fba92b Mon Sep 17 00:00:00 2001 From: Derek Visch Date: Fri, 12 Nov 2021 13:50:07 -0500 Subject: [PATCH 2/7] Added Parent Child Partitioning for Tasks, and all streams with archived/unarchived needs --- meltano.yml | 2 +- tap_clickup/client.py | 18 ++++++- tap_clickup/streams.py | 108 ++++++----------------------------------- tap_clickup/tap.py | 10 +--- 4 files changed, 36 insertions(+), 102 deletions(-) diff --git a/meltano.yml b/meltano.yml index 7ca070d..6ae4841 100644 --- a/meltano.yml +++ b/meltano.yml @@ -15,7 +15,7 @@ plugins: - name: api_token kind: password select: - - 'space.*' + - '*.*' config: start_date: '2010-01-01T00:00:00Z' loaders: diff --git a/tap_clickup/client.py b/tap_clickup/client.py index b41e1b8..cc15eaa 100644 --- a/tap_clickup/client.py +++ b/tap_clickup/client.py @@ -1,6 +1,6 @@ """REST client handling, including ClickUpStream base class.""" -from typing import Any, Optional, Iterable, cast +from typing import Any, Optional, Iterable, cast, Dict from pathlib import Path from datetime import datetime import time @@ -19,6 +19,22 @@ class ClickUpStream(RESTStream): url_base = "https://api.clickup.com/api/v2" records_jsonpath = "$[*]" # Or override `parse_response`. next_page_token_jsonpath = "$.next_page" # Or override `get_next_page_token`. + + def get_url_params( + self, context: Optional[dict], next_page_token: Optional[Any] + ) -> Dict[str, Any]: + """Return a dictionary of values to be used in URL parameterization.""" + params: dict = {} + if context: + params["archived"] = context.get("archived") + # Replication key specefic to tasks + if self.replication_key: + params["order_by"] = "updated" + params["reverse"] = "true" + params["date_updated_gt"] = self.initial_replication_key( + context + ) # Actually greater than or equal to + return params @property def http_headers(self) -> dict: diff --git a/tap_clickup/streams.py b/tap_clickup/streams.py index 24689ed..c4994dd 100644 --- a/tap_clickup/streams.py +++ b/tap_clickup/streams.py @@ -39,7 +39,7 @@ class SpacesStream(ClickUpStream): schema_filepath = SCHEMAS_DIR / "space.json" records_jsonpath = "$.spaces[*]" parent_stream_type = TeamsStream - partitions = [{"archived":"yep"},{"archived":"nope"}] + partitions = [{"archived":"true"},{"archived":"false"}] def get_child_context(self, record: dict, context: Optional[dict]) -> dict: @@ -48,23 +48,6 @@ def get_child_context(self, record: dict, context: Optional[dict]) -> dict: "space_id": record["id"], } - - def get_records(self, context: Optional[dict]) -> Iterable[Dict[str, Any]]: - """Return a generator of row-type dictionary objects. - - Each row emitted should be a dictionary of property names to their values. - - Args: - context: Stream partition or context dictionary. - - Yields: - One item per (possibly processed) record in the API. - """ - self.logger.info(f"CONTEXT: {context}") - for row in self.request_records(context): - row = self.post_process(row, context) - yield row - class FoldersStream(ClickUpStream): """Folders""" @@ -75,6 +58,7 @@ class FoldersStream(ClickUpStream): schema_filepath = SCHEMAS_DIR / "folder.json" records_jsonpath = "$.folders[*]" parent_stream_type = SpacesStream + partitions = [{"archived":"true"},{"archived":"false"}] def get_child_context(self, record: dict, context: Optional[dict]) -> dict: """Return a context dictionary for child streams.""" @@ -93,6 +77,7 @@ class FolderListsStream(ClickUpStream): schema_filepath = SCHEMAS_DIR / "list.json" records_jsonpath = "$.lists[*]" parent_stream_type = FoldersStream + partitions = [{"archived":"true"},{"archived":"false"}] def get_child_context(self, record: dict, context: Optional[dict]) -> dict: """Return a context dictionary for child streams.""" @@ -111,6 +96,7 @@ class FolderlessListsStream(ClickUpStream): schema_filepath = SCHEMAS_DIR / "list.json" records_jsonpath = "$.lists[*]" parent_stream_type = SpacesStream + partitions = [{"archived":"true"},{"archived":"false"}] def get_child_context(self, record: dict, context: Optional[dict]) -> dict: """Return a context dictionary for child streams.""" @@ -190,9 +176,19 @@ class FolderCustomFieldsStream(ClickUpStream): records_jsonpath = "$.fields[*]" parent_stream_type = FolderListsStream +class TasksStream(ClickUpStream): + """Tasks Stream""" -class ClickUpTasksStream(ClickUpStream): - """Parent Class for Task Streams""" + name = "task" + path = "/team/{team_id}/task?include_closed=true&subtasks=true" + primary_keys = ["id"] + replication_key = "date_updated" + is_sorted = True + ignore_parent_replication_key = True + schema_filepath = SCHEMAS_DIR / "task.json" + records_jsonpath = "$.tasks[*]" + parent_stream_type = TeamsStream + partitions = [{"archived":"true"},{"archived":"false"}] initial_replication_key_dict = {} @@ -255,75 +251,3 @@ def get_next_page_token( newtoken = None return newtoken - - def get_url_params( - self, context: Optional[dict], next_page_token: Optional[Any] - ) -> Dict[str, Any]: - """Return a dictionary of values to be used in URL parameterization.""" - params: dict = {} - if next_page_token: - params["page"] = next_page_token - - # Replication key specefic to tasks - if self.replication_key: - params["order_by"] = "updated" - params["reverse"] = "true" - params["date_updated_gt"] = self.initial_replication_key( - context - ) # Actually greater than or equal to - return params - - -class FolderlessTasksStream(ClickUpTasksStream): - """Tasks can come from lists not under folders""" - - name = "folderless_task" - path = "/list/{list_id}/task?include_closed=true&subtasks=true" - primary_keys = ["id"] - replication_key = "date_updated" - is_sorted = True - ignore_parent_replication_key = True - schema_filepath = SCHEMAS_DIR / "task.json" - records_jsonpath = "$.tasks[*]" - parent_stream_type = FolderlessListsStream - - -class FolderlessTasksArchivedStream(ClickUpTasksStream): - """ - Tasks can come from lists not under folders, - archived only pulls archived tasks - """ - - name = "folderless_task_archived" - path = "/list/{list_id}/task?include_closed=true&subtasks=true&archived=true" - primary_keys = ["id"] - replication_key = "date_updated" - is_sorted = True - ignore_parent_replication_key = True - schema_filepath = SCHEMAS_DIR / "task.json" - records_jsonpath = "$.tasks[*]" - parent_stream_type = FolderlessListsStream - - -class FolderTasksStream(ClickUpTasksStream): - """Tasks can come from under Folders""" - - name = "folder_task" - path = "/list/{list_id}/task?include_closed=true&subtasks=true" - primary_keys = ["id"] - replication_key = "date_updated" - schema_filepath = SCHEMAS_DIR / "task.json" - records_jsonpath = "$.tasks[*]" - parent_stream_type = FolderListsStream - - -class FolderTasksArchivedStream(ClickUpTasksStream): - """Tasks can come from under Folders, archived only pulls archived tasks""" - - name = "folder_task_archived" - path = "/list/{list_id}/task?include_closed=true&subtasks=true&archived=true" - primary_keys = ["id"] - replication_key = "date_updated" - schema_filepath = SCHEMAS_DIR / "task.json" - records_jsonpath = "$.tasks[*]" - parent_stream_type = FolderListsStream diff --git a/tap_clickup/tap.py b/tap_clickup/tap.py index c110e6c..b8e375f 100644 --- a/tap_clickup/tap.py +++ b/tap_clickup/tap.py @@ -15,12 +15,9 @@ GoalsStream, TagsStream, SharedHierarchyStream, - FolderTasksStream, - FolderlessTasksStream, + TasksStream, FolderCustomFieldsStream, FolderlessCustomFieldsStream, - FolderlessTasksArchivedStream, - FolderTasksArchivedStream, ) STREAM_TYPES = [ @@ -33,12 +30,9 @@ GoalsStream, TagsStream, SharedHierarchyStream, - FolderTasksStream, - FolderlessTasksStream, + TasksStream, FolderCustomFieldsStream, FolderlessCustomFieldsStream, - FolderlessTasksArchivedStream, - FolderTasksArchivedStream, ] From dcda3f265166259c5ad63a91755493a69d761687 Mon Sep 17 00:00:00 2001 From: Derek Visch Date: Fri, 12 Nov 2021 14:13:21 -0500 Subject: [PATCH 3/7] Have all streams but tasks working properly --- poetry.lock | 255 ++++++++++++++++++++++------------------- pyproject.toml | 2 +- tap_clickup/client.py | 5 +- tap_clickup/streams.py | 48 ++------ 4 files changed, 154 insertions(+), 156 deletions(-) diff --git a/poetry.lock b/poetry.lock index 11fc216..3da9a01 100644 --- a/poetry.lock +++ b/poetry.lock @@ -52,7 +52,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "backports.entry-points-selectable" -version = "1.1.0" +version = "1.1.1" description = "Compatibility shim providing selectable entry points for older implementations" category = "dev" optional = false @@ -63,7 +63,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"] +testing = ["pytest", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"] [[package]] name = "black" @@ -160,7 +160,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "6.0.2" +version = "6.1.2" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -192,7 +192,7 @@ test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pret name = "dataclasses" version = "0.8" description = "A backport of the dataclasses module for Python 3.6" -category = "dev" +category = "main" optional = false python-versions = ">=3.6, <3.7" @@ -214,7 +214,7 @@ python-versions = "*" [[package]] name = "filelock" -version = "3.3.0" +version = "3.3.2" description = "A platform independent file lock." category = "dev" optional = false @@ -248,7 +248,7 @@ python-versions = ">=3.5" [[package]] name = "importlib-metadata" -version = "4.8.1" +version = "4.8.2" description = "Read metadata from Python packages" category = "main" optional = false @@ -261,11 +261,11 @@ zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] [[package]] name = "importlib-resources" -version = "5.2.2" +version = "5.4.0" description = "Read resources from Python packages" category = "dev" optional = false @@ -276,7 +276,7 @@ zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] [[package]] name = "inflection" @@ -296,7 +296,7 @@ python-versions = "*" [[package]] name = "isort" -version = "5.9.3" +version = "5.10.1" description = "A Python utility / library to sort Python imports." category = "dev" optional = false @@ -381,14 +381,14 @@ python-versions = "*" [[package]] name = "packaging" -version = "21.0" +version = "21.2" description = "Core utilities for Python packages" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] -pyparsing = ">=2.0.2" +pyparsing = ">=2.0.2,<3" [[package]] name = "pathspec" @@ -466,11 +466,11 @@ python-versions = "*" [[package]] name = "py" -version = "1.10.0" +version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pycodestyle" @@ -482,7 +482,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pycparser" -version = "2.20" +version = "2.21" description = "C parser in Python" category = "main" optional = false @@ -592,7 +592,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "regex" -version = "2021.10.8" +version = "2021.11.10" description = "Alternative regular expression module, to replace re." category = "dev" optional = false @@ -626,7 +626,7 @@ python-versions = "*" [[package]] name = "singer-sdk" -version = "0.3.11" +version = "0.3.13" description = "A framework for building Singer taps" category = "main" optional = false @@ -636,6 +636,7 @@ python-versions = ">=3.6.2,<3.10" backoff = ">=1.8.0,<2.0" click = ">=8.0,<9.0" cryptography = ">=3.4.6,<4.0.0" +dataclasses = {version = "*", markers = "python_version < \"3.7\""} importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} inflection = ">=0.5.1,<0.6.0" joblib = ">=1.0.1,<2.0.0" @@ -719,7 +720,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.8.1" +version = "20.10.0" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -728,14 +729,14 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] "backports.entry-points-selectable" = ">=1.0.4" distlib = ">=0.3.1,<1" -filelock = ">=3.0.0,<4" +filelock = ">=3.2,<4" importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} importlib-resources = {version = ">=1.0", markers = "python_version < \"3.7\""} platformdirs = ">=2,<3" six = ">=1.9.0,<2" [package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] [[package]] @@ -761,7 +762,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "<3.10,>=3.6.2" -content-hash = "f2251444ae496664116f193874d4a9a8b681e46d8cdf4a0d0b447d4f93fef410" +content-hash = "746dd4dec9472856c6c49c03d532365c8bd72dbabdfd4b8da55fb5b9109c2a65" [metadata.files] appdirs = [ @@ -785,8 +786,8 @@ backoff = [ {file = "backoff-1.8.0.tar.gz", hash = "sha256:c7187f15339e775aec926dc6e5e42f8a3ad7d3c2b9a6ecae7b535000f70cd838"}, ] "backports.entry-points-selectable" = [ - {file = "backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl", hash = "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc"}, - {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"}, + {file = "backports.entry_points_selectable-1.1.1-py2.py3-none-any.whl", hash = "sha256:7fceed9532a7aa2bd888654a7314f864a3c16a4e710b34a58cfc0f08114c663b"}, + {file = "backports.entry_points_selectable-1.1.1.tar.gz", hash = "sha256:914b21a479fde881635f7af5adc7f6e38d6b274be32269070c53b698c60d5386"}, ] black = [ {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"}, @@ -868,39 +869,53 @@ colorama = [ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] coverage = [ - {file = "coverage-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1549e1d08ce38259de2bc3e9a0d5f3642ff4a8f500ffc1b2df73fd621a6cdfc0"}, - {file = "coverage-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcae10fccb27ca2a5f456bf64d84110a5a74144be3136a5e598f9d9fb48c0caa"}, - {file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:53a294dc53cfb39c74758edaa6305193fb4258a30b1f6af24b360a6c8bd0ffa7"}, - {file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8251b37be1f2cd9c0e5ccd9ae0380909c24d2a5ed2162a41fcdbafaf59a85ebd"}, - {file = "coverage-6.0.2-cp310-cp310-win32.whl", hash = "sha256:db42baa892cba723326284490283a68d4de516bfb5aaba369b4e3b2787a778b7"}, - {file = "coverage-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:bbffde2a68398682623d9dd8c0ca3f46fda074709b26fcf08ae7a4c431a6ab2d"}, - {file = "coverage-6.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:60e51a3dd55540bec686d7fff61b05048ca31e804c1f32cbb44533e6372d9cc3"}, - {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a6a9409223a27d5ef3cca57dd7cd4dfcb64aadf2fad5c3b787830ac9223e01a"}, - {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4b34ae4f51bbfa5f96b758b55a163d502be3dcb24f505d0227858c2b3f94f5b9"}, - {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3bbda1b550e70fa6ac40533d3f23acd4f4e9cb4e6e77251ce77fdf41b3309fb2"}, - {file = "coverage-6.0.2-cp36-cp36m-win32.whl", hash = "sha256:4e28d2a195c533b58fc94a12826f4431726d8eb029ac21d874345f943530c122"}, - {file = "coverage-6.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a82d79586a0a4f5fd1cf153e647464ced402938fbccb3ffc358c7babd4da1dd9"}, - {file = "coverage-6.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3be1206dc09fb6298de3fce70593e27436862331a85daee36270b6d0e1c251c4"}, - {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cd3828bbe1a40070c11fe16a51df733fd2f0cb0d745fb83b7b5c1f05967df7"}, - {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d036dc1ed8e1388e995833c62325df3f996675779541f682677efc6af71e96cc"}, - {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04560539c19ec26995ecfb3d9307ff154fbb9a172cb57e3b3cfc4ced673103d1"}, - {file = "coverage-6.0.2-cp37-cp37m-win32.whl", hash = "sha256:e4fb7ced4d9dec77d6cf533acfbf8e1415fe799430366affb18d69ee8a3c6330"}, - {file = "coverage-6.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:77b1da5767ed2f44611bc9bc019bc93c03fa495728ec389759b6e9e5039ac6b1"}, - {file = "coverage-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:61b598cbdbaae22d9e34e3f675997194342f866bb1d781da5d0be54783dce1ff"}, - {file = "coverage-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36e9040a43d2017f2787b28d365a4bb33fcd792c7ff46a047a04094dc0e2a30d"}, - {file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9f1627e162e3864a596486774876415a7410021f4b67fd2d9efdf93ade681afc"}, - {file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e7a0b42db2a47ecb488cde14e0f6c7679a2c5a9f44814393b162ff6397fcdfbb"}, - {file = "coverage-6.0.2-cp38-cp38-win32.whl", hash = "sha256:a1b73c7c4d2a42b9d37dd43199c5711d91424ff3c6c22681bc132db4a4afec6f"}, - {file = "coverage-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:1db67c497688fd4ba85b373b37cc52c50d437fd7267520ecd77bddbd89ea22c9"}, - {file = "coverage-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f184bf38e74f152eed7f87e345b51f3ab0b703842f447c22efe35e59942c24"}, - {file = "coverage-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1cf1deb3d5544bd942356364a2fdc8959bad2b6cf6eb17f47d301ea34ae822"}, - {file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad9b8c1206ae41d46ec7380b78ba735ebb77758a650643e841dd3894966c31d0"}, - {file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:381d773d896cc7f8ba4ff3b92dee4ed740fb88dfe33b6e42efc5e8ab6dfa1cfe"}, - {file = "coverage-6.0.2-cp39-cp39-win32.whl", hash = "sha256:424c44f65e8be58b54e2b0bd1515e434b940679624b1b72726147cfc6a9fc7ce"}, - {file = "coverage-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:abbff240f77347d17306d3201e14431519bf64495648ca5a49571f988f88dee9"}, - {file = "coverage-6.0.2-pp36-none-any.whl", hash = "sha256:7092eab374346121805fb637572483270324407bf150c30a3b161fc0c4ca5164"}, - {file = "coverage-6.0.2-pp37-none-any.whl", hash = "sha256:30922626ce6f7a5a30bdba984ad21021529d3d05a68b4f71ea3b16bda35b8895"}, - {file = "coverage-6.0.2.tar.gz", hash = "sha256:6807947a09510dc31fa86f43595bf3a14017cd60bf633cc746d52141bfa6b149"}, + {file = "coverage-6.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:675adb3b3380967806b3cbb9c5b00ceb29b1c472692100a338730c1d3e59c8b9"}, + {file = "coverage-6.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95a58336aa111af54baa451c33266a8774780242cab3704b7698d5e514840758"}, + {file = "coverage-6.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d0a595a781f8e186580ff8e3352dd4953b1944289bec7705377c80c7e36c4d6c"}, + {file = "coverage-6.1.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d3c5f49ce6af61154060640ad3b3281dbc46e2e0ef2fe78414d7f8a324f0b649"}, + {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:310c40bed6b626fd1f463e5a83dba19a61c4eb74e1ac0d07d454ebbdf9047e9d"}, + {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a4d48e42e17d3de212f9af44f81ab73b9378a4b2b8413fd708d0d9023f2bbde4"}, + {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ffa545230ca2ad921ad066bf8fd627e7be43716b6e0fcf8e32af1b8188ccb0ab"}, + {file = "coverage-6.1.2-cp310-cp310-win32.whl", hash = "sha256:cd2d11a59afa5001ff28073ceca24ae4c506da4355aba30d1e7dd2bd0d2206dc"}, + {file = "coverage-6.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:96129e41405887a53a9cc564f960d7f853cc63d178f3a182fdd302e4cab2745b"}, + {file = "coverage-6.1.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1de9c6f5039ee2b1860b7bad2c7bc3651fbeb9368e4c4d93e98a76358cdcb052"}, + {file = "coverage-6.1.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:80cb70264e9a1d04b519cdba3cd0dc42847bf8e982a4d55c769b9b0ee7cdce1e"}, + {file = "coverage-6.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:ba6125d4e55c0b8e913dad27b22722eac7abdcb1f3eab1bd090eee9105660266"}, + {file = "coverage-6.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8492d37acdc07a6eac6489f6c1954026f2260a85a4c2bb1e343fe3d35f5ee21a"}, + {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66af99c7f7b64d050d37e795baadf515b4561124f25aae6e1baa482438ecc388"}, + {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ebcc03e1acef4ff44f37f3c61df478d6e469a573aa688e5a162f85d7e4c3860d"}, + {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d44a8136eebbf544ad91fef5bd2b20ef0c9b459c65a833c923d9aa4546b204"}, + {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c18725f3cffe96732ef96f3de1939d81215fd6d7d64900dcc4acfe514ea4fcbf"}, + {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c8e9c4bcaaaa932be581b3d8b88b677489975f845f7714efc8cce77568b6711c"}, + {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:06d009e8a29483cbc0520665bc46035ffe9ae0e7484a49f9782c2a716e37d0a0"}, + {file = "coverage-6.1.2-cp36-cp36m-win32.whl", hash = "sha256:e5432d9c329b11c27be45ee5f62cf20a33065d482c8dec1941d6670622a6fb8f"}, + {file = "coverage-6.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:82fdcb64bf08aa5db881db061d96db102c77397a570fbc112e21c48a4d9cb31b"}, + {file = "coverage-6.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:94f558f8555e79c48c422045f252ef41eb43becdd945e9c775b45ebfc0cbd78f"}, + {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:046647b96969fda1ae0605f61288635209dd69dcd27ba3ec0bf5148bc157f954"}, + {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cc799916b618ec9fd00135e576424165691fec4f70d7dc12cfaef09268a2478c"}, + {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:62646d98cf0381ffda301a816d6ac6c35fc97aa81b09c4c52d66a15c4bef9d7c"}, + {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:27a3df08a855522dfef8b8635f58bab81341b2fb5f447819bc252da3aa4cf44c"}, + {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:610c0ba11da8de3a753dc4b1f71894f9f9debfdde6559599f303286e70aeb0c2"}, + {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:35b246ae3a2c042dc8f410c94bcb9754b18179cdb81ff9477a9089dbc9ecc186"}, + {file = "coverage-6.1.2-cp37-cp37m-win32.whl", hash = "sha256:0cde7d9fe2fb55ff68ebe7fb319ef188e9b88e0a3d1c9c5db7dd829cd93d2193"}, + {file = "coverage-6.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:958ac66272ff20e63d818627216e3d7412fdf68a2d25787b89a5c6f1eb7fdd93"}, + {file = "coverage-6.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a300b39c3d5905686c75a369d2a66e68fd01472ea42e16b38c948bd02b29e5bd"}, + {file = "coverage-6.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d3855d5d26292539861f5ced2ed042fc2aa33a12f80e487053aed3bcb6ced13"}, + {file = "coverage-6.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:586d38dfc7da4a87f5816b203ff06dd7c1bb5b16211ccaa0e9788a8da2b93696"}, + {file = "coverage-6.1.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a34fccb45f7b2d890183a263578d60a392a1a218fdc12f5bce1477a6a68d4373"}, + {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bc1ee1318f703bc6c971da700d74466e9b86e0c443eb85983fb2a1bd20447263"}, + {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3f546f48d5d80a90a266769aa613bc0719cb3e9c2ef3529d53f463996dd15a9d"}, + {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd92ece726055e80d4e3f01fff3b91f54b18c9c357c48fcf6119e87e2461a091"}, + {file = "coverage-6.1.2-cp38-cp38-win32.whl", hash = "sha256:24ed38ec86754c4d5a706fbd5b52b057c3df87901a8610d7e5642a08ec07087e"}, + {file = "coverage-6.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:97ef6e9119bd39d60ef7b9cd5deea2b34869c9f0b9777450a7e3759c1ab09b9b"}, + {file = "coverage-6.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e5a8c947a2a89c56655ecbb789458a3a8e3b0cbf4c04250331df8f647b3de59"}, + {file = "coverage-6.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a39590d1e6acf6a3c435c5d233f72f5d43b585f5be834cff1f21fec4afda225"}, + {file = "coverage-6.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9d2c2e3ce7b8cc932a2f918186964bd44de8c84e2f9ef72dc616f5bb8be22e71"}, + {file = "coverage-6.1.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3348865798c077c695cae00da0924136bb5cc501f236cfd6b6d9f7a3c94e0ec4"}, + {file = "coverage-6.1.2-cp39-cp39-win32.whl", hash = "sha256:fae3fe111670e51f1ebbc475823899524e3459ea2db2cb88279bbfb2a0b8a3de"}, + {file = "coverage-6.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:af45eea024c0e3a25462fade161afab4f0d9d9e0d5a5d53e86149f74f0a35ecc"}, + {file = "coverage-6.1.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:eab14fdd410500dae50fd14ccc332e65543e7b39f6fc076fe90603a0e5d2f929"}, + {file = "coverage-6.1.2.tar.gz", hash = "sha256:d9a635114b88c0ab462e0355472d00a180a5fbfd8511e7f18e4ac32652e7d972"}, ] cryptography = [ {file = "cryptography-3.4.8-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14"}, @@ -909,6 +924,8 @@ cryptography = [ {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34dae04a0dce5730d8eb7894eab617d8a70d0c97da76b905de9efb7128ad7085"}, {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b"}, {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:9965c46c674ba8cc572bc09a03f4c649292ee73e1b683adb1ce81e82e9a6a0fb"}, + {file = "cryptography-3.4.8-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c4129fc3fdc0fa8e40861b5ac0c673315b3c902bbdc05fc176764815b43dd1d"}, + {file = "cryptography-3.4.8-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:695104a9223a7239d155d7627ad912953b540929ef97ae0c34c7b8bf30857e89"}, {file = "cryptography-3.4.8-cp36-abi3-win32.whl", hash = "sha256:21ca464b3a4b8d8e86ba0ee5045e103a1fcfac3b39319727bc0fc58c09c6aff7"}, {file = "cryptography-3.4.8-cp36-abi3-win_amd64.whl", hash = "sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc"}, {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d2a6e5ef66503da51d2110edf6c403dc6b494cc0082f85db12f54e9c5d4c3ec5"}, @@ -934,8 +951,8 @@ distlib = [ {file = "distlib-0.3.3.zip", hash = "sha256:d982d0751ff6eaaab5e2ec8e691d949ee80eddf01a62eaa96ddb11531fe16b05"}, ] filelock = [ - {file = "filelock-3.3.0-py3-none-any.whl", hash = "sha256:bbc6a0382fe8ec4744ecdf6683a2e07f65eb10ff1aff53fc02a202565446cde0"}, - {file = "filelock-3.3.0.tar.gz", hash = "sha256:8c7eab13dc442dc249e95158bcc12dec724465919bdc9831fdbf0660f03d1785"}, + {file = "filelock-3.3.2-py3-none-any.whl", hash = "sha256:bb2a1c717df74c48a2d00ed625e5a66f8572a3a30baacb7657add1d7bac4097b"}, + {file = "filelock-3.3.2.tar.gz", hash = "sha256:7afc856f74fa7006a289fd10fa840e1eebd8bbff6bffb69c26c54a0512ea8cf8"}, ] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, @@ -946,12 +963,12 @@ idna = [ {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, - {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, + {file = "importlib_metadata-4.8.2-py3-none-any.whl", hash = "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100"}, + {file = "importlib_metadata-4.8.2.tar.gz", hash = "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb"}, ] importlib-resources = [ - {file = "importlib_resources-5.2.2-py3-none-any.whl", hash = "sha256:2480d8e07d1890056cb53c96e3de44fead9c62f2ba949b0f2e4c4345f4afa977"}, - {file = "importlib_resources-5.2.2.tar.gz", hash = "sha256:a65882a4d0fe5fbf702273456ba2ce74fe44892c25e42e057aca526b702a6d4b"}, + {file = "importlib_resources-5.4.0-py3-none-any.whl", hash = "sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45"}, + {file = "importlib_resources-5.4.0.tar.gz", hash = "sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"}, ] inflection = [ {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, @@ -962,8 +979,8 @@ iniconfig = [ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] isort = [ - {file = "isort-5.9.3-py3-none-any.whl", hash = "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"}, - {file = "isort-5.9.3.tar.gz", hash = "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899"}, + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] joblib = [ {file = "joblib-1.1.0-py2.py3-none-any.whl", hash = "sha256:f21f109b3c7ff9d95f8387f752d0d9c34a02aa2f7060c2135f465da0e5160ff6"}, @@ -1015,8 +1032,8 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] packaging = [ - {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"}, - {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, + {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"}, + {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"}, ] pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, @@ -1062,16 +1079,16 @@ ply = [ {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, ] py = [ - {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, - {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pycodestyle = [ {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, ] pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pyflakes = [ {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, @@ -1129,47 +1146,55 @@ pytzdata = [ {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, ] regex = [ - {file = "regex-2021.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:981c786293a3115bc14c103086ae54e5ee50ca57f4c02ce7cf1b60318d1e8072"}, - {file = "regex-2021.10.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51feefd58ac38eb91a21921b047da8644155e5678e9066af7bcb30ee0dca7361"}, - {file = "regex-2021.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea8de658d7db5987b11097445f2b1f134400e2232cb40e614e5f7b6f5428710e"}, - {file = "regex-2021.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1ce02f420a7ec3b2480fe6746d756530f69769292eca363218c2291d0b116a01"}, - {file = "regex-2021.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39079ebf54156be6e6902f5c70c078f453350616cfe7bfd2dd15bdb3eac20ccc"}, - {file = "regex-2021.10.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ff24897f6b2001c38a805d53b6ae72267025878d35ea225aa24675fbff2dba7f"}, - {file = "regex-2021.10.8-cp310-cp310-win32.whl", hash = "sha256:c6569ba7b948c3d61d27f04e2b08ebee24fec9ff8e9ea154d8d1e975b175bfa7"}, - {file = "regex-2021.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:45cb0f7ff782ef51bc79e227a87e4e8f24bc68192f8de4f18aae60b1d60bc152"}, - {file = "regex-2021.10.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fab3ab8aedfb443abb36729410403f0fe7f60ad860c19a979d47fb3eb98ef820"}, - {file = "regex-2021.10.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74e55f8d66f1b41d44bc44c891bcf2c7fad252f8f323ee86fba99d71fd1ad5e3"}, - {file = "regex-2021.10.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d52c5e089edbdb6083391faffbe70329b804652a53c2fdca3533e99ab0580d9"}, - {file = "regex-2021.10.8-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1abbd95cbe9e2467cac65c77b6abd9223df717c7ae91a628502de67c73bf6838"}, - {file = "regex-2021.10.8-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9b5c215f3870aa9b011c00daeb7be7e1ae4ecd628e9beb6d7e6107e07d81287"}, - {file = "regex-2021.10.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f540f153c4f5617bc4ba6433534f8916d96366a08797cbbe4132c37b70403e92"}, - {file = "regex-2021.10.8-cp36-cp36m-win32.whl", hash = "sha256:1f51926db492440e66c89cd2be042f2396cf91e5b05383acd7372b8cb7da373f"}, - {file = "regex-2021.10.8-cp36-cp36m-win_amd64.whl", hash = "sha256:5f55c4804797ef7381518e683249310f7f9646da271b71cb6b3552416c7894ee"}, - {file = "regex-2021.10.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb2baff66b7d2267e07ef71e17d01283b55b3cc51a81b54cc385e721ae172ba4"}, - {file = "regex-2021.10.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e527ab1c4c7cf2643d93406c04e1d289a9d12966529381ce8163c4d2abe4faf"}, - {file = "regex-2021.10.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c98b013273e9da5790ff6002ab326e3f81072b4616fd95f06c8fa733d2745f"}, - {file = "regex-2021.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:55ef044899706c10bc0aa052f2fc2e58551e2510694d6aae13f37c50f3f6ff61"}, - {file = "regex-2021.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0ab3530a279a3b7f50f852f1bab41bc304f098350b03e30a3876b7dd89840e"}, - {file = "regex-2021.10.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a37305eb3199d8f0d8125ec2fb143ba94ff6d6d92554c4b8d4a8435795a6eccd"}, - {file = "regex-2021.10.8-cp37-cp37m-win32.whl", hash = "sha256:2efd47704bbb016136fe34dfb74c805b1ef5c7313aef3ce6dcb5ff844299f432"}, - {file = "regex-2021.10.8-cp37-cp37m-win_amd64.whl", hash = "sha256:924079d5590979c0e961681507eb1773a142553564ccae18d36f1de7324e71ca"}, - {file = "regex-2021.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b09d3904bf312d11308d9a2867427479d277365b1617e48ad09696fa7dfcdf59"}, - {file = "regex-2021.10.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f125fce0a0ae4fd5c3388d369d7a7d78f185f904c90dd235f7ecf8fe13fa741"}, - {file = "regex-2021.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f199419a81c1016e0560c39773c12f0bd924c37715bffc64b97140d2c314354"}, - {file = "regex-2021.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:09e1031e2059abd91177c302da392a7b6859ceda038be9e015b522a182c89e4f"}, - {file = "regex-2021.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c070d5895ac6aeb665bd3cd79f673775caf8d33a0b569e98ac434617ecea57d"}, - {file = "regex-2021.10.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:176796cb7f82a7098b0c436d6daac82f57b9101bb17b8e8119c36eecf06a60a3"}, - {file = "regex-2021.10.8-cp38-cp38-win32.whl", hash = "sha256:5e5796d2f36d3c48875514c5cd9e4325a1ca172fc6c78b469faa8ddd3d770593"}, - {file = "regex-2021.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:e4204708fa116dd03436a337e8e84261bc8051d058221ec63535c9403a1582a1"}, - {file = "regex-2021.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b8b6ee6555b6fbae578f1468b3f685cdfe7940a65675611365a7ea1f8d724991"}, - {file = "regex-2021.10.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973499dac63625a5ef9dfa4c791aa33a502ddb7615d992bdc89cf2cc2285daa3"}, - {file = "regex-2021.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88dc3c1acd3f0ecfde5f95c32fcb9beda709dbdf5012acdcf66acbc4794468eb"}, - {file = "regex-2021.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4786dae85c1f0624ac77cb3813ed99267c9adb72e59fdc7297e1cf4d6036d493"}, - {file = "regex-2021.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe6ce4f3d3c48f9f402da1ceb571548133d3322003ce01b20d960a82251695d2"}, - {file = "regex-2021.10.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9e3e2cea8f1993f476a6833ef157f5d9e8c75a59a8d8b0395a9a6887a097243b"}, - {file = "regex-2021.10.8-cp39-cp39-win32.whl", hash = "sha256:82cfb97a36b1a53de32b642482c6c46b6ce80803854445e19bc49993655ebf3b"}, - {file = "regex-2021.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:b04e512eb628ea82ed86eb31c0f7fc6842b46bf2601b66b1356a7008327f7700"}, - {file = "regex-2021.10.8.tar.gz", hash = "sha256:26895d7c9bbda5c52b3635ce5991caa90fbb1ddfac9c9ff1c7ce505e2282fb2a"}, + {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, + {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"}, + {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"}, + {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"}, + {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"}, + {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"}, + {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"}, + {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"}, + {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"}, + {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"}, + {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"}, + {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"}, + {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"}, + {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"}, + {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"}, + {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"}, + {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"}, + {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, + {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, ] requests = [ {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, @@ -1195,8 +1220,8 @@ simplejson = [ {file = "simplejson-3.11.1.win32-py3.5.exe", hash = "sha256:c76d55d78dc8b06c96fd08c6cc5e2b0b650799627d3f9ca4ad23f40db72d5f6d"}, ] singer-sdk = [ - {file = "singer-sdk-0.3.11.tar.gz", hash = "sha256:60e72fa86cd31e3be255d30f9751ba050114e3007f234f9b82212e6736643dd9"}, - {file = "singer_sdk-0.3.11-py3-none-any.whl", hash = "sha256:9e4c0ece54708a4a4f535d966b2528361467c7c9780a98d58623cb1b31e86b05"}, + {file = "singer-sdk-0.3.13.tar.gz", hash = "sha256:1984f45b6fcbe92cd66f6f20da9931a2c02fb086b9530b1f6e5b719bb1cad34e"}, + {file = "singer_sdk-0.3.13-py3-none-any.whl", hash = "sha256:695546308709541d4851bff9ff469dd0d90c583c8a2e1f8e083999194a225f75"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1252,8 +1277,8 @@ urllib3 = [ {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, ] virtualenv = [ - {file = "virtualenv-20.8.1-py2.py3-none-any.whl", hash = "sha256:10062e34c204b5e4ec5f62e6ef2473f8ba76513a9a617e873f1f8fb4a519d300"}, - {file = "virtualenv-20.8.1.tar.gz", hash = "sha256:bcc17f0b3a29670dd777d6f0755a4c04f28815395bca279cdcb213b97199a6b8"}, + {file = "virtualenv-20.10.0-py2.py3-none-any.whl", hash = "sha256:4b02e52a624336eece99c96e3ab7111f469c24ba226a53ec474e8e787b365814"}, + {file = "virtualenv-20.10.0.tar.gz", hash = "sha256:576d05b46eace16a9c348085f7d0dc8ef28713a2cabaa1cf0aea41e8f12c9218"}, ] wrapt = [ {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, diff --git a/pyproject.toml b/pyproject.toml index 267889d..e445532 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ keywords = [ [tool.poetry.dependencies] python = "<3.10,>=3.6.2" requests = "^2.25.1" -singer-sdk = "0.3.11" +singer-sdk = "0.3.13" [tool.poetry.dev-dependencies] pytest = "^6.1.2" diff --git a/tap_clickup/client.py b/tap_clickup/client.py index cc15eaa..66684c4 100644 --- a/tap_clickup/client.py +++ b/tap_clickup/client.py @@ -31,9 +31,8 @@ def get_url_params( if self.replication_key: params["order_by"] = "updated" params["reverse"] = "true" - params["date_updated_gt"] = self.initial_replication_key( - context - ) # Actually greater than or equal to + # Actually greater than or equal to + params["date_updated_gt"] = self. return params @property diff --git a/tap_clickup/streams.py b/tap_clickup/streams.py index c4994dd..bdb4d65 100644 --- a/tap_clickup/streams.py +++ b/tap_clickup/streams.py @@ -190,43 +190,17 @@ class TasksStream(ClickUpStream): parent_stream_type = TeamsStream partitions = [{"archived":"true"},{"archived":"false"}] - initial_replication_key_dict = {} - - def initial_replication_key(self, context) -> int: - path = self.get_url(context) - key_cache: Optional[int] = self.initial_replication_key_dict.get(path, None) - if key_cache is None: - key_cache = self.get_starting_replication_key_value(context) - self.initial_replication_key_dict[path] = key_cache - assert key_cache is not None - return key_cache - - def get_starting_replication_key_value( - self, context: Optional[dict] - ) -> Optional[int]: - """Return starting replication key value. """ - if self.replication_key: - state = self.get_context_state(context) - replication_key_value = state.get("replication_key_value") - if replication_key_value and self.replication_key == state.get( - "replication_key" - ): - return replication_key_value - if "start_date" in self.config: - datetime_startdate = cast( - datetime.datetime, pendulum.parse(self.config["start_date"]) - ) - startdate_seconds_after_epoch = int( - datetime_startdate.replace(tzinfo=datetime.timezone.utc).timestamp() - ) - return startdate_seconds_after_epoch - else: - self.logger.info( - """Setting replication value to 0 as there wasn't a - start_date provided in the config.""" - ) - return 0 - return None + #initial_replication_key_dict = {} + + #def initial_replication_key(self, context) -> int: + # path = self.get_url(context) + # key_cache: Optional[int] = self.initial_replication_key_dict.get(path, None) + # if key_cache is None: + # key_cache = self.get_starting_replication_key_value(context) + # self.initial_replication_key_dict[path] = key_cache + # assert key_cache is not None + # return key_cache + def get_next_page_token( self, response: requests.Response, previous_token: Optional[Any] From c20a7b6232a255014a1803c5b3eb80d0ce7b2486 Mon Sep 17 00:00:00 2001 From: Derek Visch Date: Sat, 13 Nov 2021 11:48:18 -0500 Subject: [PATCH 4/7] Tasks replication key strategy same as before, with mapping for archived and not archived --- tap_clickup/client.py | 23 ++------------ tap_clickup/streams.py | 68 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/tap_clickup/client.py b/tap_clickup/client.py index 66684c4..23a8d10 100644 --- a/tap_clickup/client.py +++ b/tap_clickup/client.py @@ -25,14 +25,10 @@ def get_url_params( ) -> Dict[str, Any]: """Return a dictionary of values to be used in URL parameterization.""" params: dict = {} + if next_page_token: + params["page"] = next_page_token if context: params["archived"] = context.get("archived") - # Replication key specefic to tasks - if self.replication_key: - params["order_by"] = "updated" - params["reverse"] = "true" - # Actually greater than or equal to - params["date_updated_gt"] = self. return params @property @@ -45,21 +41,6 @@ def http_headers(self) -> dict: headers["Authorization"] = self.config.get("api_token") return headers - def get_next_page_token( - self, response: requests.Response, previous_token: Optional[Any] - ) -> Optional[Any]: - """Return a token for identifying next page or None if no more pages.""" - if self.next_page_token_jsonpath: - all_matches = extract_jsonpath( - self.next_page_token_jsonpath, response.json() - ) - first_match = next(iter(all_matches), None) - next_page_token = first_match - else: - next_page_token = response.headers.get("X-Next-Page", None) - - return next_page_token - @backoff.on_exception( backoff.expo, (requests.exceptions.RequestException), diff --git a/tap_clickup/streams.py b/tap_clickup/streams.py index bdb4d65..ee9bea6 100644 --- a/tap_clickup/streams.py +++ b/tap_clickup/streams.py @@ -180,27 +180,69 @@ class TasksStream(ClickUpStream): """Tasks Stream""" name = "task" + #Date_updated_gt is greater than or equal to not just greater than path = "/team/{team_id}/task?include_closed=true&subtasks=true" primary_keys = ["id"] - replication_key = "date_updated" + replication_key = "date_updated" is_sorted = True ignore_parent_replication_key = True schema_filepath = SCHEMAS_DIR / "task.json" records_jsonpath = "$.tasks[*]" parent_stream_type = TeamsStream partitions = [{"archived":"true"},{"archived":"false"}] - - #initial_replication_key_dict = {} - - #def initial_replication_key(self, context) -> int: - # path = self.get_url(context) - # key_cache: Optional[int] = self.initial_replication_key_dict.get(path, None) - # if key_cache is None: - # key_cache = self.get_starting_replication_key_value(context) - # self.initial_replication_key_dict[path] = key_cache - # assert key_cache is not None - # return key_cache - + + initial_replication_key_dict = {} + + def initial_replication_key(self, context) -> int: + path = self.get_url(context) + context.get("archived") + key_cache: Optional[int] = self.initial_replication_key_dict.get(path, None) + if key_cache is None: + key_cache = self.get_starting_replication_key_value(context) + self.initial_replication_key_dict[path] = key_cache + assert key_cache is not None + return key_cache + + def get_url_params( + self, context: Optional[dict], next_page_token: Optional[Any] + ) -> Dict[str, Any]: + """Return a dictionary of values to be used in URL parameterization.""" + params: dict = {} + if next_page_token: + params["page"] = next_page_token + if context: + params["archived"] = context.get("archived") + if self.replication_key: + params["order_by"] = "updated" + params["reverse"] = "true" + params["date_updated_gt"] = self.initial_replication_key(context) + return params + + def get_starting_replication_key_value( + self, context: Optional[dict] + ) -> Optional[int]: + """Return starting replication key value. """ + if self.replication_key: + state = self.get_context_state(context) + replication_key_value = state.get("replication_key_value") + if replication_key_value and self.replication_key == state.get( + "replication_key" + ): + return replication_key_value + if "start_date" in self.config: + datetime_startdate = cast( + datetime.datetime, pendulum.parse(self.config["start_date"]) + ) + startdate_seconds_after_epoch = int( + datetime_startdate.replace(tzinfo=datetime.timezone.utc).timestamp() + ) + return startdate_seconds_after_epoch + else: + self.logger.info( + """Setting replication value to 0 as there wasn't a + start_date provided in the config.""" + ) + return 0 + return None def get_next_page_token( self, response: requests.Response, previous_token: Optional[Any] From fa2155a602ffbc30f6fb646a56d99b00d70f0c29 Mon Sep 17 00:00:00 2001 From: Derek Visch Date: Sat, 13 Nov 2021 15:59:02 -0500 Subject: [PATCH 5/7] Priority has objects for some instances of clickup --- tap_clickup/schemas/list.json | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tap_clickup/schemas/list.json b/tap_clickup/schemas/list.json index f808406..b320bfd 100644 --- a/tap_clickup/schemas/list.json +++ b/tap_clickup/schemas/list.json @@ -56,8 +56,22 @@ "$ref": "#definitions/status" }, "priority": { - "type": ["null", "string"] - }, + "type": ["string", "object", "null"], + "properties":{ + "color":{ + "type": ["string"] + }, + "id":{ + "type": ["string"] + }, + "orderindex":{ + "type": ["string"] + }, + "priority":{ + "type": ["string"] + } + } + }, "assignee": { "type": ["object", "null"], "properties": { From cf01e8e9e6b59b78956c5b3a00036afc8eaced1e Mon Sep 17 00:00:00 2001 From: Derek Visch Date: Tue, 16 Nov 2021 02:03:00 -0500 Subject: [PATCH 6/7] Removed Tasks Incremental ability to make work again --- README.md | 20 ++++---------------- tap_clickup/streams.py | 16 +++++++--------- tap_clickup/tap.py | 1 - 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 0e03391..ae85837 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@ -# `tap-clickup` -![Build and Tests](https://github.com/AutoIDM/tap-clickup/actions/workflows/ci.yml/badge.svg?branch=main) -[![PyPI download month](https://img.shields.io/pypi/dm/tap-clickup.svg)](https://pypi.python.org/pypi/tap-clickup/) - +# `tap-clickup` ![Build and Tests](https://github.com/AutoIDM/tap-clickup/actions/workflows/ci.yml/badge.svg?branch=main) [![PyPI download month](https://img.shields.io/pypi/dm/tap-clickup.svg)](https://pypi.python.org/pypi/tap-clickup/) `tap-clickup` is a Singer tap for ClickUp. ## Capabilities @@ -16,7 +13,6 @@ | Setting | Required | Default | Description | |:----------|:--------:|:-------:|:------------| | api_token | True | None | Example: 'pk_12345' | -| start_date| False | None | Example: '2010-01-01T00:00:00Z' | A full list of supported settings and capabilities is available by running: `tap-clickup --about` @@ -128,21 +124,13 @@ Note that the most up to date information is located in tap_clickup/streams.py. - Bookmark column(s): N/A - Link to API endpoint documentation: [Custom Field](https://jsapi.apiary.io/apis/clickup20/reference/0/custom-fields/get-accessible-custom-fields.html) -### Folderless Tasks -- Table name: folderless_task -- Description: Some tasks do not sit under folders. This comes from the folderless_list endpoint -- Primary key column(s): id -- Replicated fully or incrementally: Yes -- Bookmark column(s): date_updated. Note that the api endpoint date_updated_gt is great than or equal to, not just greater than. -- Link to API endpoint documentation: [Get Tasks](https://jsapi.apiary.io/apis/clickup20/reference/0/tasks/get-tasks.html) - -### Folder Tasks -- Table name: folder_task +### Tasks +- Table name: tasks - Description: Some tasks do not sit under folders. This comes from the folderless_list endpoint - Primary key column(s): id - Replicated fully or incrementally: Yes - Bookmark column(s): date_updated. Note that the api endpoint date_updated_gt is great than or equal to, not just greater than. -- Link to API endpoint documentation: [Get Tasks](https://jsapi.apiary.io/apis/clickup20/reference/0/tasks/get-tasks.html) +- Link to API endpoint documentation: [Get Tasks](https://jsapi.apiary.io/apis/clickup20/reference/0/tasks/get-filtered-team-tasks.html) ## Other Info diff --git a/tap_clickup/streams.py b/tap_clickup/streams.py index ee9bea6..e8d5c97 100644 --- a/tap_clickup/streams.py +++ b/tap_clickup/streams.py @@ -183,9 +183,9 @@ class TasksStream(ClickUpStream): #Date_updated_gt is greater than or equal to not just greater than path = "/team/{team_id}/task?include_closed=true&subtasks=true" primary_keys = ["id"] - replication_key = "date_updated" - is_sorted = True - ignore_parent_replication_key = True + #replication_key = "date_updated" + #is_sorted = True + #ignore_parent_replication_key = True schema_filepath = SCHEMAS_DIR / "task.json" records_jsonpath = "$.tasks[*]" parent_stream_type = TeamsStream @@ -209,12 +209,10 @@ def get_url_params( params: dict = {} if next_page_token: params["page"] = next_page_token - if context: - params["archived"] = context.get("archived") - if self.replication_key: - params["order_by"] = "updated" - params["reverse"] = "true" - params["date_updated_gt"] = self.initial_replication_key(context) + params["archived"] = context.get("archived") + params["order_by"] = "updated" + params["reverse"] = "true" + params["date_updated_gt"] = 0 return params def get_starting_replication_key_value( diff --git a/tap_clickup/tap.py b/tap_clickup/tap.py index b8e375f..8b251b4 100644 --- a/tap_clickup/tap.py +++ b/tap_clickup/tap.py @@ -43,7 +43,6 @@ class TapClickUp(Tap): config_jsonschema = th.PropertiesList( th.Property("api_token", th.StringType, required=True), - th.Property("start_date", th.DateTimeType), ).to_dict() def discover_streams(self) -> List[Stream]: From 177c05d19be326cc5c3b3fcfc5f30cc5e3588fc7 Mon Sep 17 00:00:00 2001 From: Derek Visch Date: Wed, 17 Nov 2021 16:01:29 -0500 Subject: [PATCH 7/7] Cleanup meltano config and readme as we removed Incremental replication --- README.md | 4 +--- meltano.yml | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/README.md b/README.md index ae85837..407cbc9 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,6 @@ A full list of supported settings and capabilities is available by running: `tap * This is a personal token, it's fine to use a personal token as this tap is only for the business that's using the data. ## Clickup Replication -Incremental Replication keys are available for Tasks. The Task uses the updated at field as [documented in the tasks section](https://clickup.com/apiv1) of the api. - Start Date is used for the initial updated at value for the updated at field with tasks. Let's say that you only want tasks that have been updated in the last year. To accomplish this you would pass in a start date of the first of this year! @@ -128,7 +126,7 @@ Note that the most up to date information is located in tap_clickup/streams.py. - Table name: tasks - Description: Some tasks do not sit under folders. This comes from the folderless_list endpoint - Primary key column(s): id -- Replicated fully or incrementally: Yes +- Replicated fully or incrementally: No - Bookmark column(s): date_updated. Note that the api endpoint date_updated_gt is great than or equal to, not just greater than. - Link to API endpoint documentation: [Get Tasks](https://jsapi.apiary.io/apis/clickup20/reference/0/tasks/get-filtered-team-tasks.html) diff --git a/meltano.yml b/meltano.yml index 6ae4841..d039020 100644 --- a/meltano.yml +++ b/meltano.yml @@ -11,13 +11,10 @@ plugins: - catalog - discover settings: - - name: username - name: api_token kind: password select: - '*.*' - config: - start_date: '2010-01-01T00:00:00Z' loaders: - name: target-jsonl variant: andyh1203