From afedd94bfe4466b7447b9b98c88fe1cb99d3fbfc Mon Sep 17 00:00:00 2001 From: nautics889 Date: Sun, 16 Apr 2023 00:15:58 +0300 Subject: [PATCH 01/21] fix: Update methods for custom fields (#114) Add method `custom_field_choices()` in `App` class. Rename method `custom_choices()` to `custom_fields()`. Update docstings for both methods according to returning data. --- pynautobot/core/app.py | 34 ++++++++++++++++++++++++++++++---- tests/test_app.py | 4 ++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/pynautobot/core/app.py b/pynautobot/core/app.py index d260b63..b90fdc4 100644 --- a/pynautobot/core/app.py +++ b/pynautobot/core/app.py @@ -82,16 +82,18 @@ def choices(self): return self._choices - def custom_choices(self): + def custom_fields(self): """Returns custom-fields response from app :Returns: Raw response from Nautobot's custom-fields endpoint. :Raises: :py:class:`.RequestError` if called for an invalid endpoint. :Example: - >>> nb.extras.custom_choices() - {'Testfield1': {'Testvalue2': 2, 'Testvalue1': 1}, - 'Testfield2': {'Othervalue2': 4, 'Othervalue1': 3}} + >>> custom_fields_list = nb.extras.custom_fields() + >>> print(custom_fields_list[0]['label']) + Test custom field for rack + >>> print(custom_fields_list[0]['content_types']) + ['dcim.rack'] """ custom_fields = Request( base="{}/{}/custom-fields/".format( @@ -103,6 +105,30 @@ def custom_choices(self): ).get() return custom_fields + def custom_field_choices(self): + """Returns custom-field-choices response from app + + :Returns: Raw response from Nautobot's custom-field-choices endpoint. + :Raises: :py:class:`.RequestError` if called for an invalid endpoint. + :Example: + + + >>> custom_field_choices_list = nb.extras.custom_field_choices() + >>> print(custom_field_choices_list[0]['value']) + First option + >>> print(custom_field_choices_list[0]['field']['name']) + test_custom_field + """ + custom_fields = Request( + base="{}/{}/custom-field-choices/".format( + self.api.base_url, + self.name, + ), + token=self.api.token, + http_session=self.api.http_session, + ).get() + return custom_fields + def config(self): """Returns config response from app diff --git a/tests/test_app.py b/tests/test_app.py index 31303dd..1c25284 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -17,7 +17,7 @@ class AppCustomChoicesTestCase(unittest.TestCase): ) def test_custom_choices(self, *_): api = pynautobot.api(host, **def_kwargs) - choices = api.extras.custom_choices() + choices = api.extras.custom_fields() self.assertEqual(len(choices), 2) self.assertEqual(sorted(choices.keys()), ["Testfield1", "Testfield2"]) @@ -44,7 +44,7 @@ class PluginAppCustomChoicesTestCase(unittest.TestCase): ) def test_custom_choices(self, *_): api = pynautobot.api(host, **def_kwargs) - choices = api.plugins.test_plugin.custom_choices() + choices = api.plugins.test_plugin.custom_fields() self.assertEqual(len(choices), 2) self.assertEqual(sorted(choices.keys()), ["Testfield1", "Testfield2"]) From 8085e23f22f56b7dc71302d756152f705fd94701 Mon Sep 17 00:00:00 2001 From: nautics889 Date: Sun, 16 Apr 2023 03:37:59 +0300 Subject: [PATCH 02/21] fix: Tests for methods for custom fields (#114) Add test case `AppCustomFieldChoicesTestCase` for `custom_field_choices()` method. Rename test case for `custom_fields()` method. Add using fixtures for mentioned test cases. --- tests/test_app.py | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/tests/test_app.py b/tests/test_app.py index 1c25284..fc6782b 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -3,6 +3,8 @@ import pynautobot +from .util import Response + host = "http://localhost:8000" def_kwargs = { @@ -10,16 +12,51 @@ } -class AppCustomChoicesTestCase(unittest.TestCase): +class AppCustomFieldsTestCase(unittest.TestCase): @patch( - "pynautobot.core.query.Request.get", - return_value={"Testfield1": {"TF1_1": 1, "TF1_2": 2}, "Testfield2": {"TF2_1": 3, "TF2_2": 4}}, + "requests.sessions.Session.get", + side_effect=[Response(fixture="extras/custom_fields.json")], ) - def test_custom_choices(self, *_): + def test_custom_fields(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) choices = api.extras.custom_fields() + + session_get_mock.assert_called_once() + expect_url = f"{api.base_url}/extras/custom-fields/" + url_passed_in_args = expect_url in session_get_mock.call_args.args + url_passed_in_kwargs = expect_url == session_get_mock.call_args.kwargs.get("url") + self.assertTrue(url_passed_in_args or url_passed_in_kwargs) + + self.assertIsInstance(choices, list) self.assertEqual(len(choices), 2) - self.assertEqual(sorted(choices.keys()), ["Testfield1", "Testfield2"]) + for field in choices: + self.assertIsInstance(field.get("name"), str) + self.assertIsInstance(field.get("content_types"), list) + self.assertIsInstance(field.get("slug"), str) + self.assertIn("type", field) + + +class AppCustomFieldChoicesTestCase(unittest.TestCase): + @patch( + "requests.sessions.Session.get", + side_effect=[Response(fixture="extras/custom_field_choices.json")], + ) + def test_custom_field_choices(self, session_get_mock): + api = pynautobot.api(host, **def_kwargs) + choices = api.extras.custom_field_choices() + + session_get_mock.assert_called_once() + expect_url = f"{api.base_url}/extras/custom-field-choices/" + url_passed_in_args = expect_url in session_get_mock.call_args.args + url_passed_in_kwargs = expect_url == session_get_mock.call_args.kwargs.get("url") + self.assertTrue(url_passed_in_args or url_passed_in_kwargs) + + self.assertIsInstance(choices, list) + self.assertEqual(len(choices), 3) + for choice in choices: + self.assertIsInstance(choice.get("field"), dict) + self.assertIsInstance(choice.get("value"), str) + self.assertIn(choice.get("value"), ("First option", "Second option", "Third option")) class AppConfigTestCase(unittest.TestCase): From 69ef638ff31cd46fb68523776fd17445b2626234 Mon Sep 17 00:00:00 2001 From: nautics889 Date: Sun, 16 Apr 2023 16:02:56 +0300 Subject: [PATCH 03/21] fix: Fixtures for tests (custom fields) (#114) Add missing JSON files with fixtures for tests for getting custom fields. --- .../fixtures/extras/custom_field_choices.json | 47 +++++++++++++++ tests/fixtures/extras/custom_fields.json | 60 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 tests/fixtures/extras/custom_field_choices.json create mode 100644 tests/fixtures/extras/custom_fields.json diff --git a/tests/fixtures/extras/custom_field_choices.json b/tests/fixtures/extras/custom_field_choices.json new file mode 100644 index 0000000..9f2239c --- /dev/null +++ b/tests/fixtures/extras/custom_field_choices.json @@ -0,0 +1,47 @@ +[ + { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "First option", + "url": "http://localhost:8000/api/extras/custom-field-choices/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "field": { + "display": "Test custom field 2", + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "name": "test_custom_field_2" + }, + "value": "First option", + "weight": 100, + "created": "2023-04-15", + "last_updated": "2023-04-15T18:11:57.163237Z" + }, + { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "Second option", + "url": "http://localhost:8000/api/extras/custom-field-choices/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "field": { + "display": "Test custom field 2", + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "name": "test_custom_field_2" + }, + "value": "Second option", + "weight": 100, + "created": "2023-04-15", + "last_updated": "2023-04-15T18:11:57.169962Z" + }, + { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "Third option", + "url": "http://localhost:8000/api/extras/custom-field-choices/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "field": { + "display": "Test custom field 2", + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "name": "test_custom_field_2" + }, + "value": "Third option", + "weight": 100, + "created": "2023-04-15", + "last_updated": "2023-04-15T18:11:57.174825Z" + } +] diff --git a/tests/fixtures/extras/custom_fields.json b/tests/fixtures/extras/custom_fields.json new file mode 100644 index 0000000..aacf67f --- /dev/null +++ b/tests/fixtures/extras/custom_fields.json @@ -0,0 +1,60 @@ +[ + { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "Test custom field", + "url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "content_types": [ + "dcim.rack" + ], + "type": { + "value": "integer", + "label": "Integer" + }, + "label": "Test custom field", + "name": "test_custom_field", + "slug": "test_custom_field", + "description": "", + "required": false, + "filter_logic": { + "value": "loose", + "label": "Loose" + }, + "default": null, + "weight": 100, + "validation_minimum": null, + "validation_maximum": null, + "validation_regex": "", + "created": "2023-04-15", + "last_updated": "2023-04-15T17:45:11.839431Z", + "notes_url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/notes/" + }, + { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "Test custom field 2", + "url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "content_types": [ + "dcim.rack" + ], + "type": { + "value": "select", + "label": "Selection" + }, + "label": "Test custom field 2", + "name": "test_custom_field_2", + "slug": "test_custom_field_2", + "description": "", + "required": false, + "filter_logic": { + "value": "loose", + "label": "Loose" + }, + "default": null, + "weight": 100, + "validation_minimum": null, + "validation_maximum": null, + "validation_regex": "", + "created": "2023-04-15", + "last_updated": "2023-04-15T18:11:57.133408Z", + "notes_url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/notes/" + } +] From b09543a43339774ee951a5a24b310c8678ae2a69 Mon Sep 17 00:00:00 2001 From: nautics889 Date: Sun, 16 Apr 2023 19:42:48 +0300 Subject: [PATCH 04/21] fix: Failing test for getting custom fields (#114) Fix test cases `AppCustomFieldsTestCase` and `AppCustomFieldChoicesTestCase` for python 3.7 stable. Update logic for checking passed arguments of mock's `call_args`. --- tests/test_app.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/test_app.py b/tests/test_app.py index fc6782b..61096ad 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -22,9 +22,10 @@ def test_custom_fields(self, session_get_mock): choices = api.extras.custom_fields() session_get_mock.assert_called_once() - expect_url = f"{api.base_url}/extras/custom-fields/" - url_passed_in_args = expect_url in session_get_mock.call_args.args - url_passed_in_kwargs = expect_url == session_get_mock.call_args.kwargs.get("url") + expect_url = "{}/extras/custom-fields/".format(api.base_url) + self.assertGreaterEqual(len(session_get_mock.call_args), 2) + url_passed_in_args = expect_url in session_get_mock.call_args[0] + url_passed_in_kwargs = expect_url == session_get_mock.call_args[1].get("url") self.assertTrue(url_passed_in_args or url_passed_in_kwargs) self.assertIsInstance(choices, list) @@ -46,9 +47,10 @@ def test_custom_field_choices(self, session_get_mock): choices = api.extras.custom_field_choices() session_get_mock.assert_called_once() - expect_url = f"{api.base_url}/extras/custom-field-choices/" - url_passed_in_args = expect_url in session_get_mock.call_args.args - url_passed_in_kwargs = expect_url == session_get_mock.call_args.kwargs.get("url") + expect_url = "{}/extras/custom-field-choices/".format(api.base_url) + self.assertGreaterEqual(len(session_get_mock.call_args), 2) + url_passed_in_args = expect_url in session_get_mock.call_args[0] + url_passed_in_kwargs = expect_url == session_get_mock.call_args[1].get("url") self.assertTrue(url_passed_in_args or url_passed_in_kwargs) self.assertIsInstance(choices, list) From d5ae60b725e63fd79f473e97f8ce999f0377f63c Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:27:14 +0200 Subject: [PATCH 05/21] Update api.py --- pynautobot/core/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pynautobot/core/api.py b/pynautobot/core/api.py index bd195e0..913a5e2 100644 --- a/pynautobot/core/api.py +++ b/pynautobot/core/api.py @@ -74,6 +74,7 @@ def __init__( url, token=None, threading=False, + max_workers:int=4, api_version=None, retries=0, ): @@ -94,6 +95,7 @@ def __init__( self.http_session.mount("http://", _adapter) self.http_session.mount("https://", _adapter) self.threading = threading + self.max_workers = max_workers self.api_version = api_version self.dcim = App(self, "dcim") From 6db551801e5ab1afcc439cadccd62e8f072f778a Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:29:32 +0200 Subject: [PATCH 06/21] max_workers added --- pynautobot/core/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pynautobot/core/api.py b/pynautobot/core/api.py index 913a5e2..59ae15c 100644 --- a/pynautobot/core/api.py +++ b/pynautobot/core/api.py @@ -54,6 +54,8 @@ class Api(object): :param str token: Your Nautobot token. :param bool,optional threading: Set to True to use threading in ``.all()`` and ``.filter()`` requests. + :param int,optional max_workers: Set the maximum workers for threading in ``.all()`` + and ``.filter()`` requests. :param str,optional api_version: Set to override the default Nautobot REST API Version for all requests. :param int,optional retries: Number of retries, for HTTP codes 429, 500, 502, 503, 504, From b3f0888c4c557a3ba5881ad21529a379ab211673 Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:32:55 +0200 Subject: [PATCH 07/21] max_workers added --- pynautobot/core/query.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pynautobot/core/query.py b/pynautobot/core/query.py index 467a07b..e26a0ff 100644 --- a/pynautobot/core/query.py +++ b/pynautobot/core/query.py @@ -131,6 +131,7 @@ def __init__( key=None, token=None, threading=False, + max_workers:int=4, api_version=None, ): """ @@ -152,6 +153,7 @@ def __init__( self.http_session = http_session self.url = self.base if not key else "{}{}/".format(self.base, key) self.threading = threading + self.max_workers = max_workers self.api_version = api_version def get_openapi(self): From 08ae04d8b2bc366a690bc4876efd359f2caed08a Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:36:06 +0200 Subject: [PATCH 08/21] Update query.py --- pynautobot/core/query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pynautobot/core/query.py b/pynautobot/core/query.py index e26a0ff..6ffc0e6 100644 --- a/pynautobot/core/query.py +++ b/pynautobot/core/query.py @@ -279,7 +279,7 @@ def _make_call(self, verb="get", url_override=None, add_params=None, data=None): def concurrent_get(self, ret, page_size, page_offsets): futures_to_results = [] - with cf.ThreadPoolExecutor(max_workers=4) as pool: + with cf.ThreadPoolExecutor(max_workers=self.max_workers) as pool: for offset in page_offsets: new_params = {"offset": offset, "limit": page_size} futures_to_results.append(pool.submit(self._make_call, add_params=new_params)) From 622065ec426d159f0059996ad48c2f000ff4b6f3 Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:40:13 +0200 Subject: [PATCH 09/21] Update query.py --- pynautobot/core/query.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pynautobot/core/query.py b/pynautobot/core/query.py index 6ffc0e6..84fd3e9 100644 --- a/pynautobot/core/query.py +++ b/pynautobot/core/query.py @@ -279,6 +279,7 @@ def _make_call(self, verb="get", url_override=None, add_params=None, data=None): def concurrent_get(self, ret, page_size, page_offsets): futures_to_results = [] + print(f"DEBUG: max_workers: {self.max_workers}") with cf.ThreadPoolExecutor(max_workers=self.max_workers) as pool: for offset in page_offsets: new_params = {"offset": offset, "limit": page_size} From b92123abfb8c996445a11ef74a0fd17526c08bed Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:49:17 +0200 Subject: [PATCH 10/21] max_workers from api to request --- pynautobot/core/endpoint.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pynautobot/core/endpoint.py b/pynautobot/core/endpoint.py index bb82a1a..c2dc4f6 100644 --- a/pynautobot/core/endpoint.py +++ b/pynautobot/core/endpoint.py @@ -104,6 +104,7 @@ def all(self, api_version=None): token=self.token, http_session=self.api.http_session, threading=self.api.threading, + max_workers=self.api.max_workers, api_version=api_version, ) From 085b799efacc7afd6684dfcf937b3e612cff9eec Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:56:23 +0200 Subject: [PATCH 11/21] debug removed --- pynautobot/core/query.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pynautobot/core/query.py b/pynautobot/core/query.py index 84fd3e9..6ffc0e6 100644 --- a/pynautobot/core/query.py +++ b/pynautobot/core/query.py @@ -279,7 +279,6 @@ def _make_call(self, verb="get", url_override=None, add_params=None, data=None): def concurrent_get(self, ret, page_size, page_offsets): futures_to_results = [] - print(f"DEBUG: max_workers: {self.max_workers}") with cf.ThreadPoolExecutor(max_workers=self.max_workers) as pool: for offset in page_offsets: new_params = {"offset": offset, "limit": page_size} From e3644f06c45715da2ccdcda1fde8d5e3b6db2588 Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Fri, 30 Jun 2023 08:40:20 +0200 Subject: [PATCH 12/21] Update api.py --- pynautobot/core/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pynautobot/core/api.py b/pynautobot/core/api.py index 59ae15c..a48e9af 100644 --- a/pynautobot/core/api.py +++ b/pynautobot/core/api.py @@ -76,7 +76,7 @@ def __init__( url, token=None, threading=False, - max_workers:int=4, + max_workers=4, api_version=None, retries=0, ): From 2686642d35dea74a9bbf0fe5f9f5d54b2170645b Mon Sep 17 00:00:00 2001 From: NobodyIsPerfect78 <46317624+NobodyIsPerfect78@users.noreply.github.com> Date: Fri, 30 Jun 2023 08:42:03 +0200 Subject: [PATCH 13/21] Update query.py --- pynautobot/core/query.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pynautobot/core/query.py b/pynautobot/core/query.py index 6ffc0e6..6b3cb46 100644 --- a/pynautobot/core/query.py +++ b/pynautobot/core/query.py @@ -121,6 +121,8 @@ class Request(object): correlate to the filters a given endpoint accepts. In (e.g. /api/dcim/devices/?name='test') 'name': 'test' would be in the filters dict. + :param int,optional max_workers: Set the maximum workers for threading in ``.all()`` + and ``.filter()`` requests. """ def __init__( @@ -131,7 +133,7 @@ def __init__( key=None, token=None, threading=False, - max_workers:int=4, + max_workers=4, api_version=None, ): """ From e8b586c54607e52d0a11fe2a3747c47d280b126a Mon Sep 17 00:00:00 2001 From: nautics889 Date: Sat, 15 Jul 2023 15:41:00 +0300 Subject: [PATCH 14/21] refactor: Update docstrings and naming (#114) * (docs) update docstrings for `custom_fields()` and `custom_field_choices()` methods * (refactor): use f-strings instead of `.format()` in `custom_fields()` and `custom_field_choices()` * (tests): update naming in tests * (tests): use `return_value` instead of `side_effect` for mocks --- pynautobot/core/app.py | 63 +++++++++++++++++++++++++++++------------- tests/test_app.py | 16 +++++------ 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/pynautobot/core/app.py b/pynautobot/core/app.py index b90fdc4..497a98c 100644 --- a/pynautobot/core/app.py +++ b/pynautobot/core/app.py @@ -89,17 +89,33 @@ def custom_fields(self): :Raises: :py:class:`.RequestError` if called for an invalid endpoint. :Example: - >>> custom_fields_list = nb.extras.custom_fields() - >>> print(custom_fields_list[0]['label']) - Test custom field for rack - >>> print(custom_fields_list[0]['content_types']) - ['dcim.rack'] + >>> nb.extras.custom_fields() + [ + { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "Test custom field", + "url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "content_types": ["dcim.rack"], + "type": {"value": "integer", "label": "Integer"}, + "label": "Test custom field", + "name": "test_custom_field", + "slug": "test_custom_field", + "description": "", + "required": False, + "filter_logic": {"value": "loose", "label": "Loose"}, + "default": None, + "weight": 100, + "validation_minimum": None, + "validation_maximum": None, + "validation_regex": "", + "created": "2023-04-15", + "last_updated": "2023-04-15T17:45:11.839431Z", + "notes_url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/notes/", + }, + ] """ custom_fields = Request( - base="{}/{}/custom-fields/".format( - self.api.base_url, - self.name, - ), + base=f"{self.api.base_url}/{self.name}/custom-fields/", token=self.api.token, http_session=self.api.http_session, ).get() @@ -112,18 +128,27 @@ def custom_field_choices(self): :Raises: :py:class:`.RequestError` if called for an invalid endpoint. :Example: - - >>> custom_field_choices_list = nb.extras.custom_field_choices() - >>> print(custom_field_choices_list[0]['value']) - First option - >>> print(custom_field_choices_list[0]['field']['name']) - test_custom_field + >>> nb.extras.custom_field_choices() + [ + { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "First option", + "url": "http://localhost:8000/api/extras/custom-field-choices/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "field": { + "display": "Test custom field 2", + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "url": "http://localhost:8000/api/extras/custom-fields/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "name": "test_custom_field_2" + }, + "value": "First option", + "weight": 100, + "created": "2023-04-15", + "last_updated": "2023-04-15T18:11:57.163237Z" + }, + ] """ custom_fields = Request( - base="{}/{}/custom-field-choices/".format( - self.api.base_url, - self.name, - ), + base=f"{self.api.base_url}/{self.name}/custom-field-choices/", token=self.api.token, http_session=self.api.http_session, ).get() diff --git a/tests/test_app.py b/tests/test_app.py index 61096ad..36d387e 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -15,22 +15,22 @@ class AppCustomFieldsTestCase(unittest.TestCase): @patch( "requests.sessions.Session.get", - side_effect=[Response(fixture="extras/custom_fields.json")], + return_value=Response(fixture="extras/custom_fields.json"), ) def test_custom_fields(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) - choices = api.extras.custom_fields() + cfs = api.extras.custom_fields() session_get_mock.assert_called_once() - expect_url = "{}/extras/custom-fields/".format(api.base_url) + expect_url = f"{api.base_url}/extras/custom-fields/" self.assertGreaterEqual(len(session_get_mock.call_args), 2) url_passed_in_args = expect_url in session_get_mock.call_args[0] url_passed_in_kwargs = expect_url == session_get_mock.call_args[1].get("url") self.assertTrue(url_passed_in_args or url_passed_in_kwargs) - self.assertIsInstance(choices, list) - self.assertEqual(len(choices), 2) - for field in choices: + self.assertIsInstance(cfs, list) + self.assertEqual(len(cfs), 2) + for field in cfs: self.assertIsInstance(field.get("name"), str) self.assertIsInstance(field.get("content_types"), list) self.assertIsInstance(field.get("slug"), str) @@ -40,14 +40,14 @@ def test_custom_fields(self, session_get_mock): class AppCustomFieldChoicesTestCase(unittest.TestCase): @patch( "requests.sessions.Session.get", - side_effect=[Response(fixture="extras/custom_field_choices.json")], + return_value=Response(fixture="extras/custom_field_choices.json"), ) def test_custom_field_choices(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) choices = api.extras.custom_field_choices() session_get_mock.assert_called_once() - expect_url = "{}/extras/custom-field-choices/".format(api.base_url) + expect_url = f"{api.base_url}/extras/custom-field-choices/" self.assertGreaterEqual(len(session_get_mock.call_args), 2) url_passed_in_args = expect_url in session_get_mock.call_args[0] url_passed_in_kwargs = expect_url == session_get_mock.call_args[1].get("url") From e5efc1a84ed2a2e5e54b469d805af3dbd36911a8 Mon Sep 17 00:00:00 2001 From: Nautics889 Date: Mon, 24 Jul 2023 01:47:56 +0300 Subject: [PATCH 15/21] fix: backward compatibility * (fix): restore original method `custom_choices()` for application class to provide a compatibility with existing client code * (enhance): add logging a deprecation warning --- pynautobot/core/app.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/pynautobot/core/app.py b/pynautobot/core/app.py index 497a98c..1516a92 100644 --- a/pynautobot/core/app.py +++ b/pynautobot/core/app.py @@ -15,10 +15,14 @@ This file has been modified by NetworktoCode, LLC. """ +import logging + from pynautobot.core.endpoint import Endpoint, JobsEndpoint from pynautobot.core.query import Request from pynautobot.models import circuits, dcim, extras, ipam, users, virtualization +logger = logging.getLogger(__name__) + class App(object): """Represents apps in Nautobot. @@ -82,6 +86,38 @@ def choices(self): return self._choices + def custom_choices(self): + """Returns custom-fields response from app + + .. note:: + + This method is deprecated and will be removed in pynautobot + 2.0 or newer. Please use `custom_fields()` instead. + + :Returns: Raw response from Nautobot's custom-fields endpoint. + :Raises: :py:class:`.RequestError` if called for an invalid endpoint. + :Example: + + >>> nb.extras.custom_choices() + {'Testfield1': {'Testvalue2': 2, 'Testvalue1': 1}, + 'Testfield2': {'Othervalue2': 4, 'Othervalue1': 3}} + """ + logger.warning( + "WARNING: The method 'custom_choices()' will be removed in " + "the next major version (2.x) of pynautobot. Please use " + "`custom_fields()` instead." + ) + + custom_fields = Request( + base="{}/{}/custom-fields/".format( + self.api.base_url, + self.name, + ), + token=self.api.token, + http_session=self.api.http_session, + ).get() + return custom_fields + def custom_fields(self): """Returns custom-fields response from app From f401a2302e9d55d0577b0c901b9084290dc6c473 Mon Sep 17 00:00:00 2001 From: Nautics889 Date: Tue, 25 Jul 2023 21:36:44 +0300 Subject: [PATCH 16/21] refactor: update `custom_choices()` (#114) * (refactor): call `custom_fields()` in `custom_choices()` since they represent essentially identical requests to Nautobot --- pynautobot/core/app.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pynautobot/core/app.py b/pynautobot/core/app.py index 1516a92..149482e 100644 --- a/pynautobot/core/app.py +++ b/pynautobot/core/app.py @@ -108,15 +108,7 @@ def custom_choices(self): "`custom_fields()` instead." ) - custom_fields = Request( - base="{}/{}/custom-fields/".format( - self.api.base_url, - self.name, - ), - token=self.api.token, - http_session=self.api.http_session, - ).get() - return custom_fields + return self.custom_fields() def custom_fields(self): """Returns custom-fields response from app From 2f982c34947eeda2a7124265e0ec93d62fb05a9d Mon Sep 17 00:00:00 2001 From: Patryk Szulczewski Date: Mon, 7 Aug 2023 11:08:03 +0200 Subject: [PATCH 17/21] Add version constraint to divide into two release trains 1.x and 2.x (#130) Add version constraint to divide into two release trains 1.x and 2.x --- pynautobot/core/api.py | 8 ++++++++ tests/__init__.py | 9 +++++---- tests/conftest.py | 3 ++- tests/integration/test_api_version.py | 2 +- tests/test_api.py | 29 +++++++++++++++++++++------ tests/test_app.py | 5 +++++ 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/pynautobot/core/api.py b/pynautobot/core/api.py index a48e9af..2294743 100644 --- a/pynautobot/core/api.py +++ b/pynautobot/core/api.py @@ -15,6 +15,7 @@ This file has been modified by NetworktoCode, LLC. """ +from packaging import version import requests from requests.adapters import HTTPAdapter from urllib3 import Retry @@ -109,6 +110,13 @@ def __init__( self.users = App(self, "users") self.plugins = PluginsApp(self) self.graphql = GraphQLQuery(self) + self._validate_version() + + def _validate_version(self): + """Validate API version if eq or ge than 2.0 raise an error.""" + api_version = self.version + if api_version.replace(".", "").isnumeric() and version.parse(api_version) >= version.parse("2.0"): + raise ValueError("Nautobot version 2 detected, please upgrade pynautobot to version 2.x") @property def version(self): diff --git a/tests/__init__.py b/tests/__init__.py index 42b272d..034e971 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -5,10 +5,11 @@ from .util import Response -api = pynautobot.api( - "http://localhost:8000", - token="abc123", -) +with patch("pynautobot.api.version", "1.999"): + api = pynautobot.api( + "http://localhost:8000", + token="abc123", + ) HEADERS = { "accept": "application/json;", diff --git a/tests/conftest.py b/tests/conftest.py index 29218b6..fb7d490 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -46,8 +46,9 @@ def pytest_configure(config): @pytest.fixture -def pynautobot_api(): +def pynautobot_api(monkeypatch): """Factory to create pynautobot api instance.""" + monkeypatch.setattr("pynautobot.api.version", "1.999") return Api(url="https://mocknautobot.example.com", token="1234567890abcdefg") diff --git a/tests/integration/test_api_version.py b/tests/integration/test_api_version.py index 92d7f8b..aaa2fe3 100644 --- a/tests/integration/test_api_version.py +++ b/tests/integration/test_api_version.py @@ -11,7 +11,7 @@ class TestAPIVersioning: def nb_client_1_3(self, nb_client): """Setup a nb_client with API v1.3.""" # Instantiate with a temp url and then replace - nb_api = pynautobot.api("http://localhost", token=nb_client.token, api_version="1.3") + nb_api = pynautobot.api("http://nautobot:8000", token=nb_client.token, api_version="1.3") nb_api.base_url = nb_client.base_url return nb_api diff --git a/tests/test_api.py b/tests/test_api.py index abe94ff..55481ff 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -26,6 +26,7 @@ class ApiTestCase(unittest.TestCase): @patch( "requests.sessions.Session.post", ) + @patch("pynautobot.api.version", "1.999") def test_get(self, *_): api = pynautobot.api(host, **def_kwargs) self.assertTrue(api) @@ -33,6 +34,7 @@ def test_get(self, *_): @patch( "requests.sessions.Session.post", ) + @patch("pynautobot.api.version", "1.999") def test_sanitize_url(self, *_): api = pynautobot.api("http://localhost:8000/", **def_kwargs) self.assertTrue(api) @@ -68,6 +70,19 @@ def test_api_version_not_found(self, *_): ) self.assertEqual(api.version, "") + class ResponseHeadersWithVersion2: + headers = {"API-Version": "2.0"} + ok = True + + @patch( + "requests.sessions.Session.get", + return_value=ResponseHeadersWithVersion2(), + ) + def test_api_version_2(self, *_): + with self.assertRaises(ValueError) as error: + pynautobot.api(host) + self.assertEqual(str(error.exception), "Nautobot version 2 detected, please upgrade pynautobot to version 2.x") + class ApiStatusTestCase(unittest.TestCase): class ResponseWithStatus: @@ -82,6 +97,7 @@ def json(self): "requests.sessions.Session.get", return_value=ResponseWithStatus(), ) + @patch("pynautobot.api.version", "1.999") def test_api_status(self, *_): api = pynautobot.api( host, @@ -106,8 +122,8 @@ def test_api_retry(self, getconn_mock): "http://any.url/", retries=2, ) - - api.version + with patch("pynautobot.api.version", "1.999"): + api.version assert getconn_mock.return_value.request.mock_calls == [ call("GET", "/api/", body=None, headers=ANY), @@ -123,10 +139,11 @@ def test_api_retry_fails(self, getconn_mock): Mock(status=200, msg=HTTPMessage()), ] - api = pynautobot.api( - "http://any.url/", - retries=1, - ) + with patch("pynautobot.api.version", "1.999"): + api = pynautobot.api( + "http://any.url/", + retries=1, + ) with self.assertRaises(RequestErrorFromException): api.version diff --git a/tests/test_app.py b/tests/test_app.py index 36d387e..acbc648 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -17,6 +17,7 @@ class AppCustomFieldsTestCase(unittest.TestCase): "requests.sessions.Session.get", return_value=Response(fixture="extras/custom_fields.json"), ) + @patch("pynautobot.api.version", "1.999") def test_custom_fields(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) cfs = api.extras.custom_fields() @@ -42,6 +43,7 @@ class AppCustomFieldChoicesTestCase(unittest.TestCase): "requests.sessions.Session.get", return_value=Response(fixture="extras/custom_field_choices.json"), ) + @patch("pynautobot.api.version", "1.999") def test_custom_field_choices(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) choices = api.extras.custom_field_choices() @@ -66,6 +68,7 @@ class AppConfigTestCase(unittest.TestCase): "pynautobot.core.query.Request.get", return_value={"tables": {"DeviceTable": {"columns": ["name", "status", "tenant", "tags"]}}}, ) + @patch("pynautobot.api.version", "1.999") def test_config(self, *_): api = pynautobot.api(host, **def_kwargs) config = api.users.config() @@ -81,6 +84,7 @@ class PluginAppCustomChoicesTestCase(unittest.TestCase): "pynautobot.core.query.Request.get", return_value={"Testfield1": {"TF1_1": 1, "TF1_2": 2}, "Testfield2": {"TF2_1": 3, "TF2_2": 4}}, ) + @patch("pynautobot.api.version", "1.999") def test_custom_choices(self, *_): api = pynautobot.api(host, **def_kwargs) choices = api.plugins.test_plugin.custom_fields() @@ -91,6 +95,7 @@ def test_custom_choices(self, *_): "pynautobot.core.query.Request.get", return_value=[{"name": "test_plugin", "package": "netbox_test_plugin"}], ) + @patch("pynautobot.api.version", "1.999") def test_installed_plugins(self, *_): api = pynautobot.api(host, **def_kwargs) plugins = api.plugins.installed_plugins() From 84d685a36f7ae1b3c5f5c007187170ed3db097d3 Mon Sep 17 00:00:00 2001 From: Patryk Szulczewski Date: Wed, 4 Oct 2023 17:52:57 +0200 Subject: [PATCH 18/21] Release 2.0 (#136) * Release 2.0.0 --------- Co-authored-by: Jan Snasel Co-authored-by: Joe Wesch <10467633+joewesch@users.noreply.github.com> --- .github/workflows/ci.yml | 4 +- CHANGELOG.md | 17 + CONTRIBUTING.md | 4 +- development/docker-compose.yml | 10 +- docs/advanced/create.rst | 361 +++++----- docs/advanced/graphql.rst | 69 +- docs/advanced/read.rst | 103 ++- docs/advanced/record.rst | 242 ++++--- docs/advanced/session.rst | 5 +- docs/advanced/update.rst | 115 ++-- docs/basic/api.rst | 128 ++-- docs/basic/crud/create.rst | 26 +- docs/basic/crud/delete.rst | 18 +- docs/basic/crud/read.rst | 39 +- docs/basic/crud/update.rst | 28 +- poetry.lock | 922 +++++++++++--------------- pynautobot/core/api.py | 4 +- pynautobot/core/endpoint.py | 16 +- pynautobot/models/dcim.py | 9 +- pyproject.toml | 6 +- tasks.py | 4 +- tests/__init__.py | 2 +- tests/conftest.py | 2 +- tests/fixtures/ipam/namespace.json | 13 + tests/fixtures/ipam/namespaces.json | 33 + tests/fixtures/ipam/prefix.json | 8 + tests/fixtures/ipam/vrf.json | 8 + tests/integration/conftest.py | 11 +- tests/integration/test_api_version.py | 16 +- tests/integration/test_dcim.py | 125 ++-- tests/integration/test_ipam.py | 20 +- tests/test_api.py | 24 +- tests/test_app.py | 10 +- tests/test_ipam.py | 38 ++ tests/unit/test_api_version.py | 4 +- tests/unit/test_endpoint.py | 13 +- 36 files changed, 1268 insertions(+), 1189 deletions(-) create mode 100644 tests/fixtures/ipam/namespace.json create mode 100644 tests/fixtures/ipam/namespaces.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5b1d3f..7354e11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,8 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] - nautobot-version: ["1.2", "1.3", "stable"] + python-version: ["3.8", "3.9", "3.10"] + nautobot-version: ["2.0"] exclude: - python-version: 3.10 nautobot-version: 1.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index b28e7b8..958de1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## v2.0.0 + +### Significant Updates + +New release for nautobot 2.0 + +- (#135) - Docs Update +- (#134) - Updates in .choices due to changed `OPTIONS` schema +- (#130) - Add version constraint on `__init__` to divide 1.X and 2.X. + +## 2.0.0-rc.1 + +### Significant Updates + +Release Candidate. +New release train for nautobot 2.X + ## v1.5.0 ### New Features diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9650624..e1da34f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ This section describes how to install *pynautobot* for development, how to run t ## Python Versions -This leverages Python3.6 or later. +This leverages Python 3.8 or later. ## Installing dependencies for local development @@ -21,7 +21,7 @@ Follow these steps to set up your local development environment: ```bash # Double check your version $ python --version -Python 3.7.7 +Python 3.8.7 # Activate the Poetry environment, which will auto create the virtual environment related to the project $ poetry shell # Install project dependencies as well as development dependencies diff --git a/development/docker-compose.yml b/development/docker-compose.yml index 17318f4..b5264f5 100644 --- a/development/docker-compose.yml +++ b/development/docker-compose.yml @@ -20,7 +20,7 @@ services: nautobot: condition: "service_healthy" nautobot: - image: "ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER:-1.3}-py${PYTHON_VER:-3.7}" + image: "ghcr.io/nautobot/nautobot:${NAUTOBOT_VER:-1.3}-py${PYTHON_VER:-3.8}" command: "nautobot-server runserver 0.0.0.0:8000 --insecure" ports: - "8000:8000" @@ -33,7 +33,7 @@ services: healthcheck: interval: "30s" timeout: "10s" - start_period: "2m" + start_period: "5m" retries: 4 test: - "CMD-SHELL" @@ -49,3 +49,9 @@ services: - "-c" # this is to evaluate the $REDIS_PASSWORD from the env - "redis-server --appendonly yes --requirepass $$REDIS_PASSWORD" ## $$ because of docker-compose env_file: "./dev.env" + docs: + image: "nginx:alpine" + ports: + - "8001:80" + volumes: + - "${PWD}/docs/_build/html:/usr/share/nginx/html:ro" diff --git a/docs/advanced/create.rst b/docs/advanced/create.rst index 26e2f4a..5d86e15 100644 --- a/docs/advanced/create.rst +++ b/docs/advanced/create.rst @@ -18,55 +18,89 @@ Obtaining Choices For fields that are enum type, Endpoint objects have a :py:meth:`~pynautobot.core.endpoint.Endpoint.choices` method to provide a mapping of enum fields to their list of acceptable choices. -The examples used in the document revolve around creating a new Device Record. -Creating a *Device* requires specifying the ``status`` field, which is an example of an enum. -Below demonstrates how to view the list of available choices for Device Status. .. code-block:: python - import os - from pynautobot import api - - url = os.environ["NAUTOBOT_URL"] - token = os.environ["NAUTOBOT_TOKEN"] - nautobot = api(url=url, token=token) - - # Get the choices for enum fields for the devices endpoint - nautobot.dcim.devices.choices() - { - 'face': [ - { - 'value': 'front', - 'display_name': 'Front' - }, - { - 'value', 'rear', - 'display_name': 'Rear' - } - ], - 'status': [ - { - 'value': 'active', - 'display_name': 'Active' - }, - { - 'value': 'maintenance', - 'display_name': 'Maintenance' - }, - { - 'value': 'staged', - 'display_name': 'Staged' - } - ] - } - - # Accessing entries from choices for the status field - device_status_choices = nautobot.dcim.devices.choices()['status'] - device_status_choices[0] - {'value': 'active', 'display_name': 'Active'} - -.. tip:: - The list of available status choices is configurable, so the output will vary between implementations. + >>> import os + >>> from pprint import pprint + >>> from pynautobot import api + >>> + >>> url = os.environ["NAUTOBOT_URL"] + >>> token = os.environ["NAUTOBOT_TOKEN"] + >>> nautobot = api(url=url, token=token) + >>> + >>> # Get the choices for enum fields for the cables endpoint + >>> pprint(nautobot.dcim.cables.choices()) + {'length_unit': [{'display': 'Kilometers', 'value': 'km'}, + {'display': 'Meters', 'value': 'm'}, + {'display': 'Centimeters', 'value': 'cm'}, + {'display': 'Miles', 'value': 'mi'}, + {'display': 'Feet', 'value': 'ft'}, + {'display': 'Inches', 'value': 'in'}], + 'termination_a_type': [{'display': 'dcim | interface', + 'value': 'dcim.interface'}, + {'display': 'dcim | power feed', + 'value': 'dcim.powerfeed'}, + {'display': 'circuits | circuit termination', + 'value': 'circuits.circuittermination'}, + {'display': 'dcim | console port', + 'value': 'dcim.consoleport'}, + {'display': 'dcim | console server port', + 'value': 'dcim.consoleserverport'}, + {'display': 'dcim | front port', + 'value': 'dcim.frontport'}, + {'display': 'dcim | power outlet', + 'value': 'dcim.poweroutlet'}, + {'display': 'dcim | power port', + 'value': 'dcim.powerport'}, + {'display': 'dcim | rear port', + 'value': 'dcim.rearport'}], + 'termination_b_type': [{'display': 'dcim | interface', + 'value': 'dcim.interface'}, + {'display': 'dcim | power feed', + 'value': 'dcim.powerfeed'}, + {'display': 'circuits | circuit termination', + 'value': 'circuits.circuittermination'}, + {'display': 'dcim | console port', + 'value': 'dcim.consoleport'}, + {'display': 'dcim | console server port', + 'value': 'dcim.consoleserverport'}, + {'display': 'dcim | front port', + 'value': 'dcim.frontport'}, + {'display': 'dcim | power outlet', + 'value': 'dcim.poweroutlet'}, + {'display': 'dcim | power port', + 'value': 'dcim.powerport'}, + {'display': 'dcim | rear port', + 'value': 'dcim.rearport'}], + 'type': [{'display': 'CAT3', 'value': 'cat3'}, + {'display': 'CAT5', 'value': 'cat5'}, + {'display': 'CAT5e', 'value': 'cat5e'}, + {'display': 'CAT6', 'value': 'cat6'}, + {'display': 'CAT6a', 'value': 'cat6a'}, + {'display': 'CAT7', 'value': 'cat7'}, + {'display': 'CAT7a', 'value': 'cat7a'}, + {'display': 'CAT8', 'value': 'cat8'}, + {'display': 'Direct Attach Copper (Active)', 'value': 'dac-active'}, + {'display': 'Direct Attach Copper (Passive)', 'value': 'dac-passive'}, + {'display': 'MRJ21 Trunk', 'value': 'mrj21-trunk'}, + {'display': 'Coaxial', 'value': 'coaxial'}, + {'display': 'Multimode Fiber', 'value': 'mmf'}, + {'display': 'Multimode Fiber (OM1)', 'value': 'mmf-om1'}, + {'display': 'Multimode Fiber (OM2)', 'value': 'mmf-om2'}, + {'display': 'Multimode Fiber (OM3)', 'value': 'mmf-om3'}, + {'display': 'Multimode Fiber (OM4)', 'value': 'mmf-om4'}, + {'display': 'Singlemode Fiber', 'value': 'smf'}, + {'display': 'Singlemode Fiber (OS1)', 'value': 'smf-os1'}, + {'display': 'Singlemode Fiber (OS2)', 'value': 'smf-os2'}, + {'display': 'Active Optical Cabling (AOC)', 'value': 'aoc'}, + {'display': 'Power', 'value': 'power'}, + {'display': 'Other', 'value': 'other'}]} + >>> + >>> # Accessing entries from choices for the type field + >>> cable_types_choices = nautobot.dcim.cables.choices()['type'] + >>> cable_types_choices[3] + {'value': 'cat6', 'display': 'CAT6'} .. warning:: In order to avoid repeated calls to Nautobot, ``choices`` are cached on the Endpoint object. It is advisable to @@ -78,9 +112,9 @@ Creating Objects with Foreign Key Relationships Creating a Device in Nautobot requires the following :ref:`fields ` to specify a foreign key relationship: + * Role * Device Type - * Device Role - * Site + * Location This can be accomplished by providing the Primary Key (**PK**), which is an UUID string or a dictionary with key/value pairs that make the object unique. @@ -91,26 +125,26 @@ Endpoint object, and then referencing the ``id`` of those objects to create a ne .. code-block:: python - nautobot = api(url=url, token=token) - - # Get objects for device_type, device_role, and site to get their ID - device_type = nautobot.dcim.device_types.get(slug="c9300-48") - device_role = nautobot.dcim.device_roles.get(slug="access") - site = nautobot.dcim.sites.get(slug="hq") - - # Create new device using foreign key IDs - devices = nautobot.dcim.devices - hq_access_1 = devices.create( - name="hq-access-01", - device_type=device_type.id, - device_role=device_role.id, - site=site.id, - status="active", - ) - type(hq_access_1) + >>> nautobot = api(url=url, token=token) + >>> + >>> # Get objects for device_type, role, and location to get their ID + >>> device_type = nautobot.dcim.device_types.get(model="c9300-48") + >>> role = nautobot.extras.roles.get(name="access") + >>> location = nautobot.dcim.locations.get(name="HQ") + >>> + >>> # Create new device using foreign key IDs + >>> devices = nautobot.dcim.devices + >>> hq_access_1 = devices.create( + ... name="hq-access-01", + ... device_type=device_type.id, + ... role=role.id, + ... location=location.id, + ... status={"name": "Active"}, + ... ) + >>> type(hq_access_1) "" - hq_access_1.created - '2021-01-01' + >>> hq_access_1.created + '2023-09-30T07:56:23.664150Z' The above works, but it requires three :py:meth:`~pynautobot.core.endpoint.Endpoint.get` calls. The next example demonstrates a simpler interface for creating a device @@ -118,27 +152,28 @@ by passing dictionary objects instead of using the Primary Key. The dictionaries passed for these fields use key/value pairs to lookup the Record with matching field/value pairs in the related Model. -The *Device Type*, *Device Role*, and *Site* Models all have a ``slug`` -field that can be used to lookup a specific Record. +The *Device Type* Model has ``model`` field, and *Role* and *Location* Models all have a ``name`` +field that can be used to lookup a specific Record. ``name`` is not unique for *Location*. .. code-block:: python - nautobot = api(url=url, token=token) - device_name = "hq-access-02" - - # Create new device using fields to uniquely identify foreign key relationships - devices = nautobot.dcim.devices - hq_access_2 = devices.create( - name=device_name, - device_type={"slug": "c9300-48"}, - device_role={"slug": "access"}, - site={"slug": "hq"}, - status="active", - ) - - # Show that device was created in Nautobot - hq_access_2.created - '2021-01-01' + >>> nautobot = api(url=url, token=token) + >>> + >>> device_name = "hq-access-02" + >>> + >>> # Create new device using fields to uniquely identify foreign key relationships + >>> devices = nautobot.dcim.devices + >>> hq_access_2 = devices.create( + ... name=device_name, + ... device_type={"model": "c9300-48"}, + ... role={"name": "access"}, + ... location="HQ", + ... status="Active", + ... ) + >>> + >>> # Show that device was created in Nautobot + >>> hq_access_2.created + '2023-09-30T08:02:03.872486Z' Creating Multiple Objects @@ -150,43 +185,42 @@ This is done by passing a list of dictionaries instead of keyword arguments. .. code-block:: python - nautobot = api(url=url, token=token) - - # Create multiple new devices with a single method call - devices = nautobot.dcim.devices - hq_access_multiple = devices.create([ - { - "name": "hq-access-03", - "device_type": {"slug": "c9300-48"}, - "device_role": {"slug": "access"}, - "site": {"slug": "hq"}, - "status": "active", - }, - { - "name": "hq-access-04", - "device_type": {"slug": "c9300-48"}, - "device_role": {"slug": "access"}, - "site": {"slug": "hq"}, - "status": "active", - }, - ]) - - # show that both devices were created in Nautobot - hq_access_multiple - [hq-access-03, hq-access-04] - - # We can access these Record objects as well - hq_access_03 = hq_access_multiple[0] - hq_access_03.created - '2021-01-01' - - # Use get calls to get the newly created devices - hq_access_03 = nautobot.dcim.devices.get(name="hq-access-03") - hq_access_03.created - '2021-01-01' - hq_access_04 = nautobot.dcim.devices.get(name="hq-access-04") - hq_access_04.created - '2021-01-01' + >>> nautobot = api(url=url, token=token) + >>> + >>> # Create multiple new devices with a single method call + >>> devices = nautobot.dcim.devices + >>> hq_access_multiple = devices.create([ + ... { + ... "name": "hq-access-03", + ... "device_type": {"model": "c9300-48"}, + ... "role": {"name": "access"}, + ... "location": {"name": "HQ"}, + ... "status": "Active", + ... }, + ... { + ... "name": "hq-access-04", + ... "device_type": {"model": "c9300-48"}, + ... "role": {"name": "access"}, + ... "location": {"name": "HQ"}, + ... "status": "Active", + ... }, + ... ]) + >>> + >>> # show that both devices were created in Nautobot + >>> hq_access_multiple + [, ] + >>> + >>> # We can access these Record objects as well + >>> hq_access_03 = hq_access_multiple[0] + >>> hq_access_03.created + '2023-09-30T08:14:24.756447Z' + >>> # Use get calls to get the newly created devices + >>> hq_access_03 = nautobot.dcim.devices.get(name="hq-access-03") + >>> hq_access_03.created + '2023-09-30T08:14:24.756447Z' + >>> hq_access_04 = nautobot.dcim.devices.get(name="hq-access-04") + >>> hq_access_04.created + '2023-09-30T08:14:24.790198Z' Common Errors @@ -208,24 +242,24 @@ Missing a Required Field A :py:exc:`~pynautobot.core.query.RequestError` is raised when a required field is not passed to the :py:meth:`~pynautobot.core.endpoint.Endpoint.create` method. -Creating a new *Device* requires passing the ``name``, ``device_type``, ``device_role``, ``site``, and ``status`` fields. +Creating a new *Device* requires passing the ``name``, ``device_type``, ``role``, ``location``, and ``status`` fields. The below example demonstrates passing only ``name`` and ``status`` when creating a *Device*; -as expected, an Exception is raised indicating that ``device_type``, ``device_role``, and ``site`` are also required fields. +as expected, an Exception is raised indicating that ``device_type``, ``role``, and ``location`` are also required fields. .. code-block:: python >>> hq_access_5 = devices.create( ... name="hq-access-05", - ... status="active", + ... status="Active", ... ) Traceback (most recent call last): ... pynautobot.core.query.RequestError: The request failed with code 400 Bad Request: { - 'device_type': ['This field is required.'], - 'device_role': ['This field is required.'], - 'site': ['This field is required.'] + 'device_type': ['This field is required.'], + 'role': ['This field is required.'], + 'location': ['This field is required.'] } @@ -248,18 +282,18 @@ one uses the Primary Key, and the other uses a dictionary to lookup the Record i >>> hq_access_5 = devices.create( ... name="hq-access-05", ... device_type='2302f2a1-2ed4-4ac9-a43a-285c95190071', - ... device_role={"slug": "access"}, - ... site={"slug": "hq"}, - ... status="active", + ... role={"name": "access"}, + ... location={"name": "HQ"}, + ... status="Active", ... ) Traceback (most recent call last): ... pynautobot.core.query.RequestError: The request failed with code 400 Bad Request: { - 'device_type': [ - 'Related object not found using the provided numeric ID: 2302f2a1-2ed4-4ac9-a43a-285c95190071' - ] + 'device_type': [ + "Related object not found using the provided attributes: {'pk': UUID('2302f2a1-2ed4-4ac9-a43a-285c95190071')}" + ] } .. code-block:: python @@ -267,20 +301,20 @@ one uses the Primary Key, and the other uses a dictionary to lookup the Record i >>> # Foreign Key by fields do not exist >>> hq_access_5 = devices.create( ... name="hq-access-05", - ... device_type={"slug": "non-existent-type"}, - ... device_role={"slug": "access"}, - ... site={"slug": "hq"}, - ... status="active", + ... device_type={"model": "non-existent-type"}, + ... role={"name": "access"}, + ... location={"name": "HQ"}, + ... status="Active", ... ) Traceback (most recent call last): ... pynautobot.core.query.RequestError: The request failed with code 400 Bad Request: { - 'device_type': [ - "Related object not found using the provided attributes: " \ - "{'slug': 'non-existent-type'}" - ] + 'device_type': [ + "Related object not found using the provided attributes: " \ + "{'model': 'non-existent-type'}" + ] } The final example uses a dictionary for ``device_type`` that matches multiple *Device Types* in the database. @@ -290,20 +324,20 @@ The final example uses a dictionary for ``device_type`` that matches multiple *D >>> # Non-unique data passed in for Foreign Key field >>> hq_access_5 = devices.create( ... name="hq-access-05", - ... device_type={"model": "c9300-48"}, - ... device_role={"slug": "access"}, - ... site={"slug": "hq"}, - ... status="active", + ... device_type={"manufacturer": { "name": "Cisco" } }, + ... role={"name": "access"}, + ... location={"name": "HQ"}, + ... status="Active", ... ) Traceback (most recent call last): ... pynautobot.core.query.RequestError: The request failed with code 400 Bad Request: { - 'device_type': [ - "Multiple objects match the provided attributes: " \ - "{'model': 'c9300-48'}" - ] + 'device_type': [ + "Multiple objects match the provided attributes: " \ + " {'manufacturer__name': 'Cisco'}" + ] } @@ -332,12 +366,12 @@ The first example passes a string instead of an integer. >>> hq_access_5 = devices.create( ... name="hq-access-05", ... device_type={"model": "c9300-48"}, - ... device_role={"slug": "access"}, - ... site={"slug": "hq"}, - ... status="active", + ... role={"name": "access"}, + ... location={"name": "HQ"}, + ... status="Active", ... rack={"name": "hq-001"}, - ... face=1, - ... position="high", + ... face="front", + ... position=1, ... ) Traceback (most recent call last): ... @@ -355,20 +389,19 @@ The last example specifies a rack unit higher than what is supported by *Rack* R >>> hq_access_5 = devices.create( ... name="hq-access-05", ... device_type={"model": "c9300-48"}, - ... device_role={"slug": "access"}, - ... site={"slug": "hq"}, - ... status="active", + ... role={"name": "access"}, + ... location={"name": "HQ"}, + ... status={"name": "Active"}, ... rack={"name": "hq-001"}, - ... face=1, - ... position="high", + ... face="front", + ... position=1, ... ) Traceback (most recent call last): ... pynautobot.core.query.RequestError: The request failed with code 400 Bad Request: { - 'position': [ - 'U100 is already occupied or does not have sufficient space' \ - 'to accommodate this device type: c9300-48 (1U)' - ] + 'non_field_errors': [ + 'The position and face is already occupied on this rack. The fields rack, position, face must make a unique set.' + ] } diff --git a/docs/advanced/graphql.rst b/docs/advanced/graphql.rst index 3ef91be..d516687 100644 --- a/docs/advanced/graphql.rst +++ b/docs/advanced/graphql.rst @@ -22,7 +22,6 @@ to the above ``nautobot`` object upon initialization. The :py:meth:`~pynautobot.core.graphql.GraphQLQuery.query` method is used to perform queries against Nautobot's GraphQL endpoint. - Making a GraphQL Query ---------------------- @@ -31,40 +30,41 @@ that a query string is passed into it. The method retuns a :py:class:`~pynautobot.core.graphql.GraphQLRecord` object as discussed in :ref:`The GraphQLRecord Object` section. -This example demonstrates how to fetch the `id`, `name`, and `region name` for all *Sites*. +This example demonstrates how to fetch the `id`, `name`, and `parent name` for all *Locations*. .. code-block:: python >>> # Build a query string >>> query = """ ... query { - ... sites { + ... locations { ... id ... name - ... region { + ... parent { ... name ... } ... } ... } ... """ - + >>> >>> # Make a graphql query >>> graphql_response = nautobot.graphql.query(query=query) - + >>> >>> # Show that a GraphQLRecord is returned - GraphQLRecord(json={'data': {'sites': [{'id': '2cfbc91e-361f-4129-9db6-bc21a6f88d38', 'name': 'ams', ..., status_code=200) + >>> graphql_response + GraphQLRecord(json={'data': {'locations': [{'id': ..., status_code=200) -The next example performs the same query, but restricts it to only the ``den`` site. +The next example performs the same query, but restricts it to only the ``HQ`` location. .. code-block:: python - >>> # Build a query string restricting only to den site + >>> # Build a query string restricting only to HQ location >>> query = """ ... query { - ... sites (name: "den") { + ... locations (name: "HQ") { ... id ... name - ... region { + ... parent { ... name ... } ... } @@ -72,46 +72,44 @@ The next example performs the same query, but restricts it to only the ``den`` s ... """ >>> graphql_response = nautobot.graphql.query(query=query) >>> graphql_response - GraphQLRecord(json={'data': {'sites': [{'id': '45399b54-47f9-4eec-86e3-47352e103b1b', 'name': 'den', 'region': {'name': 'United States'}}]}}, status_code=200) + GraphQLRecord(json={'data': {'locations': [{'id': ..., 'name': 'HQ', 'parent': {'name': 'US'}}]}}, status_code=200) .. tip:: - Nautobot's `GraphQL documentation `_ + Nautobot's `GraphQL documentation `_ provides a summary of making queries. Nautobot's browsable API also provides a `graphiql` interface to aid in developing query strings at `/graphql/` - Making a GraphQL Query with Variables ------------------------------------- The :py:meth:`~pynautobot.core.graphql.GraphQLQuery.query` method supports using variables in the query string by passing in an optional ``variables`` argument. This argument is a dictionary, with the `key` being the variable name, and the `value` being the value to use for the variable in the query string. -This example is the same as the previous one, except the site name is now derived using variables. +This example is the same as the previous one, except the location name is now derived using variables. .. code-block:: python >>> # Create a variables dictionary - >>> variables = {"site_name": "den"} - + >>> variables = {"location_name": "HQ"} + >>> >>> # Create a query string that takes variables >>> query = """ - ... query ($site_name:String!) { - ... sites (name: $site_name) { + ... query ($location_name:String!) { + ... locations (name: [$location_name]) { ... id ... name - ... region { + ... parent { ... name ... } ... } ... } ... """ - + >>> >>> # Use the query method with variables >>> graphql_response = nautobot.graphql.query(query=query, variables=variables) >>> graphql_response - GraphQLRecord(json={'data': {'sites': [{'id': '45399b54-47f9-4eec-86e3-47352e103b1b', 'name': 'den', 'region': {'name': 'United States'}}]}}, status_code=200) - + GraphQLRecord(json={'data': {'locations': [{'id': ..., 'name': 'HQ', 'parent': {'name': 'US'}}]}}, status_code=200) The GraphQLRecord Object ------------------------ @@ -122,13 +120,13 @@ This example shows accessing data from the previous query. .. code-block:: python - >>> variables = {"site_name": "den"} + >>> variables = {"location_name": "HQ"} >>> query = """ - ... query ($site_name:String!) { - ... sites (name: $site_name) { + ... query ($location_name:String!) { + ... locations (name: [$location_name]) { ... id ... name - ... region { + ... parent { ... name ... } ... } @@ -138,21 +136,20 @@ This example shows accessing data from the previous query. >>> graphql_response.json { 'data': { - 'sites': [ + 'locations': [ { - 'id': '45399b54-47f9-4eec-86e3-47352e103b1b', - 'name': 'den', - 'region': { - 'name': 'United States' + 'id': ..., + 'name': 'HQ', + 'parent': { + 'name': 'US' } } ] } } - >>> # Get the name of the first site - >>> graphql_response.json["data"]["sites"][0]["name"] - 'den' - + >>> # Get the name of the first location + >>> graphql_response.json["data"]["locations"][0]["name"] + 'HQ' Saving Changes -------------- diff --git a/docs/advanced/read.rst b/docs/advanced/read.rst index bf85f05..babe9c6 100644 --- a/docs/advanced/read.rst +++ b/docs/advanced/read.rst @@ -8,7 +8,6 @@ for retrieving :py:class:`~pynautobot.core.response.Record` objects from Nautobo * The :py:meth:`~pynautobot.core.endpoint.Endpoint.filter` method will return a list of Records. * The :py:meth:`~pynautobot.core.endpoint.Endpoint.all` method will return all Records for the Model. - Using the Get Method -------------------- @@ -19,15 +18,15 @@ which is the ID for most objects. .. code-block:: python - >>> dev = nautobot.dcim.devices.get('2302f2a1-2ed4-4ac9-a43a-285c95190071') - >>> dev.name + >>> device = nautobot.dcim.devices.get('2302f2a1-2ed4-4ac9-a43a-285c95190071') + >>> device.name 'hq-access-01' - >>> dev.status + >>> device.status Active - >>> dev.device_type + >>> device.device_type c9300-48 - >>> dev.device_role - Access + >>> device.role + .. note:: If an entry with the specified value for the PK does not exist, @@ -39,14 +38,13 @@ If multiple Records are matched, then a ``ValueError`` is raised. .. code-block:: python - >>> dev = nautobot.dcim.devices.get(model="CSR1000V") + >>> device = nautobot.dcim.devices.get(device_type="c9300-48") Traceback (most recent call last): ... ValueError: get() returned more than one result. Check that the kwarg(s) passed are valid for this endpoint or use filter() or all() instead. - Using the Filter Method ----------------------- @@ -60,7 +58,6 @@ This method also supports: * filtering based on custom fields * filtering with lookup expressions - Basic Usage ^^^^^^^^^^^ @@ -72,50 +69,51 @@ but will return all matches using :py:meth:`~pynautobot.core.endpoint.Endpoint.f .. code-block:: python - >>> # Get all CSR1000V devices - >>> devices = nautobot.dcim.devices.filter(model="CSR1000V") - + >>> # Get all c9300-48 devices + >>> devices = nautobot.dcim.devices.filter(device_type="c9300-48") + >>> >>> # Show a list of Records are returned - >>> devices - [jcy-bb-01.infra.ntc.com, jcy-rtr-01.infra.ntc.com, jcy-rtr-02.infra.ntc.com] - - >>> # Show accessing data from the first CSR1000V device - >>> dev1 = devices[0] - >>> dev1.name - 'jcy-bb-01.infra.ntc.com' - >>> dev1.status - Active - + >>> pprint(devices) + [, + , + , + ] + >>> + >>> # Show accessing data from the first c9300-48 device + >>> device1 = devices[0] + >>> device1.name + 'hq-access-01' + >>> device1.status + Filtering with OR logic ^^^^^^^^^^^^^^^^^^^^^^^ The :py:meth:`~pynautobot.core.endpoint.Endpoint.filter` method allows using an **OR** condition by passing in a list of values to match against the field. -The example below gets all devices located in either *Site* ``hq`` or ``dc``. +The example below gets all devices located in either *Location* ``HQ`` or ``DC``. .. code-block:: python >>> # There are 100 devices total >>> nautobot.dcim.devices.count() 100 - - >>> # There are 20 dc devices - >>> dev_dc_site = nautobot.dcim.devices.filter(site="dc") - >>> len(dev_dc_site) + >>> + >>> # There are 20 DC devices + >>> dev_dc_location = nautobot.dcim.devices.filter(location="DC") + >>> len(dev_dc_location) 20 - - >>> # There are 5 hq devices - >>> dev_hq_site = nautobot.dcim.devices.filter(site="hq") - >>> len(dev_hq_site) + >>> + >>> # There are 5 HQ devices + >>> dev_hq_location = nautobot.dcim.devices.filter(location="HQ") + >>> len(dev_hq_location) 5 - - # The filter method will grab all devices in both sites - >>> dev_hq_dc_sites = nautobot.dcim.devices.filter(site=["hq", "dc"]) - >>> len(dev_all_sites) + >>> + # The filter method will grab all devices in both locations + >>> dev_hq_dc_locations = nautobot.dcim.devices.filter(location=["HQ", "DC"]) + >>> len(dev_hq_dc_locations) 25 - Filtering based on a Custom Field ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,13 +127,13 @@ by passing the ``cf_owner`` keyword argument. >>> devices = nautobot.dcim.devices.filter(cf_owner="John Smith") >>> devices - [switch0, switch1] - + [, + ] + >>> >>> # Show device has an owner of "John Smith" >>> devices[0].custom_fields["owner"] 'John Smith' - Filtering with Lookup Expressions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -151,19 +149,18 @@ There are several expressions that can be used; they generally cover things like * case insensitivity The example below shows how use negation with *__n*. -From the previous examples, there are 100 devices total, and 25 are located in either the `dc` or `hq` site. -Using ``site__n`` to get the negation of these sites returns 75 devices. +From the previous examples, there are 100 devices total, and 25 are located in either the `DC` or `HQ` location. +Using ``location__n`` to get the negation of these locations returns 75 devices. .. code-block:: - >>> devices = nautobot.dcim.devices.filter(site__n=["hq", "dc"]) + >>> devices = nautobot.dcim.devices.filter(location__n=["HQ", "DC"]) >>> len(devices) 75 - - >>> # Show the device is not in either hq or dc site - >>> devices[0].site - branch1 - + >>> + >>> # Show the device is not in either HQ or DC location + >>> devices[0].location + Using the All Method -------------------- @@ -176,15 +173,11 @@ This will return a list of all :py:class:`~pynautobot.core.response.Record` obje >>> devices = nautobot.dcim.devices.all() >>> len(devices) 100 - >>> dev1 = devices[0] - >>> dev1.name + >>> device1 = devices[0] + >>> device1.name 'hq-access-01' - >>> dev1.status + >>> device1.status Active -.. tip:: - Both ``filter`` and ``all`` can use threading by passing - in ``use_threading=True`` when instantiating the ``api`` object. - The following two pages cover interacting with the returned :py:class:`~pynautobot.core.response.Record` objects. The next page covers additional Update operations, which is followed by a discussion of other features and methods. diff --git a/docs/advanced/record.rst b/docs/advanced/record.rst index 0afd52d..645b863 100644 --- a/docs/advanced/record.rst +++ b/docs/advanced/record.rst @@ -3,7 +3,6 @@ Interacting With A Record We already know that we can access attributes on the record, but what else can we do? - NAPALM ------ @@ -13,15 +12,12 @@ Here we can run the ``get_facts`` getter. .. code-block:: python - dev1.napalm.list(method='get_facts') - {"get_facts": {"interface_list": ["ge-0/0/0"]}} - + >>> device1.napalm.list(method='get_facts') + {"get_facts": {"interface_list": ["ge-0/0/0"]}} Accessing Field Data -------------------- - - Serialize ^^^^^^^^^ @@ -29,117 +25,143 @@ Instead of accessing the device and only receiving the name, you can use the :py .. code-block:: python - import json - >>> print(json.dumps(dev1.serialize(), indent=4)) - { - "id": "ea354978-471a-45a2-a438-92cfc046df0b", - "url": "http://localhost:8000/api/dcim/devices/102/", - "name": "hq-access-01", - "display_name": "hq-access-01", - "device_type": 2, - "device_role": 2, - "tenant": null, - "platform": null, - "serial": "", - "asset_tag": null, - "site": 2, - "rack": null, - "position": null, - "face": null, - "parent_device": null, - "status": "active", - "primary_ip": null, - "primary_ip4": null, - "primary_ip6": null, - "cluster": null, - "virtual_chassis": null, - "vc_position": null, - "vc_priority": null, - "comments": "", - "local_context_data": null, - "tags": [], - "custom_fields": {}, - "config_context": {}, - "created": "2021-02-17", - "last_updated": "2021-02-17T17:46:44.788078Z" - } + >>> import json + >>> print(json.dumps(device1.serialize(), indent=4)) + { + "id": "86924375-4b50-4f95-a1c7-99896ab03307", + "object_type": "dcim.device", + "display": "hq-access-01", + "url": "http://nautobot:8080/api/dcim/devices/86924375-4b50-4f95-a1c7-99896ab03307/", + "natural_slug": "hq-access-01__hq_8692", + "face": null, + "local_config_context_data": null, + "local_config_context_data_owner_object_id": null, + "name": "hq-access-01", + "serial": "", + "asset_tag": null, + "position": null, + "device_redundancy_group_priority": null, + "vc_position": null, + "vc_priority": null, + "comments": "", + "local_config_context_schema": null, + "local_config_context_data_owner_content_type": null, + "device_type": "a99de3bf-9a81-4645-9828-b00866de94a5", + "status": "44a25fa2-ee88-47ed-b004-4dd36e54706f", + "role": "ca552e01-bb63-4742-be5c-d27e62ae3e50", + "tenant": null, + "platform": null, + "location": "fb720cca-ee59-4b76-9322-dfbbdaa5d052", + "rack": null, + "primary_ip4": null, + "primary_ip6": null, + "cluster": null, + "virtual_chassis": null, + "device_redundancy_group": null, + "secrets_group": null, + "created": "2023-09-30T07:56:23.664150Z", + "last_updated": "2023-09-30T07:56:23.664168Z", + "tags": [], + "notes_url": "http://nautobot:8080/api/dcim/devices/86924375-4b50-4f95-a1c7-99896ab03307/notes/", + "custom_fields": {}, + "parent_bay": null + } You may have noticed that any field that is a foreign key relationship only provides the ID. We need to cast to a dictionary to see the actual sub keys. .. code-block:: python - >>> print(json.dumps(dict(dev1), indent=4)) - { - "id": "2d7c20dc-78a8-44af-961b-56d418c14bea", - "url": "http://localhost:8000/api/dcim/devices/102/", - "name": "hq-access-01", - "display_name": "hq-access-01", - "device_type": { - "id": "100fa8e8-381b-4f25-b2cd-10c99cdef523", - "url": "http://localhost:8000/api/dcim/device-types/2/", - "manufacturer": { - "id": "e14f5b2b-bf5f-449f-b089-495b73657cf5", - "url": "http://localhost:8000/api/dcim/manufacturers/1/", - "name": "Cisco", - "slug": "cisco" - }, - "model": "c9300-48", - "slug": "c9300-48", - "display_name": "Cisco c9300-48" - }, - "device_role": { - "id": "022d3ff6-b08d-4380-9daa-8e16c6fed5ec", - "url": "http://localhost:8000/api/dcim/device-roles/2/", - "name": "Access", - "slug": "access" - }, - "tenant": null, - "platform": null, - "serial": "", - "asset_tag": null, - "site": { - "id": "09df769c-af34-45f8-950a-94c268d48464", - "url": "http://localhost:8000/api/dcim/sites/2/", - "name": "HQ", - "slug": "hq" - }, - "rack": null, - "position": null, - "face": null, - "parent_device": null, - "status": { - "value": "active", - "label": "Active" - }, - "primary_ip": null, - "primary_ip4": null, - "primary_ip6": null, - "cluster": null, - "virtual_chassis": null, - "vc_position": null, - "vc_priority": null, - "comments": "", - "local_context_data": null, - "tags": [], - "custom_fields": {}, - "config_context": {}, - "created": "2021-02-17", - "last_updated": "2021-02-17T17:46:44.788078Z" - } - + >>> print(json.dumps(dict(device1), indent=4)) + { + "id": "86924375-4b50-4f95-a1c7-99896ab03307", + "object_type": "dcim.device", + "display": "hq-access-01", + "url": "http://nautobot:8080/api/dcim/devices/86924375-4b50-4f95-a1c7-99896ab03307/", + "natural_slug": "hq-access-01__hq_8692", + "face": null, + "local_config_context_data": null, + "local_config_context_data_owner_object_id": null, + "name": "hq-access-01", + "serial": "", + "asset_tag": null, + "position": null, + "device_redundancy_group_priority": null, + "vc_position": null, + "vc_priority": null, + "comments": "", + "local_config_context_schema": null, + "local_config_context_data_owner_content_type": null, + "device_type": { + "id": "a99de3bf-9a81-4645-9828-b00866de94a5", + "object_type": "dcim.devicetype", + "url": "http://nautobot:8080/api/dcim/device-types/a99de3bf-9a81-4645-9828-b00866de94a5/" + }, + "status": { + "id": "44a25fa2-ee88-47ed-b004-4dd36e54706f", + "object_type": "extras.status", + "url": "http://nautobot:8080/api/extras/statuses/44a25fa2-ee88-47ed-b004-4dd36e54706f/", + "display": "Active", + "natural_slug": "active_44a2", + "content_types": [ + "circuits.circuit", + "dcim.device", + "dcim.powerfeed", + "dcim.rack", + "ipam.ipaddress", + "ipam.prefix", + "ipam.vlan", + "virtualization.virtualmachine", + "virtualization.vminterface", + "dcim.interface", + "dcim.location", + "dcim.deviceredundancygroup", + "dcim.interfaceredundancygroup" + ], + "name": "Active", + "color": "4caf50", + "description": "Unit is active", + "created": "2023-09-30T00:00:00Z", + "last_updated": "2023-09-30T06:06:44.559130Z", + "notes_url": "http://nautobot:8080/api/extras/statuses/44a25fa2-ee88-47ed-b004-4dd36e54706f/notes/", + "custom_fields": {} + }, + "role": { + "id": "ca552e01-bb63-4742-be5c-d27e62ae3e50", + "object_type": "extras.role", + "url": "http://nautobot:8080/api/extras/roles/ca552e01-bb63-4742-be5c-d27e62ae3e50/" + }, + "tenant": null, + "platform": null, + "location": { + "id": "fb720cca-ee59-4b76-9322-dfbbdaa5d052", + "object_type": "dcim.location", + "url": "http://nautobot:8080/api/dcim/locations/fb720cca-ee59-4b76-9322-dfbbdaa5d052/" + }, + "rack": null, + "primary_ip4": null, + "primary_ip6": null, + "cluster": null, + "virtual_chassis": null, + "device_redundancy_group": null, + "secrets_group": null, + "created": "2023-09-30T07:56:23.664150Z", + "last_updated": "2023-09-30T07:56:23.664168Z", + "tags": [], + "notes_url": "http://nautobot:8080/api/dcim/devices/86924375-4b50-4f95-a1c7-99896ab03307/notes/", + "custom_fields": {}, + "parent_bay": null + } Record Hashes and Equality Comparison ------------------------------------- - Record Hash ^^^^^^^^^^^ The hash of a record is made from a combination of the name of the endpoint and its ID. If the ID does not exist, then it will be a hash of **only** the endpoint name. If an ID does exist then the hash will be of the tuple representing `(endpoint.name, id)`. - Equality Comparison ^^^^^^^^^^^^^^^^^^^ @@ -148,24 +170,24 @@ then a equals comparison will return True, even though there is a different data .. code-block:: python - # Assign den-rtr01 to dev1, then to dev2 - >>> dev1 = nautobot.dcim.devices.get(name="den-rtr01") - >>> dev2 = nautobot.dcim.devices.get(name="den-rtr01") - >>> dev1 == dev2 + >>> # Assign hq-access-01 to device1, then to device2 + >>> device1 = nautobot.dcim.devices.get(name="hq-access-01") + >>> device2 = nautobot.dcim.devices.get(name="hq-access-01") + >>> device1 == device2 True - >>> dev2.platform + >>> device2.platform Cisco IOS # Change the platform - >>> dev2.platform = "Cisco NXOS" - >>> dev2.platform + >>> device2.platform = "Cisco NXOS" + >>> device2.platform 'Cisco NXOS' # Compare the devices, since the ID nor the - >>> dev1 == dev2 + >>> device1 == device2 True A comparison can be made on individual attributes of an object: .. code-block:: python - >>> dev1.platform == dev2.platform + >>> device1.platform == device2.platform False diff --git a/docs/advanced/session.rst b/docs/advanced/session.rst index 037ccde..313acf6 100644 --- a/docs/advanced/session.rst +++ b/docs/advanced/session.rst @@ -10,7 +10,6 @@ A few examples are provided below: * :ref:`SSL Verification` * :ref:`Timeouts` - Headers ------- @@ -31,11 +30,10 @@ The example below shows how to update a Token if it has been cycled. # Update Session object with new header nautobot.http_session.headers["Authorization"] = new_token - SSL Verification ---------------- -Handling SSL Verification is documented `here `_. +Handling SSL verification is documented `here `_. The below example shows how to disable SSL verification. .. code-block:: python @@ -48,7 +46,6 @@ The below example shows how to disable SSL verification. ) nautobot.http_session.verify = False - Timeouts -------- diff --git a/docs/advanced/update.rst b/docs/advanced/update.rst index c0d9f52..ed08788 100644 --- a/docs/advanced/update.rst +++ b/docs/advanced/update.rst @@ -9,7 +9,6 @@ and call the :py:meth:`~pynautobot.core.response.Record.save` method. The main difference with this approach is that changes are not synced to Nautobot until the :py:meth:`~pynautobot.core.response.Record.save` method is called. - Modifying a Record by Attribute Updates --------------------------------------- @@ -22,28 +21,27 @@ The below example will: .. code-block:: >>> device = nautobot.dcim.devices.get(name="hq-access-03") - + >>> >>> # Show that device is active >>> device.status - Active - + + >>> >>> # Update status and name fields >>> device.comments = "removed from service" - >>> device.status = "decommissioned" - + >>> device.status = "Decommissioned" + >>> >>> # Show that changes haven't been synced >>> tmp_device = nautobot.dcim.devices.get(name="hq-access-03") >>> tmp_device.status - Active - + + >>> >>> # Save updates and show that changes have been synced >>> device.save() >>> updated_device = nautobot.dcim.devices.get(name="hq-access-03") >>> updated_device.comments 'removed from service' >>> updated_device.status - Decommissioned - + Errors with updates ------------------- @@ -58,25 +56,17 @@ method and returns an exception immediately. The second example modifies the objects ``position`` attribute, and the exception is not raised until the :py:meth:`~pynautobot.core.response.Record.save` method is called. - Invalid Type ^^^^^^^^^^^^ .. code-block:: python >>> # Get a device record - >>> hq_access_5 = devices.get(name="hq-access-05") - + >>> hq_access_4 = devices.get(name="hq-access-04") + >>> >>> # Attempt to update position with an invalid type - >>> hq_access_5.update({"postition": "high"}) - Traceback (most recent call last): - ... - pynautobot.core.query.RequestError: - The request failed with code 400 Bad Request: - { - 'position': ['A valid integer is required.'] - } - + >>> hq_access_4.update({"postition": "high"}) + False Invalid Schema ^^^^^^^^^^^^^^ @@ -84,13 +74,13 @@ Invalid Schema .. code-block:: python >>> # Get a device record - >>> hq_access_5 = devices.get(name="hq-access-05") - + >>> hq_access_4 = devices.get(name="hq-access-04") + >>> >>> # Attempt to provide invalid rack unit for position - >>> hq_access_5.position = 100 - + >>> hq_access_4.position = 100 + >>> >>> # The exception is only raised when save() is called - >>> hq_access_5.save() + >>> hq_access_4.save() Traceback (most recent call last): ... pynautobot.core.query.RequestError: @@ -102,7 +92,6 @@ Invalid Schema ] } - Atomic ^^^^^^ @@ -115,16 +104,16 @@ and fetching the object from Nautobot shows that ``face`` has also been left unc .. code-block:: python >>> # Get a device record - >>> hq_access_5 = devices.get(name="hq-access-05") - + >>> hq_access_4 = devices.get(name="hq-access-04") + >>> >>> # Set the face attribute - >>> hq_access_5.face = "front" - + >>> hq_access_4.face = "front" + >>> >>> # Attempt to provide invalid rack unit for position - >>> hq_access_5.position = 100 - + >>> hq_access_4.position = 100 + >>> >>> # An exception is raised - >>> hq_access_5.save() + >>> hq_access_4.save() Traceback (most recent call last): ... pynautobot.core.query.RequestError: @@ -137,23 +126,22 @@ and fetching the object from Nautobot shows that ``face`` has also been left unc } >>> # Show that the object's face field has not changed - >>> tmp_hq_access_5 = devices.get(name="hq-access-05") - >>> tmp_hq_access_5.face is None + >>> tmp_hq_access_4 = devices.get(name="hq-access-04") + >>> tmp_hq_access_4.face is None True - + >>> >>> # Fix the position field and retrigger update - >>> hq_access_5.position = 42 - >>> hq_access_5.save() + >>> hq_access_4.position = 42 + >>> hq_access_4.save() True - + >>> >>> # Show that updates have taken affect - >>> tmp_hq_access_5 = devices.get(name="hq-access-05") - >>> tmp_hq_access_5.face - Front - >>> tmp_hq_access_5.position + >>> tmp_hq_access_4 = devices.get(name="hq-access-04") + >>> tmp_hq_access_4.face + + >>> tmp_hq_access_4.position 42 - Updating objects without loading data ------------------------------------- @@ -171,23 +159,24 @@ The examples updates a Device record, however this can apply to other API .. code-block:: python - import os - from pynautobot import api - - url = os.environ["NAUTOBOT_URL"] - token = os.environ["NAUTOBOT_TOKEN"] - nautobot = api(url=url, token=token) - - # Update status and name fields - result = nautobot.dcim.devices.update( - id="491d799a-2b4d-41fc-80e1-7c5cbb5b71b6", - data={ - "comments": "removed from service", - "status": "decommissioned", - }, - ) - - print(result) # will output True if successful + >>> import os + >>> from pynautobot import api + >>> + >>> url = os.environ["NAUTOBOT_URL"] + >>> token = os.environ["NAUTOBOT_TOKEN"] + >>> nautobot = api(url=url, token=token) + >>> + >>> # Update status and name fields + >>> result = nautobot.dcim.devices.update( + >>> id="491d799a-2b4d-41fc-80e1-7c5cbb5b71b6", + >>> data={ + >>> "comments": "removed from service", + >>> "status": "Decommissioned", + >>> }, + >>> ) + >>> + >>> result + True References: diff --git a/docs/basic/api.rst b/docs/basic/api.rst index 7fabc91..1d970e0 100644 --- a/docs/basic/api.rst +++ b/docs/basic/api.rst @@ -6,22 +6,30 @@ passing in the proper URL and a valid Token. The code sample below assumes that the token has been stored as an environment variable, and uses the builtin :py:mod:`os` module to retrieve it. -.. code-block:: python - - import os +.. note:: - from pynautobot import api + To display dictionaries or other objects in examples, the ``pprint`` package is used. To install it run ``pip install pprint``. - url = "https://demo.nautobot.com" +.. code-block:: python - # Retrieve token from system environment variable - # token = os.environ["NAUTOBOT_TOKEN"] - token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - nautobot = api(url=url, token=token) + >>> import os + >>> + >>> from pprint import pprint + >>> + >>> from pynautobot import api + >>> + >>> url = "https://next.demo.nautobot.com" + >>> + >>> # Retrieve token from system environment variable + >>> # token = os.environ["NAUTOBOT_TOKEN"] + >>> token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + >>> nautobot = api(url=url, token=token) + >>> nautobot + .. tip:: - Creating a `token `_ in Nautobot. + Creating a `token `_ in Nautobot. Nautobot Info and Apps @@ -44,27 +52,61 @@ The core Apps are: .. code-block:: python >>> nautobot = api(url=url, token=token) - + >>> >>> # View version of Nautobot >>> nautobot.version - '1.0' - + '2.0' + >>> >>> # View various details about Nautobot - >>> nautobot.status() - { - 'django-version': '3.1.3', - 'installed-apps': {...}, - 'nautobot-version': '1.0.3+5de17ddd', - 'plugins': { - 'nautobot_healthcheck': '0.0.1' - }, - 'python-version': '3.7.9', - 'rq-workers-running': 2 - } - + >>> pprint(nautobot.status()) + {'celery-workers-running': 0, + 'django-version': '3.2.21', + 'installed-apps': {'constance': '2.9.1', + 'constance.backends.database': None, + 'corsheaders': None, + 'db_file_storage': None, + 'debug_toolbar': '4.1.0', + 'django.contrib.admin': None, + 'django.contrib.auth': None, + 'django.contrib.contenttypes': None, + 'django.contrib.humanize': None, + 'django.contrib.messages': None, + 'django.contrib.sessions': None, + 'django.contrib.staticfiles': None, + 'django_ajax_tables': None, + 'django_celery_beat': '2.5.0..', + 'django_celery_results': '2.4.0..', + 'django_extensions': '3.2.3', + 'django_filters': '23.1', + 'django_jinja': '3.2.21.final.0', + 'django_prometheus': '2.3.1', + 'django_tables2': '2.6.0', + 'drf_spectacular': '0.26.3', + 'drf_spectacular_sidecar': '2023.9.1', + 'example_plugin': '1.0.0', + 'graphene_django': '2.16.0', + 'health_check': None, + 'health_check.storage': None, + 'nautobot.circuits': None, + 'nautobot.core': None, + 'nautobot.dcim': None, + 'nautobot.extras': None, + 'nautobot.extras.tests.example_plugin_dependency': None, + 'nautobot.ipam': None, + 'nautobot.tenancy': None, + 'nautobot.users': None, + 'nautobot.virtualization': None, + 'rest_framework': '3.14.0', + 'social_django': '5.2.0', + 'taggit': '4.0.0', + 'timezone_field': '5.1'}, + 'nautobot-version': '2.0.0', + 'plugins': {'example_plugin': '1.0.0'}, + 'python-version': '3.8.18'} + >>> >>> # Show that the dcim app is available >>> nautobot.dcim - + The main purpose of :py:class:`~pynautobot.core.app.App` objects is to provide access to :ref:`Models ` and their data. @@ -76,7 +118,7 @@ Models Pynautobot :py:class:`~pynautobot.core.app.App` objects will treat all unknown attributes as :py:class:`Endpoints `. The :py:class:`~pynautobot.core.endpoint.Endpoint` class is used to represent Models in Nautobot. -For example, the Nautobot DCIM App contains Models, such as: *Devices*, *Platforms*, and *Device Roles*. +For example, the Nautobot DCIM App contains Models, such as: *Devices*, *Platforms*, and *Roles*. The pynautobot ``dcim`` :py:class:`~pynautobot.core.app.App` does not provide attributes to represent these Models, however, :py:class:`~pynautobot.core.endpoint.Endpoint` objects are created upon attribute access. @@ -86,23 +128,21 @@ but the ``devices`` Model is still accessible from it. .. code-block:: python >>> nautobot = api(url=url, token=token) - + >>> >>> # Show that the devices attribute does not exist on the dcim object - >>> nautobot.dcim.__dict__ - { - 'api': , - 'name': 'dcim', - '_choices': None, - 'model': >> pprint(nautobot.dcim.__dict__) + {'_choices': None, + 'api': , + 'model': , + 'name': 'dcim'} + >>> >>> # Show that the devices attribute is accessible and >>> # is an Endpoint object corresponding to the Devices Model >>> devices = nautobot.dcim.devices >>> devices - + >>> devices.url - 'https://demo.nautobot.com/api/dcim/devices' + 'https://next.demo.nautobot.com/api/dcim/devices' .. note:: @@ -111,19 +151,19 @@ but the ``devices`` Model is still accessible from it. Some Models in Nautobot have names that contain more than a single word. In order to access these Models, the names should be joined with an underscore. -The above example of *Device Roles* would use ``device_roles``. +The above example of *Roles* would use ``roles``. Pynautobot will automatically convert the underscore into a hyphen for access to the Nautobot API endpoint. .. code-block:: python >>> nautobot = api(url=url, token=token) - + >>> >>> # Show using an underscore to access Models with multi-word names. - >>> device_roles = nautobot.dcim.device_roles - + >>> roles = nautobot.extras.roles + >>> >>> # Show that the URL converts the underscore to a hyphen - >>> device_roles.url - 'https://demo.nautobot.com/api/dcim/device-roles' + >>> roles.url + 'https://next.demo.nautobot.com/api/extras.roles' .. note:: diff --git a/docs/basic/crud/create.rst b/docs/basic/crud/create.rst index 26fc979..c6b6749 100644 --- a/docs/basic/crud/create.rst +++ b/docs/basic/crud/create.rst @@ -6,17 +6,17 @@ All fields supported by the Model in Nautobot can be passed into the method, and .. code-block:: python - nautobot = api(url=url, token=token) - device_roles = nautobot.dcim.device_roles - - # Create a dict of keyword arguments to use for device role config. - access_role_config = { - "name": "Access Switch", - "slug": "access-switch", - } - - # Create a new Record in the Device Roles Model. - access_role = device_roles.create(**access_role_config) + >>> nautobot = api(url=url, token=token) + >>> roles = nautobot.extras.roles + >>> + >>> # Create a dict of keyword arguments to use for role config. + >>> access_role_config = { + ... "name": "Access Switch", + ... "content_types": ["dcim.device"], + ... } + >>> + >>> # Create a new Record in the Roles Model. + >>> access_role = roles.create(**access_role_config) The :py:meth:`~pynautobot.core.endpoint.Endpoint.create` method adds a new Record into the Nautobot database, and a representative :py:class:`~pynautobot.core.response.Record` object is returned. @@ -29,9 +29,7 @@ The following code block is a continuation of the previous one. >>> # are accessible attributes with expected values >>> access_role.name 'Access Switch' - >>> access_role.slug - 'access-switch' - + >>> >>> # Show that fields not passed to the method >>> # were assigned values by the Model >>> access_role.description diff --git a/docs/basic/crud/delete.rst b/docs/basic/crud/delete.rst index 489e12a..3418c4d 100644 --- a/docs/basic/crud/delete.rst +++ b/docs/basic/crud/delete.rst @@ -8,15 +8,15 @@ This method will return a boolean to indicate whether or not the Record was succ .. code-block:: python >>> nautobot = api(url=url, token=token) - >>> device_roles = nautobot.dcim.device_roles - - >>> # Get the record object for the access-switch device role - >>> access_role = device_roles.get(slug="access-switch") - + >>> roles = nautobot.extras.roles + >>> + >>> # Get the record object for the access-switch role + >>> access_role = roles.get(name="Access Switch") + >>> >>> # Show deleting the Record >>> access_role.delete() True - - >>> # Show that the "access-switch" Device Role was deleted - >>> device_roles.get(slug="access-switch") - ValueError ... + >>> + >>> # Show that the "access-switch" Role was deleted + >>> pprint(roles.get(name="Access Switch")) + None diff --git a/docs/basic/crud/read.rst b/docs/basic/crud/read.rst index 05338a5..ad40f0e 100644 --- a/docs/basic/crud/read.rst +++ b/docs/basic/crud/read.rst @@ -5,15 +5,15 @@ Pynautobot's :py:class:`` objects also provid to retrieve the :py:class:`Records ` stored in the Nautobot database. The :py:meth:`~pynautobot.core.endpoint.Endpoint.get` method can be used to retrieve a single :ref:`Record `. The most common way to use this method is to pass keyword arguments mapping the -Record's :ref:`fields ` with its value, such as ``slug="access-switch"``. +Record's :ref:`fields ` with its value, such as ``name="Access Switch"``. .. code-block:: python - nautobot = api(url=url, token=token) - device_roles = nautobot.dcim.device_roles - - # Show getting a record using a keyword argument - access_role = device_roles.get(slug="access-switch") + >>> nautobot = api(url=url, token=token) + >>> roles = nautobot.extras.roles + >>> + >>> # Show getting a record using a keyword argument + >>> access_role = roles.get(name="Access Switch") .. note:: Multiple keyword arguments can be supplied if needed to uniquely identify a single entry. @@ -26,8 +26,6 @@ from the :py:meth:`~pynautobot.core.endpoint.Endpoint.create` method in :ref:`Cr >>> access_role.name 'Access Switch' - >>> access_role.slug - 'access-switch' >>> access_role.description '' >>> # Show that the primary key has the same value from create object @@ -40,20 +38,21 @@ for retrieving all Records of the :ref:`Model `. .. code-block:: python >>> nautobot = api(url=url, token=token) - >>> device_roles = nautobot.dcim.device_roles - - >>> # Show retrieving all Device Role Records - >>> all_device_roles = device_roles.all() - >>> all_device_roles - ['Spine', 'Leaf', 'Access Switch'] - + >>> roles = nautobot.extras.roles + >>> + >>> # Show retrieving all Role Records + >>> all_roles = roles.all() + >>> first_3_roles = all_roles[:3] + >>> first_3_roles + [, , ] + >>> >>> # Show that the returned objects are record instances - >>> for role in all_device_roles: - ... print(f"Device Role {role.name} has an ID of: {role.id}") + >>> for role in first_3_roles: + ... print(f"Role {role.name} has an ID of: {role.id}") ... - Device Role Spine has an ID of: 6929b68d-8f87-4470-8377-e7fdc933a2bb - Device Role Leaf has an ID of: 749396ff-692b-448e-9c98-b24f4c7fcb3d - Device Role Access Switch has an ID of: 6928e7b4-f68e-4b69-bff5-9575c950f713 + Role loopback has an ID of: 866eaed3-2d12-49f8-9702-7dc1c2f3b053 + Role mgmt has an ID of: a1b9bb07-da6d-458a-8fd5-bf1f993da85a + Role point-to-point has an ID of: f3d0ac02-23d0-4b2d-9f2b-afd4875f5f0f .. warning:: diff --git a/docs/basic/crud/update.rst b/docs/basic/crud/update.rst index 2fa538f..82b069c 100644 --- a/docs/basic/crud/update.rst +++ b/docs/basic/crud/update.rst @@ -11,28 +11,28 @@ and then updating :ref:`fields ` in the returned :py:class:`Record .. code-block:: python >>> nautobot = api(url=url, token=token) - >>> device_roles = nautobot.dcim.device_roles - - >>> # Get the record object for the access-switch device role - >>> access_role = device_roles.get(slug="access-switch") - + >>> roles = nautobot.extras.roles + >>> + >>> # Get the record object for the access-switch role + >>> access_role = roles.get(name="Access Switch") + >>> >>> # Show existing values for name and description fields >>> access_role.name 'Access Switch' >>> access_role.description '' - - >>> # Create a dictionary to update the device role fields + >>> + >>> # Create a dictionary to update the role fields >>> access_switch_updates = { - "name": "access switch", - "description": "Provides access to end hosts", - } - - >>> # Show using the update method on the device role + ... "name": "access switch", + ... "description": "Provides access to end hosts", + ... } + >>> + >>> # Show using the update method on the role >>> access_role.update(access_switch_updates) True - - >>> # Show that the fields were updated on the existing device role + >>> + >>> # Show that the fields were updated on the existing role >>> access_role.name 'access switch' >>> access_role.description diff --git a/poetry.lock b/poetry.lock index 432fdc4..060143b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,22 +14,18 @@ files = [ [[package]] name = "astroid" -version = "2.11.7" +version = "3.0.0" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.8.0" files = [ - {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, - {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, + {file = "astroid-3.0.0-py3-none-any.whl", hash = "sha256:f2510e7fdcd6cfda4ec50014726d4857abf79acfc010084ce8c26091913f1b25"}, + {file = "astroid-3.0.0.tar.gz", hash = "sha256:1defdbca052635dd29657ea674edfc45e4b5be9cd53630c5b084fcfed94344a8"}, ] [package.dependencies] -lazy-object-proxy = ">=1.4.0" -setuptools = ">=20.0" -typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} -wrapt = ">=1.11,<2" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "attrs" @@ -43,9 +39,6 @@ files = [ {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, ] -[package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - [package.extras] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] dev = ["attrs[docs,tests]", "pre-commit"] @@ -94,37 +87,34 @@ yaml = ["PyYAML"] [[package]] name = "black" -version = "23.3.0" +version = "23.9.1" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.7" -files = [ - {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, - {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, - {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, - {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, - {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, - {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, - {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, - {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, - {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, - {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, - {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, - {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, - {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, - {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, +python-versions = ">=3.8" +files = [ + {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, + {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, + {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, + {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, + {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, + {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, + {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, + {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, + {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, + {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, + {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, ] [package.dependencies] @@ -134,8 +124,7 @@ packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -145,116 +134,130 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2023.5.7" +version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, - {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.3.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-win32.whl", hash = "sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c"}, + {file = "charset_normalizer-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"}, + {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, ] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "colorama" @@ -270,14 +273,14 @@ files = [ [[package]] name = "dill" -version = "0.3.6" -description = "serialize all of python" +version = "0.3.7" +description = "serialize all of Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, + {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, + {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, ] [package.extras] @@ -285,26 +288,26 @@ graph = ["objgraph (>=1.7.2)"] [[package]] name = "docutils" -version = "0.17.1" +version = "0.20.1" description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, - {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, ] [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, ] [package.extras] @@ -323,7 +326,6 @@ files = [ ] [package.dependencies] -importlib-metadata = {version = ">=1.1.0,<4.3", markers = "python_version < \"3.8\""} mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.9.0,<2.10.0" pyflakes = ">=2.5.0,<2.6.0" @@ -345,19 +347,21 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.31" +version = "3.1.37" description = "GitPython is a Python library used to interact with Git repositories" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.31-py3-none-any.whl", hash = "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d"}, - {file = "GitPython-3.1.31.tar.gz", hash = "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573"}, + {file = "GitPython-3.1.37-py3-none-any.whl", hash = "sha256:5f4c4187de49616d710a77e98ddf17b4782060a1788df441846bddefbb89ab33"}, + {file = "GitPython-3.1.37.tar.gz", hash = "sha256:f9b9ddc0761c125d5780eab2d64be4873fc6817c2899cbcb34b02344bdc7bc54"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" -typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} + +[package.extras] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar"] [[package]] name = "idna" @@ -385,23 +389,23 @@ files = [ [[package]] name = "importlib-metadata" -version = "4.2.0" +version = "6.8.0" description = "Read metadata from Python packages" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, - {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, ] [package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "iniconfig" @@ -417,30 +421,30 @@ files = [ [[package]] name = "invoke" -version = "2.1.1" +version = "2.2.0" description = "Pythonic task execution" category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "invoke-2.1.1-py3-none-any.whl", hash = "sha256:e86a53046eca453d3e609e7017f65db5f66b947d4d337b60658859eb8c8a80e3"}, - {file = "invoke-2.1.1.tar.gz", hash = "sha256:7dcf054c4626b89713da650635c29e9dfeb8a1dd0a14edc60bd3e16f751292ff"}, + {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, + {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, ] [[package]] name = "isort" -version = "5.11.5" +version = "5.12.0" description = "A Python utility / library to sort Python imports." category = "dev" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "isort-5.11.5-py3-none-any.whl", hash = "sha256:ba1d72fb2595a01c7895a5128f9585a5cc4b6d395f1c8d514989b9a7eb2a8746"}, - {file = "isort-5.11.5.tar.gz", hash = "sha256:6be1f76a507cb2ecf16c7cf14a37e41609ca082330be4e3436a18ef74add55db"}, + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, ] [package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] +colors = ["colorama (>=0.4.3)"] pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] requirements-deprecated-finder = ["pip-api", "pipreqs"] @@ -463,67 +467,20 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "lazy-object-proxy" -version = "1.9.0" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, -] - [[package]] name = "markdown-it-py" -version = "2.2.0" +version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, - {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, ] [package.dependencies] mdurl = ">=0.1,<1.0" -typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [package.extras] benchmarking = ["psutil", "pytest", "pytest-benchmark"] @@ -532,67 +489,77 @@ compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0 linkify = ["linkify-it-py (>=1,<3)"] plugins = ["mdit-py-plugins"] profiling = ["gprof2dot"] -rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.2" +version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"}, - {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] [[package]] @@ -633,26 +600,26 @@ files = [ [[package]] name = "packaging" -version = "23.1" +version = "23.2" description = "Core utilities for Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] [[package]] name = "pathspec" -version = "0.11.1" +version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] [[package]] @@ -669,38 +636,32 @@ files = [ [[package]] name = "platformdirs" -version = "3.5.0" +version = "3.11.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, - {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, + {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, + {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.5", markers = "python_version < \"3.8\""} - [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.3.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, ] -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] @@ -730,7 +691,6 @@ files = [ ] [package.dependencies] -importlib-metadata = {version = ">=2.0.0,<5.0.0", markers = "python_version < \"3.8\""} snowballstemmer = ">=2.2.0" [package.extras] @@ -750,14 +710,14 @@ files = [ [[package]] name = "pygments" -version = "2.15.1" +version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, - {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, ] [package.extras] @@ -765,125 +725,140 @@ plugins = ["importlib-metadata"] [[package]] name = "pylint" -version = "2.13.9" +version = "3.0.0" description = "python code static checker" category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.8.0" files = [ - {file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"}, - {file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"}, + {file = "pylint-3.0.0-py3-none-any.whl", hash = "sha256:21da8ed1294f88d66c82eb3e624a0993291613548bb17fbccaa220c31c41293b"}, + {file = "pylint-3.0.0.tar.gz", hash = "sha256:d22816c963816d7810b87afe0bdf5c80009e1078ecbb9c8f2e2a24d4430039b1"}, ] [package.dependencies] -astroid = ">=2.11.5,<=2.12.0-dev0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -dill = ">=0.2" +astroid = ">=3.0.0,<=3.1.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, +] isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -testutil = ["gitpython (>3)"] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] [[package]] name = "pytest" -version = "7.3.1" +version = "7.4.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, - {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, + {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, + {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, ] [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytz" -version = "2023.3" +version = "2023.3.post1" description = "World timezone definitions, modern and historical" category = "dev" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, ] [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.1" description = "YAML parser and emitter for Python" category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] [[package]] name = "requests" -version = "2.30.0" +version = "2.31.0" description = "Python HTTP for Humans." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "requests-2.30.0-py3-none-any.whl", hash = "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294"}, - {file = "requests-2.30.0.tar.gz", hash = "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"}, + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, ] [package.dependencies] @@ -898,14 +873,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requests-mock" -version = "1.10.0" +version = "1.11.0" description = "Mock out responses from the requests package" category = "dev" optional = false python-versions = "*" files = [ - {file = "requests-mock-1.10.0.tar.gz", hash = "sha256:59c9c32419a9fb1ae83ec242d98e889c45bd7d7a65d48375cc243ec08441658b"}, - {file = "requests_mock-1.10.0-py2.py3-none-any.whl", hash = "sha256:2fdbb637ad17ee15c06f33d31169e71bf9fe2bdb7bc9da26185be0dd8d842699"}, + {file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"}, + {file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"}, ] [package.dependencies] @@ -914,45 +889,28 @@ six = "*" [package.extras] fixture = ["fixtures"] -test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testrepository (>=0.0.18)", "testtools"] +test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] [[package]] name = "rich" -version = "13.3.5" +version = "13.6.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" category = "dev" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.3.5-py3-none-any.whl", hash = "sha256:69cdf53799e63f38b95b9bf9c875f8c90e78dd62b2f00c13a911c7a3b9fa4704"}, - {file = "rich-13.3.5.tar.gz", hash = "sha256:2d11b9b8dd03868f09b4fffadc84a6a8cda574e40dc90821bd845720ebb8e89c"}, + {file = "rich-13.6.0-py3-none-any.whl", hash = "sha256:2b38e2fe9ca72c9a00170a1a2d20c63c790d0e10ef1fe35eba76e1e7b1d7d245"}, + {file = "rich-13.6.0.tar.gz", hash = "sha256:5c14d22737e6d5084ef4771b62d5d4363165b403455a30a1c8ca39dc7b644bef"}, ] [package.dependencies] -markdown-it-py = ">=2.2.0,<3.0.0" +markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] -[[package]] -name = "setuptools" -version = "67.7.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"}, - {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "six" version = "1.16.0" @@ -967,14 +925,14 @@ files = [ [[package]] name = "smmap" -version = "5.0.0" +version = "5.0.1" description = "A pure Python implementation of a sliding window memory map manager" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, + {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, + {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, ] [[package]] @@ -991,28 +949,28 @@ files = [ [[package]] name = "sphinx" -version = "4.3.2" +version = "7.1.2" description = "Python documentation generator" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "Sphinx-4.3.2-py3-none-any.whl", hash = "sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851"}, - {file = "Sphinx-4.3.2.tar.gz", hash = "sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c"}, + {file = "sphinx-7.1.2-py3-none-any.whl", hash = "sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe"}, + {file = "sphinx-7.1.2.tar.gz", hash = "sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f"}, ] [package.dependencies] alabaster = ">=0.7,<0.8" -babel = ">=1.3" -colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.14,<0.18" -imagesize = "*" -Jinja2 = ">=2.3" -packaging = "*" -Pygments = ">=2.0" -requests = ">=2.5.0" -setuptools = "*" -snowballstemmer = ">=1.1" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.21" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.13" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = ">=2.0.0" @@ -1022,19 +980,19 @@ sphinxcontrib-serializinghtml = ">=1.1.5" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "isort", "mypy (>=0.920)", "types-pkg-resources", "types-requests", "types-typed-ast"] -test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.2" -description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +version = "1.0.4" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, - {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, ] [package.extras] @@ -1059,14 +1017,14 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.0" +version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, - {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, ] [package.extras] @@ -1122,18 +1080,17 @@ test = ["pytest"] [[package]] name = "stevedore" -version = "3.5.2" +version = "5.1.0" description = "Manage dynamic plugins for Python applications" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "stevedore-3.5.2-py3-none-any.whl", hash = "sha256:fa2630e3d0ad3e22d4914aff2501445815b9a4467a6edc49387c667a38faf5bf"}, - {file = "stevedore-3.5.2.tar.gz", hash = "sha256:cf99f41fc0d5a4f185ca4d3d42b03be9011b0a1ec1a4ea1a282be1b4b306dcc2"}, + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, ] [package.dependencies] -importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} pbr = ">=2.0.0,<2.1.0 || >2.1.0" [[package]] @@ -1161,163 +1118,56 @@ files = [ ] [[package]] -name = "typed-ast" -version = "1.5.4" -description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "tomlkit" +version = "0.12.1" +description = "Style preserving TOML library" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, - {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, - {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, - {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, - {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, - {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, - {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, - {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, - {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, - {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, + {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, + {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, ] [[package]] name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, ] [[package]] name = "urllib3" -version = "1.26.15" +version = "1.26.17" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, - {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, + {file = "urllib3-1.26.17-py2.py3-none-any.whl", hash = "sha256:94a757d178c9be92ef5539b8840d48dc9cf1b2709c9d6b588232a055c524458b"}, + {file = "urllib3-1.26.17.tar.gz", hash = "sha256:24d6a242c28d29af46c3fae832c36db3bbebcc533dd1bb549172cd739c82df21"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] -[[package]] -name = "wrapt" -version = "1.15.0" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, -] - [[package]] name = "yamllint" -version = "1.31.0" +version = "1.32.0" description = "A linter for YAML files." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "yamllint-1.31.0-py3-none-any.whl", hash = "sha256:15f4bdb645e6a4a0a22fe5415bc38b4a934c51419b30104896d2f3f95e329185"}, - {file = "yamllint-1.31.0.tar.gz", hash = "sha256:2d83f1d12f733e162a87e06b176149d7bb9c5bae4a9e5fce1c771d7f703f7a65"}, + {file = "yamllint-1.32.0-py3-none-any.whl", hash = "sha256:d97a66e48da820829d96077d76b8dfbe6c6140f106e558dae87e81ac4e6b30b7"}, + {file = "yamllint-1.32.0.tar.gz", hash = "sha256:d01dde008c65de5b235188ab3110bebc59d18e5c65fc8a58267cd211cd9df34a"}, ] [package.dependencies] @@ -1329,24 +1179,24 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [[package]] name = "zipp" -version = "3.15.0" +version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [extras] docs = [] [metadata] lock-version = "2.0" -python-versions = "^3.7" -content-hash = "460b35f20a8ba488a0007cdb63aab8c91f0027abe1e0e8c2483df1461b2a87e0" +python-versions = "^3.8" +content-hash = "bb8f9375e090e9d1d90de967059f5fce0f53f0231a2dbde83b1fce84ad5ffb58" diff --git a/pynautobot/core/api.py b/pynautobot/core/api.py index 2294743..646b1dc 100644 --- a/pynautobot/core/api.py +++ b/pynautobot/core/api.py @@ -115,8 +115,8 @@ def __init__( def _validate_version(self): """Validate API version if eq or ge than 2.0 raise an error.""" api_version = self.version - if api_version.replace(".", "").isnumeric() and version.parse(api_version) >= version.parse("2.0"): - raise ValueError("Nautobot version 2 detected, please upgrade pynautobot to version 2.x") + if api_version.replace(".", "").isnumeric() and version.parse(api_version) < version.parse("2.0"): + raise ValueError("Nautobot version 1 detected, please downgrade pynautobot to version 1.x") @property def version(self): diff --git a/pynautobot/core/endpoint.py b/pynautobot/core/endpoint.py index c2dc4f6..d3d3229 100644 --- a/pynautobot/core/endpoint.py +++ b/pynautobot/core/endpoint.py @@ -390,14 +390,14 @@ def choices(self, api_version=None): api_version=api_version, ).options() try: - post_data = req["actions"]["POST"] - except KeyError: - raise ValueError("Unexpected format in the OPTIONS response at {}".format(self.url)) - self._choices = {} - for prop in post_data: - if "choices" in post_data[prop]: - self._choices[prop] = post_data[prop]["choices"] - + post_data = req["schema"]["properties"] + except (KeyError, TypeError): + raise ValueError(f"Unexpected format in the OPTIONS response at {self.url}") + self._choices = { + prop: [{"value": x, "display": y} for x, y in zip(post_data[prop]["enum"], post_data[prop]["enumNames"])] + for prop in post_data + if "enum" in post_data[prop] + } return self._choices def count(self, *args, api_version=None, **kwargs): diff --git a/pynautobot/models/dcim.py b/pynautobot/models/dcim.py index 89af558..efc3f64 100644 --- a/pynautobot/models/dcim.py +++ b/pynautobot/models/dcim.py @@ -24,6 +24,12 @@ class TraceableRecord(Record): + def _get_app_endpoint(self, hop_item_data): + if "url" not in hop_item_data: + return "" + path_elements = urlparse(hop_item_data["url"][len(self.api.base_url) :]).path.split("/")[1:3] + return "/".join(path_elements) + def trace(self): req = Request( key=str(self.id) + "/trace", @@ -46,8 +52,7 @@ def trace(self): this_hop_ret.append(hop_item_data) continue - # TODO: Move this to a more general function. - app_endpoint = "/".join(urlparse(hop_item_data["url"][len(self.api.base_url) :]).path.split("/")[1:3]) + app_endpoint = self._get_app_endpoint(hop_item_data) return_obj_class = uri_to_obj_class_map.get( app_endpoint, diff --git a/pyproject.toml b/pyproject.toml index 4ec34e2..9640d41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "pynautobot" -version = "1.5.0" +version = "2.0.0" description = "Nautobot API client library" authors = ["Network to Code, LLC "] readme = "README.md" @@ -12,14 +12,14 @@ classifiers = [ "Intended Audience :: Developers", "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.8", ] repository = "https://github.com/nautobot/pynautobot" homepage = "https://nautobot.com" documentation = "https://pynautobot.readthedocs.io" [tool.poetry.dependencies] -python = "^3.7" +python = "^3.8" requests = "^2.30.0" # requests doesn't support `urllib3` 2.0 yet see: https://github.com/psf/requests/issues/6432 urllib3 = ">=1.21.1 <1.27" diff --git a/tasks.py b/tasks.py index 866792e..0aac57f 100644 --- a/tasks.py +++ b/tasks.py @@ -100,9 +100,9 @@ def logs(context, service="", follow=False, tail=None): @task -def debug(context): +def debug(context, service=_DEFAULT_SERVICE): print("Starting Nautobot in debug mode...") - return context.run("docker-compose up", env=_DOCKER_COMPOSE_ENV, pty=True) + return context.run(f"docker-compose up -- {service}", env=_DOCKER_COMPOSE_ENV, pty=True) def run_cmd(context, exec_cmd, local=INVOKE_LOCAL, service=_DEFAULT_SERVICE): diff --git a/tests/__init__.py b/tests/__init__.py index 034e971..168ce15 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -5,7 +5,7 @@ from .util import Response -with patch("pynautobot.api.version", "1.999"): +with patch("pynautobot.api.version", "2.0"): api = pynautobot.api( "http://localhost:8000", token="abc123", diff --git a/tests/conftest.py b/tests/conftest.py index fb7d490..d49c6f2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -48,7 +48,7 @@ def pytest_configure(config): @pytest.fixture def pynautobot_api(monkeypatch): """Factory to create pynautobot api instance.""" - monkeypatch.setattr("pynautobot.api.version", "1.999") + monkeypatch.setattr("pynautobot.api.version", "2.0") return Api(url="https://mocknautobot.example.com", token="1234567890abcdefg") diff --git a/tests/fixtures/ipam/namespace.json b/tests/fixtures/ipam/namespace.json new file mode 100644 index 0000000..79e95c9 --- /dev/null +++ b/tests/fixtures/ipam/namespace.json @@ -0,0 +1,13 @@ +{ + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "internal", + "url": "http://localhost:8080/api/ipam/namespaces/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "name": "internal", + "description": "", + "location": null, + "created": "2023-04-24T12:36:38.598529Z", + "last_updated": "2023-04-24T12:36:38.598564Z", + "tags": [], + "notes_url": "http://localhost:8080/api/ipam/namespaces/5b39ba88-e5ab-4be2-89f5-5a016473b53c/notes/", + "custom_fields": {} +} diff --git a/tests/fixtures/ipam/namespaces.json b/tests/fixtures/ipam/namespaces.json new file mode 100644 index 0000000..d9c04d8 --- /dev/null +++ b/tests/fixtures/ipam/namespaces.json @@ -0,0 +1,33 @@ +{ + "count": 2, + "next": null, + "previous": null, + "results": [ + { + "id": "c7671ec3-3900-4650-9dd7-ac538f2bee67", + "display": "Global", + "url": "http://localhost:8080/api/ipam/namespaces/c7671ec3-3900-4650-9dd7-ac538f2bee67/", + "name": "Global", + "description": "Default Global namespace. Created by Nautobot.", + "location": null, + "created": "2023-04-24T12:25:55.901435Z", + "last_updated": "2023-04-24T12:25:55.901447Z", + "tags": [], + "notes_url": "http://localhost:8080/api/ipam/namespaces/c7671ec3-3900-4650-9dd7-ac538f2bee67/notes/", + "custom_fields": {} + }, + { + "id": "b0b85da2-4e5f-4b0f-a960-4f7bc5f225db", + "display": "internal", + "url": "http://localhost:8080/api/ipam/namespaces/b0b85da2-4e5f-4b0f-a960-4f7bc5f225db/", + "name": "internal", + "description": "", + "location": null, + "created": "2023-04-24T12:36:38.598529Z", + "last_updated": "2023-04-24T12:36:38.598564Z", + "tags": [], + "notes_url": "http://localhost:8080/api/ipam/namespaces/b0b85da2-4e5f-4b0f-a960-4f7bc5f225db/notes/", + "custom_fields": {} + } + ] +} diff --git a/tests/fixtures/ipam/prefix.json b/tests/fixtures/ipam/prefix.json index 6ea86fd..4e33c2a 100644 --- a/tests/fixtures/ipam/prefix.json +++ b/tests/fixtures/ipam/prefix.json @@ -9,6 +9,14 @@ "slug": "test1" }, "vrf": null, + "namespace": { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "internal", + "url": "http://localhost:8080/api/ipam/namespaces/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "name": "internal", + "description": "", + "location": null + }, "tenant": null, "vlan": null, "status": { diff --git a/tests/fixtures/ipam/vrf.json b/tests/fixtures/ipam/vrf.json index 1f45244..2e9b848 100644 --- a/tests/fixtures/ipam/vrf.json +++ b/tests/fixtures/ipam/vrf.json @@ -1,6 +1,14 @@ { "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", "name": "TEST", + "namespace": { + "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", + "display": "internal", + "url": "http://localhost:8080/api/ipam/namespaces/5b39ba88-e5ab-4be2-89f5-5a016473b53c/", + "name": "internal", + "description": "", + "location": null + }, "rd": "65535:1", "tenant": null, "enforce_unique": true, diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 18c30c7..6be5b97 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -31,6 +31,9 @@ "Server", "Spine Switch", ] +PARENT_PREFIXES = [ + "192.0.0.0/8", +] # When running tests locally `export NAUTOBOT_URL="http://localhost:8000"` (or wherever Nautobot runs) to override the default _NAUTOBOT_URL = os.getenv("NAUTOBOT_URL", "http://nautobot:8000") @@ -110,7 +113,7 @@ def populate_nautobot_object_types(nb_api, devicetype_library_repo_dirpath): # create the manufacturers manufacturer_names = {model["manufacturer"] for model in device_type_models} for manufacturer_name in manufacturer_names: - nb_api.dcim.manufacturers.create(name=manufacturer_name, slug=manufacturer_name.lower().replace(" ", "-")) + nb_api.dcim.manufacturers.create(name=manufacturer_name) # create the device types and their components for device_type_model in device_type_models: @@ -145,7 +148,11 @@ def populate_nautobot_object_types(nb_api, devicetype_library_repo_dirpath): # add device roles for device_role_name in DEVICE_ROLE_NAMES: - nb_api.dcim.device_roles.create(name=device_role_name, slug=device_role_name.lower().replace(" ", "-")) + nb_api.extras.roles.create(name=device_role_name, content_types=["dcim.device"]) + + # add parent prefix + for parent_prefix in PARENT_PREFIXES: + nb_api.ipam.prefixes.create(prefix=parent_prefix, namespace={"name": "Global"}, status={"name": "Active"}) @pytest.fixture(scope="session") diff --git a/tests/integration/test_api_version.py b/tests/integration/test_api_version.py index aaa2fe3..29edcde 100644 --- a/tests/integration/test_api_version.py +++ b/tests/integration/test_api_version.py @@ -31,7 +31,7 @@ def skipif_version(self, nb_client): def tag(self, nb_client): """Create a tag.""" tag_name = "Test Tag" - tag = nb_client.extras.tags.create(name=tag_name, slug=tag_name.lower().replace(" ", "_")) + tag = nb_client.extras.tags.create(name=tag_name, content_types=["dcim.location"]) assert tag return tag @@ -41,14 +41,14 @@ def test_invalid_api_version(self, nb_client): with pytest.raises(pynautobot.core.query.RequestError) as _: nb_client.extras.tags.all(api_version="0.0") - def test_tag_content_types(self, skipif_version, nb_client_1_3, tag): + def test_tag_content_types(self, skipif_version, nb_client, tag): """Verify we can retrieve and update a tag's content types when using API v1.3.""" assert skipif_version - tag_1_3 = nb_client_1_3.extras.tags.get(id=tag.id) - assert tag_1_3 - assert tag_1_3.content_types + tag = nb_client.extras.tags.get(id=tag.id) + assert tag + assert tag.content_types new_content_types = {"content_types": ["dcim.device"]} - tag_1_3.update(new_content_types) - tag_1_3 = nb_client_1_3.extras.tags.get(id=tag.id) - assert tag_1_3.content_types == new_content_types["content_types"] + tag.update(new_content_types) + tag = nb_client.extras.tags.get(id=tag.id) + assert tag.content_types == new_content_types["content_types"] diff --git a/tests/integration/test_dcim.py b/tests/integration/test_dcim.py index bd5d75a..763fe4e 100644 --- a/tests/integration/test_dcim.py +++ b/tests/integration/test_dcim.py @@ -17,36 +17,52 @@ class TestSimpleServerRackingAndConnecting: """Verify we can create, rack, and connect a server.""" @pytest.fixture - def site(self, nb_client): - """Verify we can create a site.""" - site_name = "MSP" - site = nb_client.dcim.sites.create(name=site_name, slug=site_name.lower().replace(" ", "_"), status="active") - assert site + def location(self, nb_client): + """Verify we can create a location.""" + location_types = ["dcim.device", "dcim.rack", "dcim.rackgroup"] + site_type = nb_client.dcim.location_types.create(name="Site", content_types=location_types, nestable=True) + location_name = "MSP" + location = nb_client.dcim.locations.create( + name=location_name, + status={"name": "Active"}, + location_type=site_type.id, + ) + assert location + + return location + + @pytest.fixture + def rack_group(self, location): + """Verify we can create a rack device.""" + rack_group = location.api.dcim.rack_groups.create(name="rack_group_1", location=location.id) + assert rack_group - return site + return rack_group @pytest.fixture - def rack(self, site): + def rack(self, location, rack_group): """Verify we can create a rack device.""" - rack = site.api.dcim.racks.create(name="rack1", site=site.id, status="active") + rack = location.api.dcim.racks.create( + name="rack1", location=location.id, rack_group=rack_group.id, status={"name": "Active"} + ) assert rack return rack @pytest.fixture - def data_leafs(self, rack): + def data_leafs(self, rack, location): """Verify we can create data leaf switch devices.""" devices = [] for i in [1, 2]: device = rack.api.dcim.devices.create( name=f"access_switch{i}.networktocode.com", - device_type={"slug": "dcs-7050tx3-48c8"}, - device_role={"name": "Leaf Switch"}, - site=rack.site.id, + device_type={"model": "DCS-7050TX3-48C8"}, + role={"name": "Leaf Switch"}, + location=location.id, rack=rack.id, face="rear", position=rack.u_height - i, - status="active", + status={"name": "Active"}, ) assert device devices.append(device) @@ -54,78 +70,82 @@ def data_leafs(self, rack): return devices @pytest.fixture - def mgmt_leaf(self, rack): + def mgmt_leaf(self, rack, location): """Verify we can create data leaf switch devices.""" device = rack.api.dcim.devices.create( name="mgmt_switch1.networktocode.com", - device_type={"slug": "dcs-7010t-48"}, - device_role={"name": "Leaf Switch"}, - site=rack.site.id, + device_type={"model": "DCS-7010T-48"}, + role={"name": "Leaf Switch"}, + location=location.id, rack=rack.id, face="rear", position=rack.u_height - 3, - status="active", + status={"name": "Active"}, ) assert device return device @pytest.fixture - def server(self, site): + def server(self, location): """Verify we can create a server device.""" - device = site.api.dcim.devices.create( + device = location.api.dcim.devices.create( name="server.networktocode.com", - device_type={"slug": "dell_poweredge_r640"}, - device_role={"name": "Server"}, - site=site.id, - status="active", + device_type={"model": "PowerEdge R640"}, + role={"name": "Server"}, + location=location.id, + status={"name": "Active"}, ) assert device return device - def test_racking_server(self, server, data_leafs, mgmt_leaf, rack): + def test_racking_server(self, nb_client, server, data_leafs, mgmt_leaf, rack): """Verify we can rack the server.""" assert server.update({"rack": rack.id, "face": "front", "position": rack.u_height - 4}) # connect the mgmt iface - server_mgmt_iface = server.api.dcim.interfaces.get(device_id=server.id, mgmt_only=True, cabled=False) + server_mgmt_iface = server.api.dcim.interfaces.get(device_id=server.id, mgmt_only=True, has_cable=False) assert server_mgmt_iface - mleaf_iface = mgmt_leaf.api.dcim.interfaces.filter(mgmt_only=False, cabled=False)[0] + mleaf_iface = mgmt_leaf.api.dcim.interfaces.filter(mgmt_only=False, has_cable=False)[0] cable = server.api.dcim.cables.create( termination_a_type="dcim.interface", termination_a_id=server_mgmt_iface.id, termination_b_type="dcim.interface", termination_b_id=mleaf_iface.id, - status="connected", + status={"name": "Connected"}, ) # connect the data ifaces in a bond server_data_ifaces = server.api.dcim.interfaces.filter(device_id=server.id, mgmt_only=False)[:2] assert len(server_data_ifaces) == 2 - bond_iface = server.api.dcim.interfaces.create(device=server.id, name="bond0", type="lag") + bond_iface = server.api.dcim.interfaces.create( + device=server.id, name="bond0", type="lag", status={"name": "Active"} + ) assert bond_iface for server_data_iface, data_leaf in zip(server_data_ifaces, data_leafs): - dleaf_iface = data_leaf.api.dcim.interfaces.filter(device_id=data_leaf.id, mgmt_only=False, cabled=False)[0] + dleaf_iface = data_leaf.api.dcim.interfaces.filter( + device_id=data_leaf.id, mgmt_only=False, has_cable=False + )[0] cable = server.api.dcim.cables.create( termination_a_type="dcim.interface", termination_a_id=server_data_iface.id, termination_b_type="dcim.interface", termination_b_id=dleaf_iface.id, - status="connected", + status={"name": "Connected"}, ) assert cable assert server_data_iface.update({"lag": bond_iface.id}) # now reload the server and verify it's set correctly - server = server.api.dcim.devices.get(server.id) + server = nb_client.dcim.devices.get(name="server.networktocode.com") # check the cable traces - for iface in server.api.dcim.interfaces.filter(device_id=server.id, cabled=True): + for iface in server.api.dcim.interfaces.filter(device_id=server.id, has_cable=True): trace = iface.trace() assert len(trace) == 1 local_iface, cable, remote_iface = trace[0] @@ -138,46 +158,47 @@ def test_racking_server(self, server, data_leafs, mgmt_leaf, rack): def test_string_represention(self, nb_client): """Validate two device objects return the proper string when casting to string.""" - site = nb_client.dcim.sites.get(slug="msp") + location = nb_client.dcim.locations.get(name="MSP") device_no_name = nb_client.dcim.devices.create( - device_type={"slug": "dcs-7050tx3-48c8"}, - device_role={"name": "Leaf Switch"}, - site=site.id, - status="active", + device_type={"model": "DCS-7050TX3-48C8"}, + role={"name": "Leaf Switch"}, + location=location.id, + status={"name": "Active"}, ) device_w_name = nb_client.dcim.devices.create( name="im a real boy", - device_type={"slug": "dcs-7050tx3-48c8"}, - device_role={"name": "Leaf Switch"}, - site=site.id, - status="active", + device_type={"model": "DCS-7050TX3-48C8"}, + role={"name": "Leaf Switch"}, + location=location.id, + status={"name": "Active"}, ) assert str(device_no_name) == f"Arista DCS-7050TX3-48C8 ({device_no_name['id']})" assert str(device_w_name) == "im a real boy" def test_fetching_vc_success(self, nb_client): """Validate nb_client.dcim.virtual_chassis.all() fetches successfully and has the correct data.""" - site = nb_client.dcim.sites.get(slug="msp") + location = nb_client.dcim.locations.get(name="MSP") dev1 = nb_client.dcim.devices.create( name="dev-1", - device_type={"slug": "dcs-7050tx3-48c8"}, - device_role={"name": "Leaf Switch"}, - site=site.id, - status="active", + device_type={"model": "DCS-7050TX3-48C8"}, + role={"name": "Leaf Switch"}, + location=location.id, + status={"name": "Active"}, ) vc = nb_client.dcim.virtual_chassis.create(name="VC1", master=dev1.id) nb_client.dcim.devices.create( name="dev-2", - device_type={"slug": "dcs-7050tx3-48c8"}, - device_role={"name": "Leaf Switch"}, - site=site.id, - status="active", + device_type={"model": "DCS-7050TX3-48C8"}, + role={"name": "Leaf Switch"}, + location=location.id, + status={"name": "Active"}, virtual_chassis=vc.id, vc_position=2, ) all_vcs = nb_client.dcim.virtual_chassis.all() - vc1 = all_vcs[0] assert len(all_vcs) == 1 + + vc1 = nb_client.dcim.virtual_chassis.get(name="VC1") assert vc1.member_count == 2 assert vc1.master.name == dev1.name assert vc1.master.id == dev1.id diff --git a/tests/integration/test_ipam.py b/tests/integration/test_ipam.py index 19ad552..d553849 100644 --- a/tests/integration/test_ipam.py +++ b/tests/integration/test_ipam.py @@ -3,20 +3,26 @@ def test_ip_address_nat_inside_outside_correct_objects(nb_client): """Validate nat_inside and nat_outside both return IpAddress Record objects.""" - ip_inside = nb_client.ipam.ip_addresses.create(address="192.0.2.1/32", status="active") - ip_outside = nb_client.ipam.ip_addresses.create(address="192.0.2.2/32", status="active", nat_inside=ip_inside.id) + parent = nb_client.ipam.prefixes.get(prefix="192.0.0.0/8") + ip_inside = nb_client.ipam.ip_addresses.create(address="192.0.2.1/32", status={"name": "Active"}, parent=parent.id) + nb_client.ipam.ip_addresses.create( + address="192.0.2.2/32", status={"name": "Active"}, parent=parent.id, nat_inside=ip_inside.id + ) ip_inside_refresh = nb_client.ipam.ip_addresses.get(address="192.0.2.1/32") + ip_outside_refresh = nb_client.ipam.ip_addresses.get(address="192.0.2.2/32") - assert str(ip_outside.nat_inside) == "192.0.2.1/32" - assert str(ip_inside_refresh.nat_outside) == "192.0.2.2/32" + assert str(ip_outside_refresh.nat_inside.address) == "192.0.2.1/32" + assert str(ip_inside_refresh.nat_outside_list[0].address) == "192.0.2.2/32" def test_prefixes_successfully_stringify_tags(nb_client): """Validate prefix will properly stringify the tags attribute and they are Record objects.""" - tag = nb_client.extras.tags.create(name="production", slug="production") - prefix = nb_client.ipam.prefixes.create(prefix="192.0.2.0/24", status="active", tags=[tag.id]) - + tag = nb_client.extras.tags.create(name="production", content_types=["ipam.prefix"]) + nb_client.ipam.prefixes.create( + prefix="192.0.2.0/24", namespace={"name": "Global"}, status={"name": "Active"}, tags=[tag.id] + ) + prefix = nb_client.ipam.prefixes.get(prefix="192.0.2.0/24", namespace="Global") assert str(prefix) == "192.0.2.0/24" assert prefix.tags assert isinstance(prefix.tags[0], Record) diff --git a/tests/test_api.py b/tests/test_api.py index 55481ff..62be338 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -26,7 +26,7 @@ class ApiTestCase(unittest.TestCase): @patch( "requests.sessions.Session.post", ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_get(self, *_): api = pynautobot.api(host, **def_kwargs) self.assertTrue(api) @@ -34,7 +34,7 @@ def test_get(self, *_): @patch( "requests.sessions.Session.post", ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_sanitize_url(self, *_): api = pynautobot.api("http://localhost:8000/", **def_kwargs) self.assertTrue(api) @@ -51,10 +51,11 @@ class ResponseHeadersWithVersion: return_value=ResponseHeadersWithVersion(), ) def test_api_version(self, *_): - api = pynautobot.api( - host, + with self.assertRaises(ValueError) as error: + pynautobot.api(host) + self.assertEqual( + str(error.exception), "Nautobot version 1 detected, please downgrade pynautobot to version 1.x" ) - self.assertEqual(api.version, "1.999") class ResponseHeadersWithoutVersion: headers = {} @@ -79,9 +80,10 @@ class ResponseHeadersWithVersion2: return_value=ResponseHeadersWithVersion2(), ) def test_api_version_2(self, *_): - with self.assertRaises(ValueError) as error: - pynautobot.api(host) - self.assertEqual(str(error.exception), "Nautobot version 2 detected, please upgrade pynautobot to version 2.x") + api = pynautobot.api( + host, + ) + self.assertEqual(api.version, "2.0") class ApiStatusTestCase(unittest.TestCase): @@ -97,7 +99,7 @@ def json(self): "requests.sessions.Session.get", return_value=ResponseWithStatus(), ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_api_status(self, *_): api = pynautobot.api( host, @@ -122,7 +124,7 @@ def test_api_retry(self, getconn_mock): "http://any.url/", retries=2, ) - with patch("pynautobot.api.version", "1.999"): + with patch("pynautobot.api.version", "2.0"): api.version assert getconn_mock.return_value.request.mock_calls == [ @@ -139,7 +141,7 @@ def test_api_retry_fails(self, getconn_mock): Mock(status=200, msg=HTTPMessage()), ] - with patch("pynautobot.api.version", "1.999"): + with patch("pynautobot.api.version", "2.0"): api = pynautobot.api( "http://any.url/", retries=1, diff --git a/tests/test_app.py b/tests/test_app.py index acbc648..07c6479 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -17,7 +17,7 @@ class AppCustomFieldsTestCase(unittest.TestCase): "requests.sessions.Session.get", return_value=Response(fixture="extras/custom_fields.json"), ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_custom_fields(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) cfs = api.extras.custom_fields() @@ -43,7 +43,7 @@ class AppCustomFieldChoicesTestCase(unittest.TestCase): "requests.sessions.Session.get", return_value=Response(fixture="extras/custom_field_choices.json"), ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_custom_field_choices(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) choices = api.extras.custom_field_choices() @@ -68,7 +68,7 @@ class AppConfigTestCase(unittest.TestCase): "pynautobot.core.query.Request.get", return_value={"tables": {"DeviceTable": {"columns": ["name", "status", "tenant", "tags"]}}}, ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_config(self, *_): api = pynautobot.api(host, **def_kwargs) config = api.users.config() @@ -84,7 +84,7 @@ class PluginAppCustomChoicesTestCase(unittest.TestCase): "pynautobot.core.query.Request.get", return_value={"Testfield1": {"TF1_1": 1, "TF1_2": 2}, "Testfield2": {"TF2_1": 3, "TF2_2": 4}}, ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_custom_choices(self, *_): api = pynautobot.api(host, **def_kwargs) choices = api.plugins.test_plugin.custom_fields() @@ -95,7 +95,7 @@ def test_custom_choices(self, *_): "pynautobot.core.query.Request.get", return_value=[{"name": "test_plugin", "package": "netbox_test_plugin"}], ) - @patch("pynautobot.api.version", "1.999") + @patch("pynautobot.api.version", "2.0") def test_installed_plugins(self, *_): api = pynautobot.api(host, **def_kwargs) plugins = api.plugins.installed_plugins() diff --git a/tests/test_ipam.py b/tests/test_ipam.py index 01595f2..39670e5 100644 --- a/tests/test_ipam.py +++ b/tests/test_ipam.py @@ -11,6 +11,22 @@ class PrefixTestCase(Generic.Tests): name = "prefixes" name_singular = "prefix" + @patch( + "requests.sessions.Session.get", + side_effect=[Response(fixture="ipam/namespace.json"), Response(fixture="ipam/prefix.json")], + ) + def test_namespace_in_prefix(self, mock): + namespace = self.endpoint.get(self.uuid) + prefix = api.ipam.prefixes.get(self.uuid) + mock.assert_called_with( + f"http://localhost:8000/api/ipam/prefixes/{self.uuid}/", + params={}, + json=None, + headers=HEADERS, + ) + self.assertEqual(namespace.id, prefix.namespace.id) + self.assertEqual(namespace.name, prefix.namespace.name) + @patch("requests.sessions.Session.get", return_value=Response(fixture="ipam/prefix.json")) def test_modify(self, *_): ret = self.endpoint.get(self.uuid) @@ -154,6 +170,28 @@ class VRFTestCase(Generic.Tests): app = "ipam" name = "vrfs" + @patch( + "requests.sessions.Session.get", + side_effect=[Response(fixture="ipam/namespace.json"), Response(fixture="ipam/vrf.json")], + ) + def test_namespace_in_vrf(self, mock): + namespace = self.endpoint.get(self.uuid) + vrf = api.ipam.vrfs.get(self.uuid) + mock.assert_called_with( + f"http://localhost:8000/api/ipam/vrfs/{self.uuid}/", + params={}, + json=None, + headers=HEADERS, + ) + self.assertEqual(namespace.id, vrf.namespace.id) + self.assertEqual(namespace.name, vrf.namespace.name) + + +class NameSpaceTestCase(Generic.Tests): + app = "ipam" + name = "namespaces" + name_singular = "namespace" + # class ServicesTestCase(Generic.Tests): # app = "ipam" diff --git a/tests/unit/test_api_version.py b/tests/unit/test_api_version.py index ac3433f..20f08eb 100644 --- a/tests/unit/test_api_version.py +++ b/tests/unit/test_api_version.py @@ -42,7 +42,7 @@ def test_api_versioning_at_api_level(self, ResponseLoader): ) # Test choices request includes version=1.3 in its headers - self.api.http_session.options.return_value.json.return_value = {"actions": {"POST": []}} + self.api.http_session.options.return_value.json.return_value = {"schema": {"properties": {}}} self.test_obj.choices() self.api.http_session.options.assert_called_with( "http://localhost:8000/api/test/test/", @@ -80,7 +80,7 @@ def test_api_versioning_at_per_request_level(self, ResponseLoader): ) # Test choices request overrides Api level versioning - self.api.http_session.options.return_value.json.return_value = {"actions": {"POST": []}} + self.api.http_session.options.return_value.json.return_value = {"schema": {"properties": {}}} self.test_obj.choices(api_version=1.2) self.api.http_session.options.assert_called_with( "http://localhost:8000/api/test/test/", diff --git a/tests/unit/test_endpoint.py b/tests/unit/test_endpoint.py index e43997d..4a0c631 100644 --- a/tests/unit/test_endpoint.py +++ b/tests/unit/test_endpoint.py @@ -37,21 +37,18 @@ def test_choices(self): api = Mock(base_url="http://localhost:8000/api") app = Mock(name="test") mock.return_value = { - "actions": { - "POST": { + "schema": { + "properties": { "letter": { - "choices": [ - {"display_name": "A", "value": 1}, - {"display_name": "B", "value": 2}, - {"display_name": "C", "value": 3}, - ] + "enum": [1, 2, 3], + "enumNames": ["A", "B", "C"], } } } } test_obj = Endpoint(api, app, "test") choices = test_obj.choices() - self.assertEqual(choices["letter"][1]["display_name"], "B") + self.assertEqual(choices["letter"][1]["display"], "B") self.assertEqual(choices["letter"][1]["value"], 2) From fbd94fd1e88a16a883a2ee7542903f75e5f878a2 Mon Sep 17 00:00:00 2001 From: Patryk Szulczewski Date: Wed, 18 Oct 2023 10:35:00 +0200 Subject: [PATCH 19/21] Fix SSL verify (#140) (#142) --- docs/advanced/session.rst | 5 ++--- pynautobot/core/api.py | 3 +++ tests/test_api.py | 12 ++++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/advanced/session.rst b/docs/advanced/session.rst index 313acf6..62a748e 100644 --- a/docs/advanced/session.rst +++ b/docs/advanced/session.rst @@ -33,7 +33,6 @@ The example below shows how to update a Token if it has been cycled. SSL Verification ---------------- -Handling SSL verification is documented `here `_. The below example shows how to disable SSL verification. .. code-block:: python @@ -42,9 +41,9 @@ The below example shows how to disable SSL verification. from pynautobot import api nautobot = api( url='https://localhost:8000', - token=os.environ["NAUTOBOT_TOKEN"] + token=os.environ["NAUTOBOT_TOKEN"], + verify=False ) - nautobot.http_session.verify = False Timeouts -------- diff --git a/pynautobot/core/api.py b/pynautobot/core/api.py index 646b1dc..6d2bfce 100644 --- a/pynautobot/core/api.py +++ b/pynautobot/core/api.py @@ -61,6 +61,7 @@ class Api(object): for all requests. :param int,optional retries: Number of retries, for HTTP codes 429, 500, 502, 503, 504, this client will try before dropping. + :param bool,optional verify: SSL cert verification. :raises AttributeError: If app doesn't exist. :Examples: @@ -80,12 +81,14 @@ def __init__( max_workers=4, api_version=None, retries=0, + verify=True, ): base_url = "{}/api".format(url if url[-1] != "/" else url[:-1]) self.token = token self.headers = {"Authorization": f"Token {self.token}"} self.base_url = base_url self.http_session = requests.Session() + self.http_session.verify = verify if retries: _adapter = HTTPAdapter( max_retries=Retry( diff --git a/tests/test_api.py b/tests/test_api.py index 62be338..3261689 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -40,6 +40,18 @@ def test_sanitize_url(self, *_): self.assertTrue(api) self.assertEqual(api.base_url, "http://localhost:8000/api") + @patch("pynautobot.api.version", "2.0") + def test_verify_true(self, *_): + api = pynautobot.api("http://localhost:8000/", **def_kwargs) + self.assertTrue(api) + self.assertTrue(api.http_session.verify) + + @patch("pynautobot.api.version", "2.0") + def test_verify_false(self, *_): + api = pynautobot.api("http://localhost:8000/", verify=False, **def_kwargs) + self.assertTrue(api) + self.assertFalse(api.http_session.verify) + class ApiVersionTestCase(unittest.TestCase): class ResponseHeadersWithVersion: From 5987da4c23617d3a297d0775410f31e8c1a0008e Mon Sep 17 00:00:00 2001 From: Patryk Szulczewski Date: Tue, 24 Oct 2023 15:25:08 +0200 Subject: [PATCH 20/21] Fix custom_fields and custom_field_choices method overlap with endpoints (#141) (#144) --- pynautobot/core/app.py | 38 +++++--------------------------- tests/integration/test_extras.py | 36 ++++++++++++++++++++++++++++++ tests/test_app.py | 12 +++++----- 3 files changed, 48 insertions(+), 38 deletions(-) create mode 100644 tests/integration/test_extras.py diff --git a/pynautobot/core/app.py b/pynautobot/core/app.py index a42407c..195bb64 100644 --- a/pynautobot/core/app.py +++ b/pynautobot/core/app.py @@ -86,38 +86,14 @@ def choices(self): return self._choices - def custom_choices(self): - """Returns custom-fields response from app - - .. note:: - - This method is deprecated and will be removed in pynautobot - 2.0 or newer. Please use `custom_fields()` instead. - - :Returns: Raw response from Nautobot's custom-fields endpoint. - :Raises: :py:class:`.RequestError` if called for an invalid endpoint. - :Example: - - >>> nb.extras.custom_choices() - {'Testfield1': {'Testvalue2': 2, 'Testvalue1': 1}, - 'Testfield2': {'Othervalue2': 4, 'Othervalue1': 3}} - """ - logger.warning( - "WARNING: The method 'custom_choices()' will be removed in " - "the next major version (2.x) of pynautobot. Please use " - "`custom_fields()` instead." - ) - - return self.custom_fields() - - def custom_fields(self): + def get_custom_fields(self): """Returns custom-fields response from app :Returns: Raw response from Nautobot's custom-fields endpoint. :Raises: :py:class:`.RequestError` if called for an invalid endpoint. :Example: - >>> nb.extras.custom_fields() + >>> nb.extras.get_custom_fields() [ { "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", @@ -142,21 +118,20 @@ def custom_fields(self): }, ] """ - custom_fields = Request( + return Request( base=f"{self.api.base_url}/{self.name}/custom-fields/", token=self.api.token, http_session=self.api.http_session, ).get() - return custom_fields - def custom_field_choices(self): + def get_custom_field_choices(self): """Returns custom-field-choices response from app :Returns: Raw response from Nautobot's custom-field-choices endpoint. :Raises: :py:class:`.RequestError` if called for an invalid endpoint. :Example: - >>> nb.extras.custom_field_choices() + >>> nb.extras.get_custom_field_choices() [ { "id": "5b39ba88-e5ab-4be2-89f5-5a016473b53c", @@ -175,12 +150,11 @@ def custom_field_choices(self): }, ] """ - custom_fields = Request( + return Request( base=f"{self.api.base_url}/{self.name}/custom-field-choices/", token=self.api.token, http_session=self.api.http_session, ).get() - return custom_fields def config(self): """Returns config response from app diff --git a/tests/integration/test_extras.py b/tests/integration/test_extras.py new file mode 100644 index 0000000..90c4166 --- /dev/null +++ b/tests/integration/test_extras.py @@ -0,0 +1,36 @@ +import pytest + + +class TestCustomField: + + """Verify we can create, custom field, and custom field choices.""" + + @pytest.fixture(scope="session") + def create_custom_field(self, nb_client): + data = { + "label": "test_cf", + "key": "test_cf", + "content_types": ["dcim.device"], + "type": "select", + "weight": 100, + "filter_logic": "loose", + } + return nb_client.extras.custom_fields.create(**data) + + @pytest.fixture(scope="session") + def create_custom_field_choices(self, nb_client, create_custom_field): + data = { + "value": "A", + "custom_field": create_custom_field["id"], + "weight": 100, + } + return nb_client.extras.custom_field_choices.create(**data) + + def test_custom_field(self, create_custom_field): + assert create_custom_field["label"] == "test_cf" + + def test_custom_field_choice(self, create_custom_field_choices): + assert create_custom_field_choices["value"] == "A" + + def test_custom_field_choice_to_cf(self, create_custom_field_choices, create_custom_field): + assert create_custom_field_choices["custom_field"]["id"] == create_custom_field["id"] diff --git a/tests/test_app.py b/tests/test_app.py index 07c6479..46e3dd6 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -20,7 +20,7 @@ class AppCustomFieldsTestCase(unittest.TestCase): @patch("pynautobot.api.version", "2.0") def test_custom_fields(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) - cfs = api.extras.custom_fields() + cfs = api.extras.get_custom_fields() session_get_mock.assert_called_once() expect_url = f"{api.base_url}/extras/custom-fields/" @@ -46,7 +46,7 @@ class AppCustomFieldChoicesTestCase(unittest.TestCase): @patch("pynautobot.api.version", "2.0") def test_custom_field_choices(self, session_get_mock): api = pynautobot.api(host, **def_kwargs) - choices = api.extras.custom_field_choices() + choices = api.extras.get_custom_field_choices() session_get_mock.assert_called_once() expect_url = f"{api.base_url}/extras/custom-field-choices/" @@ -85,11 +85,11 @@ class PluginAppCustomChoicesTestCase(unittest.TestCase): return_value={"Testfield1": {"TF1_1": 1, "TF1_2": 2}, "Testfield2": {"TF2_1": 3, "TF2_2": 4}}, ) @patch("pynautobot.api.version", "2.0") - def test_custom_choices(self, *_): + def test_custom_fields(self, *_): api = pynautobot.api(host, **def_kwargs) - choices = api.plugins.test_plugin.custom_fields() - self.assertEqual(len(choices), 2) - self.assertEqual(sorted(choices.keys()), ["Testfield1", "Testfield2"]) + custom_fields = api.plugins.test_plugin.get_custom_fields() + self.assertEqual(len(custom_fields), 2) + self.assertEqual(sorted(custom_fields.keys()), ["Testfield1", "Testfield2"]) @patch( "pynautobot.core.query.Request.get", From 046edd85afa8ed25dd9c730b91c18f23d9be772d Mon Sep 17 00:00:00 2001 From: pszulczewski Date: Tue, 24 Oct 2023 15:42:28 +0200 Subject: [PATCH 21/21] Release 2.0.1 --- CHANGELOG.md | 7 ++ poetry.lock | 333 ++++++++++++++++++++----------------------------- pyproject.toml | 2 +- 3 files changed, 143 insertions(+), 199 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 958de1c..1791835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v2.0.1 + +### Bug Fixes + +- (#140) Fixes SSL +- (#141) Fixes methods and endpoints naming overlap + ## v2.0.0 ### Significant Updates diff --git a/poetry.lock b/poetry.lock index 060143b..4771e97 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -14,14 +13,13 @@ files = [ [[package]] name = "astroid" -version = "3.0.0" +version = "3.0.1" description = "An abstract syntax tree for Python with inference support." -category = "dev" optional = false python-versions = ">=3.8.0" files = [ - {file = "astroid-3.0.0-py3-none-any.whl", hash = "sha256:f2510e7fdcd6cfda4ec50014726d4857abf79acfc010084ce8c26091913f1b25"}, - {file = "astroid-3.0.0.tar.gz", hash = "sha256:1defdbca052635dd29657ea674edfc45e4b5be9cd53630c5b084fcfed94344a8"}, + {file = "astroid-3.0.1-py3-none-any.whl", hash = "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca"}, + {file = "astroid-3.0.1.tar.gz", hash = "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e"}, ] [package.dependencies] @@ -31,7 +29,6 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -48,24 +45,25 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte [[package]] name = "babel" -version = "2.12.1" +version = "2.13.0" description = "Internationalization utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, - {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, + {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"}, + {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"}, ] [package.dependencies] pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + [[package]] name = "bandit" version = "1.7.5" description = "Security oriented static analyser for python code." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -87,34 +85,29 @@ yaml = ["PyYAML"] [[package]] name = "black" -version = "23.9.1" +version = "23.10.1" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, - {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, - {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, - {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, - {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, - {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, - {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, - {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, - {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, - {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, - {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, - {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, - {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, + {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, + {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, + {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, + {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, + {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, + {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, + {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, + {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, + {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, + {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, + {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, + {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, ] [package.dependencies] @@ -136,7 +129,6 @@ uvloop = ["uvloop (>=0.15.2)"] name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -146,109 +138,107 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.0" +version = "3.3.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win32.whl", hash = "sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"}, - {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, + {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, + {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, ] [[package]] name = "click" version = "8.1.7" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -263,7 +253,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -275,7 +264,6 @@ files = [ name = "dill" version = "0.3.7" description = "serialize all of Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -290,7 +278,6 @@ graph = ["objgraph (>=1.7.2)"] name = "docutils" version = "0.20.1" description = "Docutils -- Python Documentation Utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -302,7 +289,6 @@ files = [ name = "exceptiongroup" version = "1.1.3" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -317,7 +303,6 @@ test = ["pytest (>=6)"] name = "flake8" version = "5.0.4" description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" optional = false python-versions = ">=3.6.1" files = [ @@ -332,14 +317,13 @@ pyflakes = ">=2.5.0,<2.6.0" [[package]] name = "gitdb" -version = "4.0.10" +version = "4.0.11" description = "Git Object Database" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, - {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, + {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, + {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, ] [package.dependencies] @@ -347,27 +331,25 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.37" +version = "3.1.40" description = "GitPython is a Python library used to interact with Git repositories" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.37-py3-none-any.whl", hash = "sha256:5f4c4187de49616d710a77e98ddf17b4782060a1788df441846bddefbb89ab33"}, - {file = "GitPython-3.1.37.tar.gz", hash = "sha256:f9b9ddc0761c125d5780eab2d64be4873fc6817c2899cbcb34b02344bdc7bc54"}, + {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"}, + {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" [package.extras] -test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar"] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"] [[package]] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -379,7 +361,6 @@ files = [ name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -391,7 +372,6 @@ files = [ name = "importlib-metadata" version = "6.8.0" description = "Read metadata from Python packages" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -411,7 +391,6 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -423,7 +402,6 @@ files = [ name = "invoke" version = "2.2.0" description = "Pythonic task execution" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -435,7 +413,6 @@ files = [ name = "isort" version = "5.12.0" description = "A Python utility / library to sort Python imports." -category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -453,7 +430,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -471,7 +447,6 @@ i18n = ["Babel (>=2.7)"] name = "markdown-it-py" version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -496,7 +471,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -566,7 +540,6 @@ files = [ name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -578,7 +551,6 @@ files = [ name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -590,7 +562,6 @@ files = [ name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -602,7 +573,6 @@ files = [ name = "packaging" version = "23.2" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -614,7 +584,6 @@ files = [ name = "pathspec" version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -626,7 +595,6 @@ files = [ name = "pbr" version = "5.11.1" description = "Python Build Reasonableness" -category = "dev" optional = false python-versions = ">=2.6" files = [ @@ -638,7 +606,6 @@ files = [ name = "platformdirs" version = "3.11.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -654,7 +621,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-co name = "pluggy" version = "1.3.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -670,7 +636,6 @@ testing = ["pytest", "pytest-benchmark"] name = "pycodestyle" version = "2.9.1" description = "Python style guide checker" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -682,7 +647,6 @@ files = [ name = "pydocstyle" version = "6.3.0" description = "Python docstring style checker" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -700,7 +664,6 @@ toml = ["tomli (>=1.2.3)"] name = "pyflakes" version = "2.5.0" description = "passive checker of Python programs" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -712,7 +675,6 @@ files = [ name = "pygments" version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -725,23 +687,22 @@ plugins = ["importlib-metadata"] [[package]] name = "pylint" -version = "3.0.0" +version = "3.0.2" description = "python code static checker" -category = "dev" optional = false python-versions = ">=3.8.0" files = [ - {file = "pylint-3.0.0-py3-none-any.whl", hash = "sha256:21da8ed1294f88d66c82eb3e624a0993291613548bb17fbccaa220c31c41293b"}, - {file = "pylint-3.0.0.tar.gz", hash = "sha256:d22816c963816d7810b87afe0bdf5c80009e1078ecbb9c8f2e2a24d4430039b1"}, + {file = "pylint-3.0.2-py3-none-any.whl", hash = "sha256:60ed5f3a9ff8b61839ff0348b3624ceeb9e6c2a92c514d81c9cc273da3b6bcda"}, + {file = "pylint-3.0.2.tar.gz", hash = "sha256:0d4c286ef6d2f66c8bfb527a7f8a629009e42c99707dec821a03e1b51a4c1496"}, ] [package.dependencies] -astroid = ">=3.0.0,<=3.1.0-dev0" +astroid = ">=3.0.1,<=3.1.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, - {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, ] isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.8" @@ -758,7 +719,6 @@ testutils = ["gitpython (>3)"] name = "pytest" version = "7.4.2" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -781,7 +741,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytz" version = "2023.3.post1" description = "World timezone definitions, modern and historical" -category = "dev" optional = false python-versions = "*" files = [ @@ -793,7 +752,6 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -853,7 +811,6 @@ files = [ name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -875,7 +832,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-mock" version = "1.11.0" description = "Mock out responses from the requests package" -category = "dev" optional = false python-versions = "*" files = [ @@ -895,7 +851,6 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes name = "rich" version = "13.6.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -915,7 +870,6 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -927,7 +881,6 @@ files = [ name = "smmap" version = "5.0.1" description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -939,7 +892,6 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" optional = false python-versions = "*" files = [ @@ -951,7 +903,6 @@ files = [ name = "sphinx" version = "7.1.2" description = "Python documentation generator" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -987,7 +938,6 @@ test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] name = "sphinxcontrib-applehelp" version = "1.0.4" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1003,7 +953,6 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1019,7 +968,6 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1035,7 +983,6 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1050,7 +997,6 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1066,7 +1012,6 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1082,7 +1027,6 @@ test = ["pytest"] name = "stevedore" version = "5.1.0" description = "Manage dynamic plugins for Python applications" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1097,7 +1041,6 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1109,7 +1052,6 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1121,7 +1063,6 @@ files = [ name = "tomlkit" version = "0.12.1" description = "Style preserving TOML library" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1133,7 +1074,6 @@ files = [ name = "typing-extensions" version = "4.8.0" description = "Backported and Experimental Type Hints for Python 3.8+" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1143,14 +1083,13 @@ files = [ [[package]] name = "urllib3" -version = "1.26.17" +version = "1.26.18" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.17-py2.py3-none-any.whl", hash = "sha256:94a757d178c9be92ef5539b8840d48dc9cf1b2709c9d6b588232a055c524458b"}, - {file = "urllib3-1.26.17.tar.gz", hash = "sha256:24d6a242c28d29af46c3fae832c36db3bbebcc533dd1bb549172cd739c82df21"}, + {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, + {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, ] [package.extras] @@ -1162,7 +1101,6 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "yamllint" version = "1.32.0" description = "A linter for YAML files." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1181,7 +1119,6 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] name = "zipp" version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" optional = false python-versions = ">=3.8" files = [ diff --git a/pyproject.toml b/pyproject.toml index 9640d41..d0f5e39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "pynautobot" -version = "2.0.0" +version = "2.0.1" description = "Nautobot API client library" authors = ["Network to Code, LLC "] readme = "README.md"