From f15d89940b7d8aa48f040e26b372ee70acff2ec4 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 00:23:07 -0400 Subject: [PATCH 01/13] Centralizes parameter utilities Fixes issue when using Python snake_case for resultsLimit Cleans up imports --- mygeotab/api.py | 50 ++++----------------------------- mygeotab/api_async.py | 29 +++++++------------ mygeotab/cli.py | 25 +++++++++-------- mygeotab/parameters.py | 62 +++++++++++++++++++++++++++++++++++++++++ mygeotab/serializers.py | 2 +- 5 files changed, 91 insertions(+), 77 deletions(-) create mode 100644 mygeotab/parameters.py diff --git a/mygeotab/api.py b/mygeotab/api.py index 20e2248..fa66769 100644 --- a/mygeotab/api.py +++ b/mygeotab/api.py @@ -9,8 +9,6 @@ from __future__ import unicode_literals -import copy -import re import ssl import sys from urllib.parse import urlparse @@ -23,6 +21,7 @@ from . import __title__, __version__ from .exceptions import AuthenticationException, MyGeotabException, TimeoutException +from .parameters import camelcaseify_parameters, convert_get_parameters from .serializers import json_deserialize, json_serialize DEFAULT_TIMEOUT = 300 @@ -102,7 +101,7 @@ def call(self, method, **parameters): """ if method is None: raise Exception("A method name must be specified") - params = process_parameters(parameters) + params = camelcaseify_parameters(parameters) if self.credentials and not self.credentials.session_id: self.authenticate() if "credentials" not in params and self.credentials.session_id: @@ -168,22 +167,7 @@ def get(self, type_name, **parameters): :return: The results from the server. :rtype: list """ - if parameters: - # Detect resultsLimit if passed camelCase or python_case and - # remove from parameters (otherwise they will become part of search) - results_limit = parameters.get("resultsLimit") - if results_limit is not None: - del parameters["resultsLimit"] - else: - results_limit = parameters.get("results_limit") - if results_limit is not None: - del parameters["results_limit"] - - if "search" in parameters: - parameters.update(parameters["search"]) - del parameters["search"] - parameters = dict(search=parameters, resultsLimit=results_limit) - return self.call("Get", type_name=type_name, **parameters) + return self.call("Get", type_name=type_name, **convert_get_parameters(parameters)) def add(self, type_name, entity): """Adds an entity using the API. Shortcut for using call() with the 'Add' method. @@ -333,9 +317,7 @@ def __str__(self): return "{0} @ {1}/{2}".format(self.username, self.server, self.database) def __repr__(self): - return "Credentials(username={username}, database={database})".format( - username=self.username, database=self.database - ) + return "Credentials(username={username}, database={database})".format(username=self.username, database=self.database) def get_param(self): """A simple representation of the credentials object for passing into the API.authenticate() server call. @@ -444,32 +426,10 @@ def server_call(method, server, timeout=DEFAULT_TIMEOUT, verify_ssl=True, proxie raise Exception("A method name must be specified") if server is None: raise Exception("A server (eg. my3.geotab.com) must be specified") - parameters = process_parameters(parameters) + parameters = camelcaseify_parameters(parameters) return _query(server, method, parameters, timeout=timeout, verify_ssl=verify_ssl, proxies=proxies) -def process_parameters(parameters): - """Allows the use of Pythonic-style parameters with underscores instead of camel-case. - - :param parameters: The parameters object. - :type parameters: dict - :return: The processed parameters. - :rtype: dict - """ - if not parameters: - return {} - params = copy.copy(parameters) - for param_name in parameters: - value = parameters[param_name] - server_param_name = re.sub(r"_(\w)", lambda m: m.group(1).upper(), param_name) - if isinstance(value, dict): - value = process_parameters(value) - params[server_param_name] = value - if server_param_name != param_name: - del params[param_name] - return params - - def get_api_url(server): """Formats the server URL properly in order to query the API. diff --git a/mygeotab/api_async.py b/mygeotab/api_async.py index af82f81..4d7799c 100644 --- a/mygeotab/api_async.py +++ b/mygeotab/api_async.py @@ -8,19 +8,18 @@ """ import asyncio - import ssl from concurrent.futures import TimeoutError import aiohttp -from mygeotab import api -from mygeotab.api import DEFAULT_TIMEOUT, get_headers -from mygeotab.exceptions import MyGeotabException, TimeoutException, AuthenticationException -from mygeotab.serializers import json_serialize, json_deserialize +from .api import API as SyncAPI, DEFAULT_TIMEOUT, _process, get_api_url, get_headers +from .exceptions import AuthenticationException, MyGeotabException, TimeoutException +from .parameters import camelcaseify_parameters, convert_get_parameters +from .serializers import json_deserialize, json_serialize -class API(api.API): +class API(SyncAPI): """A simple, asynchronous, and Pythonic wrapper for the MyGeotab API.""" def __init__( @@ -60,7 +59,7 @@ async def call_async(self, method, **parameters): """ if method is None: raise Exception("A method name must be specified") - params = api.process_parameters(parameters) + params = camelcaseify_parameters(parameters) if self.credentials and not self.credentials.session_id: self.authenticate() if "credentials" not in params and self.credentials.session_id: @@ -105,15 +104,7 @@ async def get_async(self, type_name, **parameters): :raise MyGeotabException: Raises when an exception occurs on the MyGeotab server. :raise TimeoutException: Raises when the request does not respond after some time. """ - if parameters: - results_limit = parameters.get("resultsLimit", None) - if results_limit is not None: - del parameters["resultsLimit"] - if "search" in parameters: - parameters.update(parameters["search"]) - del parameters["search"] - parameters = dict(search=parameters, resultsLimit=results_limit) - return await self.call_async("Get", type_name=type_name, **parameters) + return await self.call_async("Get", type_name=type_name, **convert_get_parameters(parameters)) async def add_async(self, type_name, entity): """ @@ -178,7 +169,7 @@ async def server_call_async(method, server, timeout=DEFAULT_TIMEOUT, verify_ssl= raise Exception("A method name must be specified") if server is None: raise Exception("A server (eg. my3.geotab.com) must be specified") - parameters = api.process_parameters(parameters) + parameters = camelcaseify_parameters(parameters) return await _query(server, method, parameters, timeout=timeout, verify_ssl=verify_ssl) @@ -196,7 +187,7 @@ async def _query(server, method, parameters, timeout=DEFAULT_TIMEOUT, verify_ssl :raise TimeoutException: Raises when the request does not respond after some time. :raise aiohttp.ClientResponseError: Raises when there is an HTTP status code that indicates failure. """ - api_endpoint = api.get_api_url(server) + api_endpoint = get_api_url(server) params = dict(id=-1, method=method, params=parameters) headers = get_headers() @@ -226,4 +217,4 @@ async def _query(server, method, parameters, timeout=DEFAULT_TIMEOUT, verify_ssl raise TimeoutException(server) from exc if content_type and "application/json" not in content_type.lower(): return body - return api._process(json_deserialize(body)) + return _process(json_deserialize(body)) diff --git a/mygeotab/cli.py b/mygeotab/cli.py index 3cab468..7b98b55 100644 --- a/mygeotab/cli.py +++ b/mygeotab/cli.py @@ -9,14 +9,15 @@ import configparser import os.path - import sys import click import mygeotab -import mygeotab.api -import mygeotab.dates + +from . import API, __title__, __version__, dates +from .api import Credentials +from .exceptions import AuthenticationException class Session(object): @@ -28,7 +29,7 @@ def __init__(self): @staticmethod def _get_config_file(): - config_path = click.get_app_dir(mygeotab.__title__) + config_path = click.get_app_dir(__title__) if not os.path.exists(config_path): os.makedirs(config_path) return os.path.join(config_path, "config.ini") @@ -82,7 +83,7 @@ def load(self, name=None): session_id = config.get(section_name, "session_id") database = config.get(section_name, "database") server = config.get(section_name, "server") - self.credentials = mygeotab.Credentials(username, session_id, database, server) + self.credentials = Credentials(username, session_id, database, server) except configparser.NoSectionError: self.credentials = None except configparser.NoOptionError: @@ -95,14 +96,14 @@ def get_sessions(self): def get_api(self): if self.credentials: - return mygeotab.API.from_credentials(self.credentials) + return API.from_credentials(self.credentials) return None def login(self, username, password=None, database=None, server=None): if server: - api = mygeotab.API(username=username, password=password, database=database, server=server) + api = API(username=username, password=password, database=database, server=server) else: - api = mygeotab.API(username=username, password=password, database=database) + api = API(username=username, password=password, database=database) self.credentials = api.authenticate() self.save() @@ -139,7 +140,7 @@ def login(session, user, password, database=None, server=None): click.echo("Logged in as: %s" % session.credentials) session.load(database) return session.get_api() - except mygeotab.AuthenticationException: + except AuthenticationException: click.echo("Incorrect credentials. Please try again.") sys.exit(0) @@ -206,7 +207,7 @@ def console(session, database=None, user=None, password=None, server=None): :param server: The server ie. my23.geotab.com. Optional as this usually gets resolved upon authentication. """ local_vars = _populate_locals(database, password, server, session, user) - myg_console_version = "MyGeotab Console {0}".format(mygeotab.__version__) + myg_console_version = "MyGeotab Console {0}".format(__version__) version = "{0} [Python {1}]".format(myg_console_version, sys.version.replace("\n", "")) auth_line = ("Logged in as: %s" % session.credentials) if session.credentials else "Not logged in" banner = "\n".join([version, auth_line]) @@ -258,11 +259,11 @@ def _populate_locals(database, password, server, session, user): api = login(session, user, password, database, server) try: api.get("User", name=session.credentials.username) - except mygeotab.AuthenticationException: + except AuthenticationException: # Credentials expired, try logging in again click.echo("Your session has expired. Please login again.") api = login(session, user, password, database, server) - return dict(myg=api, mygeotab=mygeotab, dates=mygeotab.dates) + return dict(myg=api, mygeotab=mygeotab, dates=dates) main.add_command(console) diff --git a/mygeotab/parameters.py b/mygeotab/parameters.py new file mode 100644 index 0000000..3eb6a66 --- /dev/null +++ b/mygeotab/parameters.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- + +""" +mygeotab.parameters +~~~~~~~~~~~~~~~~~~~ + +This module contains parameter utilites used in the MyGeotab API. +""" + +import re +from copy import copy +from typing import Any + + +def camelcaseify_parameters(parameters: dict[str, Any]) -> dict[str, Any]: + """Allows the use of Pythonic-style parameters with underscores instead of camel-case. + + :param parameters: The parameters object. + :type parameters: dict + :return: The processed parameters. + :rtype: dict + """ + if not parameters: + return dict() + params = copy(parameters) + for param_name in parameters: + value = parameters[param_name] + server_param_name = re.sub(r"_(\w)", lambda m: m.group(1).upper(), param_name) + if isinstance(value, dict): + value = camelcaseify_parameters(value) + params[server_param_name] = value + if server_param_name != param_name: + del params[param_name] + return params + + +def convert_get_parameters(parameters: dict[str, Any]) -> dict[str, Any]: + """Converts parameters passed into a get() call to a format suitable for the MyGeotab API. + It detects if a 'search' dictionary is passed and flattens it into the top-level parameters. + It also detects 'resultsLimit' or 'results_limit' and removes it from the parameters + so it doesn't become part of the search. + + :param parameters: The parameters object. + :type parameters: dict + :return: The processed parameters. + :rtype: dict + """ + if not parameters: + return dict() + + results_limit = parameters.get("resultsLimit") + if results_limit is not None: + del parameters["resultsLimit"] + else: + results_limit = parameters.get("results_limit") + if results_limit is not None: + del parameters["results_limit"] + + if "search" in parameters: + parameters.update(parameters["search"]) + del parameters["search"] + return dict(search=parameters, resultsLimit=results_limit) diff --git a/mygeotab/serializers.py b/mygeotab/serializers.py index 11e50f0..043ed0c 100644 --- a/mygeotab/serializers.py +++ b/mygeotab/serializers.py @@ -12,7 +12,7 @@ import arrow -from mygeotab import dates +from . import dates use_rapidjson = False try: From c3b9f13e95697a1163449c6a7acb5d6a037a2446 Mon Sep 17 00:00:00 2001 From: "Aaron T." <50092+aaront@users.noreply.github.com> Date: Wed, 6 Aug 2025 00:31:51 -0400 Subject: [PATCH 02/13] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- mygeotab/parameters.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mygeotab/parameters.py b/mygeotab/parameters.py index 3eb6a66..2b19a8a 100644 --- a/mygeotab/parameters.py +++ b/mygeotab/parameters.py @@ -4,7 +4,7 @@ mygeotab.parameters ~~~~~~~~~~~~~~~~~~~ -This module contains parameter utilites used in the MyGeotab API. +This module contains parameter utilities used in the MyGeotab API. """ import re @@ -59,4 +59,7 @@ def convert_get_parameters(parameters: dict[str, Any]) -> dict[str, Any]: if "search" in parameters: parameters.update(parameters["search"]) del parameters["search"] - return dict(search=parameters, resultsLimit=results_limit) + result = {'search': parameters} + if results_limit is not None: + result['resultsLimit'] = results_limit + return result From d2fd80301d2d37e5a9af14520cbd777601678743 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 00:36:37 -0400 Subject: [PATCH 03/13] Updates dependencies --- Pipfile.lock | 982 +++++++++++++++++++++++++++---------------------- pyproject.toml | 1 - 2 files changed, 543 insertions(+), 440 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index f5494f7..8a63da2 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0339406113e3c9923add050960dc36776bef4cda93a607a4f68a6321f9fc7090" + "sha256": "73f1154538ae649b1845f2255ffb7f12078492832bb95df514b42f250a58a9b3" }, "pipfile-spec": 6, "requires": {}, @@ -1003,230 +1003,245 @@ "version": "==24.2.0" }, "black": { - "extras": [ - "jupyter" - ], - "hashes": [ - "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6", - "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e", - "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f", - "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018", - "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e", - "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd", - "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4", - "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed", - "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2", - "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42", - "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af", - "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb", - "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368", - "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb", - "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af", - "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed", - "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47", - "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2", - "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a", - "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c", - "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920", - "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1" + "hashes": [ + "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", + "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", + "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", + "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", + "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", + "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", + "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", + "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", + "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", + "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", + "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", + "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", + "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0", + "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", + "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", + "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", + "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355", + "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", + "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e", + "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", + "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", + "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.8.0" + "markers": "python_version >= '3.9'", + "version": "==25.1.0" }, "certifi": { "hashes": [ - "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", - "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9" + "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", + "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5" ], - "markers": "python_version >= '3.6'", - "version": "==2024.8.30" + "markers": "python_version >= '3.7'", + "version": "==2025.8.3" }, "charset-normalizer": { "hashes": [ - "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", - "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", - "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", - "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", - "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", - "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", - "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", - "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", - "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", - "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", - "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", - "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", - "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", - "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", - "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", - "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", - "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", - "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", - "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", - "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", - "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", - "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", - "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", - "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", - "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", - "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", - "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", - "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", - "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", - "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", - "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", - "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", - "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", - "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", - "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", - "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", - "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", - "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", - "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", - "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", - "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", - "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", - "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", - "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", - "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", - "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", - "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", - "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", - "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", - "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", - "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", - "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", - "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", - "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", - "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", - "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", - "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", - "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", - "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", - "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", - "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", - "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", - "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", - "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", - "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", - "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", - "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", - "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", - "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", - "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", - "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", - "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", - "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", - "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", - "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", - "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", - "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", - "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", - "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", - "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", - "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", - "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", - "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", - "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", - "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", - "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", - "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", - "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", - "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", - "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" - ], - "markers": "python_full_version >= '3.7.0'", - "version": "==3.3.2" + "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", + "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45", + "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", + "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", + "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", + "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", + "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d", + "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", + "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184", + "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", + "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b", + "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64", + "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", + "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", + "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", + "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344", + "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58", + "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", + "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", + "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", + "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", + "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", + "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", + "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", + "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", + "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1", + "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01", + "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", + "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58", + "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", + "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", + "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2", + "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a", + "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", + "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", + "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5", + "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb", + "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f", + "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", + "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", + "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", + "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", + "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7", + "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", + "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455", + "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", + "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4", + "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", + "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", + "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", + "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", + "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", + "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", + "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", + "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", + "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", + "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", + "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa", + "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", + "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", + "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", + "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", + "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", + "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", + "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02", + "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", + "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", + "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", + "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", + "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", + "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", + "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", + "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681", + "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", + "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", + "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a", + "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", + "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", + "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", + "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", + "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027", + "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", + "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", + "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", + "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", + "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", + "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", + "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da", + "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", + "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f", + "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", + "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.2" }, "click": { "hashes": [ - "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" + "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", + "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b" ], - "markers": "python_version >= '3.7'", - "version": "==8.1.7" + "markers": "python_version >= '3.10'", + "version": "==8.2.1" }, "coverage": { "extras": [ "toml" ], "hashes": [ - "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", - "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", - "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", - "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", - "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", - "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", - "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", - "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", - "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", - "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", - "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", - "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", - "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", - "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", - "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", - "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", - "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", - "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", - "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", - "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", - "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", - "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", - "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", - "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", - "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", - "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", - "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", - "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", - "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", - "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", - "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", - "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", - "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", - "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", - "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", - "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", - "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", - "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", - "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", - "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", - "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", - "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", - "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", - "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", - "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", - "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", - "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", - "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", - "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", - "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", - "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", - "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", - "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", - "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", - "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", - "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", - "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", - "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", - "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", - "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", - "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", - "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", - "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", - "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", - "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", - "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", - "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", - "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", - "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", - "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", - "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", - "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc" + "sha256:0100b19f230df72c90fdb36db59d3f39232391e8d89616a7de30f677da4f532b", + "sha256:04c74f9ef1f925456a9fd23a7eef1103126186d0500ef9a0acb0bd2514bdc7cc", + "sha256:069b779d03d458602bc0e27189876e7d8bdf6b24ac0f12900de22dd2154e6ad7", + "sha256:11333094c1bff621aa811b67ed794865cbcaa99984dedea4bd9cf780ad64ecba", + "sha256:12e52b5aa00aa720097d6947d2eb9e404e7c1101ad775f9661ba165ed0a28303", + "sha256:14fb5b6641ab5b3c4161572579f0f2ea8834f9d3af2f7dd8fbaecd58ef9175cc", + "sha256:164429decd0d6b39a0582eaa30c67bf482612c0330572343042d0ed9e7f15c20", + "sha256:1a2e934e9da26341d342d30bfe91422bbfdb3f1f069ec87f19b2909d10d8dcc4", + "sha256:20f405188d28da9522b7232e51154e1b884fc18d0b3a10f382d54784715bbe01", + "sha256:228946da741558904e2c03ce870ba5efd9cd6e48cbc004d9a27abee08100a15a", + "sha256:22aca3e691c7709c5999ccf48b7a8ff5cf5a8bd6fe9b36efbd4993f5a36b2fcf", + "sha256:248b5394718e10d067354448dc406d651709c6765669679311170da18e0e9af8", + "sha256:2c3b210d79925a476dfc8d74c7d53224888421edebf3a611f3adae923e212b27", + "sha256:2d358f259d8019d4ef25d8c5b78aca4c7af25e28bd4231312911c22a0e824a57", + "sha256:2e980e4179f33d9b65ac4acb86c9c0dde904098853f27f289766657ed16e07b3", + "sha256:38fd1ccfca7838c031d7a7874d4353e2f1b98eb5d2a80a2fe5732d542ae25e9c", + "sha256:3b990df23dd51dccce26d18fb09fd85a77ebe46368f387b0ffba7a74e470b31b", + "sha256:3f37516458ec1550815134937f73d6d15b434059cd10f64678a2068f65c62406", + "sha256:44329cbed24966c0b49acb386352c9722219af1f0c80db7f218af7793d251902", + "sha256:4c2de4cb80b9990e71c62c2d3e9f3ec71b804b1f9ca4784ec7e74127e0f42468", + "sha256:5250bda76e30382e0a2dcd68d961afcab92c3a7613606e6269855c6979a1b0bb", + "sha256:52d708b5fd65589461381fa442d9905f5903d76c086c6a4108e8e9efdca7a7ed", + "sha256:5b9d538e8e04916a5df63052d698b30c74eb0174f2ca9cd942c981f274a18eaf", + "sha256:5c61675a922b569137cf943770d7ad3edd0202d992ce53ac328c5ff68213ccf4", + "sha256:5d6e6d84e6dd31a8ded64759626627247d676a23c1b892e1326f7c55c8d61055", + "sha256:64586ce42bbe0da4d9f76f97235c545d1abb9b25985a8791857690f96e23dc3b", + "sha256:651015dcd5fd9b5a51ca79ece60d353cacc5beaf304db750407b29c89f72fe2b", + "sha256:65b451949cb789c346f9f9002441fc934d8ccedcc9ec09daabc2139ad13853f7", + "sha256:6c031da749a05f7a01447dd7f47beedb498edd293e31e1878c0d52db18787df0", + "sha256:6eb586fa7d2aee8d65d5ae1dd71414020b2f447435c57ee8de8abea0a77d5074", + "sha256:6f0cbe5f7dd19f3a32bac2251b95d51c3b89621ac88a2648096ce40f9a5aa1e7", + "sha256:718044729bf1fe3e9eb9f31b52e44ddae07e434ec050c8c628bf5adc56fe4bdd", + "sha256:71d40b3ac0f26fa9ffa6ee16219a714fed5c6ec197cdcd2018904ab5e75bcfa3", + "sha256:75bf7ab2374a7eb107602f1e07310cda164016cd60968abf817b7a0b5703e288", + "sha256:75cc1a3f8c88c69bf16a871dab1fe5a7303fdb1e9f285f204b60f1ee539b8fc0", + "sha256:765b13b164685a2f8b2abef867ad07aebedc0e090c757958a186f64e39d63dbd", + "sha256:76c1ffaaf4f6f0f6e8e9ca06f24bb6454a7a5d4ced97a1bc466f0d6baf4bd518", + "sha256:79f0283ab5e6499fd5fe382ca3d62afa40fb50ff227676a3125d18af70eabf65", + "sha256:7f10ca4cde7b466405cce0a0e9971a13eb22e57a5ecc8b5f93a81090cc9c7eb9", + "sha256:81bf6a32212f9f66da03d63ecb9cd9bd48e662050a937db7199dbf47d19831de", + "sha256:835f39e618099325e7612b3406f57af30ab0a0af350490eff6421e2e5f608e46", + "sha256:86da8a3a84b79ead5c7d0e960c34f580bc3b231bb546627773a3f53c532c2f21", + "sha256:890ad3a26da9ec7bf69255b9371800e2a8da9bc223ae5d86daeb940b42247c83", + "sha256:8f34b09f68bdadec122ffad312154eda965ade433559cc1eadd96cca3de5c824", + "sha256:916369b3b914186b2c5e5ad2f7264b02cff5df96cdd7cdad65dccd39aa5fd9f0", + "sha256:95db3750dd2e6e93d99fa2498f3a1580581e49c494bddccc6f85c5c21604921f", + "sha256:95e23987b52d02e7c413bf2d6dc6288bd5721beb518052109a13bfdc62c8033b", + "sha256:96e5921342574a14303dfdb73de0019e1ac041c863743c8fe1aa6c2b4a257226", + "sha256:98a838101321ac3089c9bb1d4bfa967e8afed58021fda72d7880dc1997f20ae1", + "sha256:99cef9731c8a39801830a604cc53c93c9e57ea8b44953d26589499eded9576e0", + "sha256:99d16f15cb5baf0729354c5bd3080ae53847a4072b9ba1e10957522fb290417f", + "sha256:9bdff88e858ee608a924acfad32a180d2bf6e13e059d6a7174abbae075f30436", + "sha256:9c1cd71483ea78331bdfadb8dcec4f4edfb73c7002c1206d8e0af6797853f5be", + "sha256:9dd37e9ac00d5eb72f38ed93e3cdf2280b1dbda3bb9b48c6941805f265ad8d87", + "sha256:9f75dbf4899e29a37d74f48342f29279391668ef625fdac6d2f67363518056a1", + "sha256:a219b70100500d0c7fd3ebb824a3302efb6b1a122baa9d4eb3f43df8f0b3d899", + "sha256:a3e853cc04987c85ec410905667eed4bf08b1d84d80dfab2684bb250ac8da4f6", + "sha256:a7df481e7508de1c38b9b8043da48d94931aefa3e32b47dd20277e4978ed5b95", + "sha256:a91e027d66eff214d88d9afbe528e21c9ef1ecdf4956c46e366c50f3094696d0", + "sha256:abb57fdd38bf6f7dcc66b38dafb7af7c5fdc31ac6029ce373a6f7f5331d6f60f", + "sha256:aca7b5645afa688de6d4f8e89d30c577f62956fefb1bad021490d63173874186", + "sha256:adda2268b8cf0d11f160fad3743b4dfe9813cd6ecf02c1d6397eceaa5b45b388", + "sha256:ae385e1d58fbc6a9b1c315e5510ac52281e271478b45f92ca9b5ad42cf39643f", + "sha256:bc2e69b795d97ee6d126e7e22e78a509438b46be6ff44f4dccbb5230f550d340", + "sha256:bc3945b7bad33957a9eca16e9e5eae4b17cb03173ef594fdaad228f4fc7da53b", + "sha256:be127f292496d0fbe20d8025f73221b36117b3587f890346e80a13b310712982", + "sha256:bf67d1787cd317c3f8b2e4c6ed1ae93497be7e30605a0d32237ac37a37a8a322", + "sha256:c2e117e64c26300032755d4520cd769f2623cde1a1d1c3515b05a3b8add0ade1", + "sha256:c7195444b932356055a8e287fa910bf9753a84a1bc33aeb3770e8fca521e032e", + "sha256:ca07fa78cc9d26bc8c4740de1abd3489cf9c47cc06d9a8ab3d552ff5101af4c0", + "sha256:cc3902584d25c7eef57fb38f440aa849a26a3a9f761a029a72b69acfca4e31f8", + "sha256:d800705f6951f75a905ea6feb03fff8f3ea3468b81e7563373ddc29aa3e5d1ca", + "sha256:d8f2d83118f25328552c728b8e91babf93217db259ca5c2cd4dd4220b8926293", + "sha256:daaf98009977f577b71f8800208f4d40d4dcf5c2db53d4d822787cdc198d76e1", + "sha256:de3c6271c482c250d3303fb5c6bdb8ca025fff20a67245e1425df04dc990ece9", + "sha256:e33e79a219105aa315439ee051bd50b6caa705dc4164a5aba6932c8ac3ce2d98", + "sha256:e4545e906f595ee8ab8e03e21be20d899bfc06647925bc5b224ad7e8c40e08b8", + "sha256:e4f5f1320f8ee0d7cfa421ceb257bef9d39fd614dd3ddcfcacd284d4824ed2c2", + "sha256:e8415918856a3e7d57a4e0ad94651b761317de459eb74d34cc1bb51aad80f07e", + "sha256:e96649ac34a3d0e6491e82a2af71098e43be2874b619547c3282fc11d3840a4b", + "sha256:ea58b112f2966a8b91eb13f5d3b1f8bb43c180d624cd3283fb33b1cedcc2dd75", + "sha256:ea8d8fe546c528535c761ba424410bbeb36ba8a0f24be653e94b70c93fd8a8ca", + "sha256:f256173b48cc68486299d510a3e729a96e62c889703807482dbf56946befb5c8", + "sha256:f287a25a8ca53901c613498e4a40885b19361a2fe8fbfdbb7f8ef2cad2a23f03", + "sha256:f2a79145a531a0e42df32d37be5af069b4a914845b6f686590739b786f2f7bce", + "sha256:f35481d42c6d146d48ec92d4e239c23f97b53a3f1fbd2302e7c64336f28641fe", + "sha256:fd17f427f041f6b116dc90b4049c6f3e1230524407d00daa2d8c7915037b5947", + "sha256:fe024d40ac31eb8d5aae70215b41dafa264676caa4404ae155f77d2fa95c37bb" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==7.6.1" + "markers": "python_version >= '3.9'", + "version": "==7.10.2" }, "frozenlist": { "hashes": [ @@ -1321,42 +1336,78 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "libcst": { "hashes": [ - "sha256:061d6855ef30efe38b8a292b7e5d57c8e820e71fc9ec9846678b60a934b53bbb", - "sha256:17d71001cb25e94cfe8c3d997095741a8c4aa7a6d234c0f972bc42818c88dfaf", - "sha256:279b54568ea1f25add50ea4ba3d76d4f5835500c82f24d54daae4c5095b986aa", - "sha256:2d47de16d105e7dd5f4e01a428d9f4dc1e71efd74f79766daf54528ce37f23c3", - "sha256:3399e6c95df89921511b44d8c5bf6a75bcbc2d51f1f6429763609ba005c10f6b", - "sha256:3401dae41fe24565387a65baee3887e31a44e3e58066b0250bc3f3ccf85b1b5a", - "sha256:3c6a8faab9da48c5b371557d0999b4ca51f4f2cbd37ee8c2c4df0ac01c781465", - "sha256:449e0b16604f054fa7f27c3ffe86ea7ef6c409836fe68fe4e752a1894175db00", - "sha256:48601e3e590e2d6a7ab8c019cf3937c70511a78d778ab3333764531253acdb33", - "sha256:5da9d7dc83801aba3b8d911f82dc1a375db0d508318bad79d9fb245374afe068", - "sha256:62e2682ee1567b6a89c91853865372bf34f178bfd237853d84df2b87b446e654", - "sha256:7c54aa66c86d8ece9c93156a2cf5ca512b0dce40142fe9e072c86af2bf892411", - "sha256:7ece51d935bc9bf60b528473d2e5cc67cbb88e2f8146297e40ee2c7d80be6f13", - "sha256:81653dea1cdfa4c6520a7c5ffb95fa4d220cbd242e446c7a06d42d8636bfcbba", - "sha256:8e54c777b8d27339b70f304d16fc8bc8674ef1bd34ed05ea874bf4921eb5a313", - "sha256:9d0cc3c5a2a51fa7e1d579a828c0a2e46b2170024fd8b1a0691c8a52f3abb2d9", - "sha256:addc6d585141a7677591868886f6bda0577529401a59d210aa8112114340e129", - "sha256:b8ecdba8934632b4dadacb666cd3816627a6ead831b806336972ccc4ba7ca0e9", - "sha256:bb0abf627ee14903d05d0ad9b2c6865f1b21eb4081e2c7bea1033f85db2b8bae", - "sha256:cb4e42ea107a37bff7f9fdbee9532d39f9ea77b89caa5c5112b37057b12e0838", - "sha256:d024f44059a853b4b852cfc04fec33e346659d851371e46fc8e7c19de24d3da9", - "sha256:d1989fa12d3cd79118ebd29ebe2a6976d23d509b1a4226bc3d66fcb7cb50bd5d", - "sha256:e6227562fc5c9c1efd15dfe90b0971ae254461b8b6b23c1b617139b6003de1c1", - "sha256:f42797309bb725f0f000510d5463175ccd7155395f09b5e7723971b0007a976d", - "sha256:f6abce0e66bba2babfadc20530fd3688f672d565674336595b4623cd800b91ef" + "sha256:08a8c7d9922ca6eed24e2c13a3c552b3c186af8fc78e5d4820b58487d780ec19", + "sha256:08e9dca4ab6f8551794ce7ec146f86def6a82da41750cbed2c07551345fa10d3", + "sha256:0be639f5b2e1999a4b4a82a0f4633969f97336f052d0c131627983589af52f56", + "sha256:0f23409add2aaebbb6d8e881babab43c2d979f051b8bd8aed5fe779ea180a4e8", + "sha256:11ea148902e3e1688afa392087c728ac3a843e54a87d334d1464d2097d3debb7", + "sha256:1ba85f9e6a7f37ef998168aa3fd28d263d7f83016bd306a4508a2394e5e793b4", + "sha256:207575dec2dae722acf6ab39b4b361151c65f8f895fd37edf9d384f5541562e1", + "sha256:22c9473a2cc53faabcc95a0ac6ca4e52d127017bf34ba9bc0f8e472e44f7b38e", + "sha256:2b5c57a3c1976c365678eb0730bcb140d40510990cb77df9a91bb5c41d587ba6", + "sha256:2e264307ec49b2c72480422abafe80457f90b4e6e693b7ddf8a23d24b5c24001", + "sha256:2e8c1dfa854e700fcf6cd79b2796aa37d55697a74646daf5ea47c7c764bac31c", + "sha256:36d5ab95f39f855521585b0e819dc2d4d1b2a4080bad04c2f3de1e387a5d2233", + "sha256:3ece08ba778b6eeea74d9c705e9af2d1b4e915e9bc6de67ad173b962e575fcc0", + "sha256:41613fe08e647213546c7c59a5a1fc5484666e7d4cab6e80260c612acbb20e8c", + "sha256:43ccaa6c54daa1749cec53710c70d47150965574d4c6d4c4f2e3f87b9bf9f591", + "sha256:449f9ff8a5025dcd5c8d4ad28f6c291de5de89e4c044b0bda96b45bef8999b75", + "sha256:460fcf3562f078781e1504983cb11909eb27a1d46eaa99e65c4b0fafdc298298", + "sha256:4f14f5045766646ed9e8826b959c6d07194788babed1e0ba08c94ea4f39517e3", + "sha256:51bbafdd847529e8a16d1965814ed17831af61452ee31943c414cb23451de926", + "sha256:52a1067cf31d9e9e4be514b253bea6276f1531dd7de6ab0917df8ce5b468a820", + "sha256:59e8f611c977206eba294c296c2d29a1c1b1b88206cb97cd0d4847c1a3d923e7", + "sha256:5c513e64eff0f7bf2a908e2d987a98653eb33e1062ce2afd3a84af58159a24f9", + "sha256:5efd1bf6ee5840d1b0b82ec8e0b9c64f182fa5a7c8aad680fbd918c4fa3826e0", + "sha256:66e82cedba95a6176194a817be4232c720312f8be6d2c8f3847f3317d95a0c7f", + "sha256:6753e50904e05c27915933da41518ecd7a8ca4dd3602112ba44920c6e353a455", + "sha256:67d9720d91f507c87b3e5f070627ad640a00bc6cfdf5635f8c6ee9f2964cf71c", + "sha256:688a03bac4dfb9afc5078ec01d53c21556381282bdf1a804dd0dbafb5056de2a", + "sha256:706d07106af91c343150be86caeae1ea3851b74aa0730fcbbf8cd089e817f818", + "sha256:7fe762c4c390039b79b818cbc725d8663586b25351dc18a2704b0e357d69b924", + "sha256:8310521f2ccb79b5c4345750d475b88afa37bad930ab5554735f85ad5e3add30", + "sha256:8a81d816c2088d2055112af5ecd82fdfbe8ff277600e94255e2639b07de10234", + "sha256:94b7c032b72566077614a02baab1929739fd0af0cc1d46deaba4408b870faef2", + "sha256:96e2363e1f6e44bd7256bbbf3a53140743f821b5133046e6185491e0d9183447", + "sha256:9c2bd4ac288a9cdb7ffc3229a9ce8027a66a3fd3f2ab9e13da60f5fbfe91f3b2", + "sha256:a50618f4819a97ef897e055ac7aaf1cad5df84c206f33be35b0759d671574197", + "sha256:a553d452004e44b841788f6faa7231a02157527ddecc89dbbe5b689b74822226", + "sha256:a5d5519962ce7c72d81888fb0c09e58e308ba4c376e76bcd853b48151063d6a8", + "sha256:a70e40ce7600e1b32e293bb9157e9de3b69170e2318ccb219102f1abb826c94a", + "sha256:ae22376633cfa3db21c4eed2870d1c36b5419289975a41a45f34a085b2d9e6ea", + "sha256:b0110140738be1287e3724080a101e7cec6ae708008b7650c9d8a1c1788ec03a", + "sha256:b5269b96367e65793a7714608f6d906418eb056d59eaac9bba980486aabddbed", + "sha256:b62aa11d6b74ed5545e58ac613d3f63095e5fd0254b3e0d1168fda991b9a6b41", + "sha256:b68ea4a6018abfea1f68d50f74de7d399172684c264eb09809023e2c8696fc23", + "sha256:b88e9104c456590ad0ef0e82851d4fc03e9aa9d621fa8fdd4cd0907152a825ae", + "sha256:bba7c2b5063e8ada5a5477f9fa0c01710645426b5a8628ec50d558542a0a292e", + "sha256:be821d874ce8b26cbadd7277fa251a9b37f6d2326f8b5682b6fc8966b50a3a59", + "sha256:c1381ddbd1066d543e05d580c15beacf671e1469a0b2adb6dba58fec311f4eed", + "sha256:c34060ff2991707c710250463ae9f415ebb21653f2f5b013c61c9c376ff9b715", + "sha256:d11992561de0ad29ec2800230fbdcbef9efaa02805d5c633a73ab3cf2ba51bf1", + "sha256:d20e932ddd9a389da57b060c26e84a24118c96ff6fc5dcc7b784da24e823b694", + "sha256:d2194ae959630aae4176a4b75bd320b3274c20bef2a5ca6b8d6fc96d3c608edf", + "sha256:d97c9fe13aacfbefded6861f5200dcb8e837da7391a9bdeb44ccb133705990af", + "sha256:da2d8b008aff72acd5a4a588491abdda1b446f17508e700f26df9be80d8442ae", + "sha256:dd4310ea8ddc49cc8872e083737cf806299b17f93159a1f354d59aa08993e876", + "sha256:e5ba3ea570c8fb6fc44f71aa329edc7c668e2909311913123d0d7ab8c65fc357", + "sha256:e9bb599c175dc34a4511f0e26d5b5374fbcc91ea338871701a519e95d52f3c28", + "sha256:f5391d71bd7e9e6c73dcb3ee8d8c63b09efc14ce6e4dad31568d4838afc9aae0", + "sha256:f54f5c4176d60e7cd6b0880e18fb3fa8501ae046069151721cab457c7c538a3d", + "sha256:f69582e24667715e3860d80d663f1caeb2398110077e23cc0a1e0066a851f5ab", + "sha256:f74b0bc7378ad5afcf25ac9d0367b4dbba50f6f6468faa41f5dfddcf8bf9c0f8", + "sha256:fa3b807c2d2b34397c135d19ad6abb20c47a2ddb7bf65d90455f2040f7797e1e" ], "markers": "python_version >= '3.9'", - "version": "==1.4.0" + "version": "==1.8.2" }, "monkeytype": { "hashes": [ @@ -1470,148 +1521,193 @@ }, "mypy": { "hashes": [ - "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36", - "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce", - "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6", - "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b", - "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca", - "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24", - "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383", - "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7", - "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86", - "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d", - "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4", - "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8", - "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987", - "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385", - "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79", - "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef", - "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6", - "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70", - "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca", - "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70", - "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12", - "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104", - "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a", - "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318", - "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1", - "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b", - "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d" + "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", + "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", + "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849", + "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733", + "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81", + "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", + "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6", + "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", + "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91", + "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972", + "sha256:43808d9476c36b927fbcd0b0255ce75efe1b68a080154a38ae68a7e62de8f0f8", + "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd", + "sha256:5d1092694f166a7e56c805caaf794e0585cabdbf1df36911c414e4e9abb62ae9", + "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0", + "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", + "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", + "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", + "sha256:79d44f9bfb004941ebb0abe8eff6504223a9c1ac51ef967d1263c6572bbebc99", + "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7", + "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", + "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7", + "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a", + "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed", + "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94", + "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", + "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", + "sha256:b01586eed696ec905e61bd2568f48740f7ac4a45b3a468e6423a03d3788a51a8", + "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", + "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a", + "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df", + "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", + "sha256:d7598cf74c3e16539d4e2f0b8d8c318e00041553d83d4861f87c7a72e95ac24d", + "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390", + "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b", + "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", + "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14", + "sha256:feb8cc32d319edd5859da2cc084493b3e2ce5e49a946377663cc90f6c15fb259", + "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.11.2" + "markers": "python_version >= '3.9'", + "version": "==1.17.1" }, "mypy-extensions": { "hashes": [ - "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", + "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" + "markers": "python_version >= '3.8'", + "version": "==1.1.0" }, "numpy": { "hashes": [ - "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5", - "sha256:0b8cc2715a84b7c3b161f9ebbd942740aaed913584cae9cdc7f8ad5ad41943d0", - "sha256:0d07841fd284718feffe7dd17a63a2e6c78679b2d386d3e82f44f0108c905550", - "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c", - "sha256:13ce49a34c44b6de5241f0b38b07e44c1b2dcacd9e36c30f9c2fcb1bb5135db7", - "sha256:24c2ad697bd8593887b019817ddd9974a7f429c14a5469d7fad413f28340a6d2", - "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b", - "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df", - "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f", - "sha256:397bc5ce62d3fb73f304bec332171535c187e0643e176a6e9421a6e3eacef06d", - "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270", - "sha256:50a95ca3560a6058d6ea91d4629a83a897ee27c00630aed9d933dff191f170cd", - "sha256:52ac2e48f5ad847cd43c4755520a2317f3380213493b9d8a4c5e37f3b87df504", - "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec", - "sha256:57eb525e7c2a8fdee02d731f647146ff54ea8c973364f3b850069ffb42799647", - "sha256:5889dd24f03ca5a5b1e8a90a33b5a0846d8977565e4ae003a63d22ecddf6782f", - "sha256:59ca673ad11d4b84ceb385290ed0ebe60266e356641428c845b39cd9df6713ab", - "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe", - "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5", - "sha256:7be6a07520b88214ea85d8ac8b7d6d8a1839b0b5cb87412ac9f49fa934eb15d5", - "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e", - "sha256:7dd86dfaf7c900c0bbdcb8b16e2f6ddf1eb1fe39c6c8cca6e94844ed3152a8fd", - "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313", - "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0", - "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f", - "sha256:913cc1d311060b1d409e609947fa1b9753701dac96e6581b58afc36b7ee35af6", - "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553", - "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed", - "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb", - "sha256:98ce7fb5b8063cfdd86596b9c762bf2b5e35a2cdd7e967494ab78a1fa7f8b86e", - "sha256:99f4a9ee60eed1385a86e82288971a51e71df052ed0b2900ed30bc840c0f2e39", - "sha256:9a8e06c7a980869ea67bbf551283bbed2856915f0a792dc32dd0f9dd2fb56728", - "sha256:ae8ce252404cdd4de56dcfce8b11eac3c594a9c16c231d081fb705cf23bd4d9e", - "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a", - "sha256:b49742cdb85f1f81e4dc1b39dcf328244f4d8d1ded95dea725b316bd2cf18c95", - "sha256:b5613cfeb1adfe791e8e681128f5f49f22f3fcaa942255a6124d58ca59d9528f", - "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480", - "sha256:c8a0e34993b510fc19b9a2ce7f31cb8e94ecf6e924a40c0c9dd4f62d0aac47d9", - "sha256:caf5d284ddea7462c32b8d4a6b8af030b6c9fd5332afb70e7414d7fdded4bfd0", - "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f", - "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd", - "sha256:d10c39947a2d351d6d466b4ae83dad4c37cd6c3cdd6d5d0fa797da56f710a6ae", - "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201", - "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136", - "sha256:d51fc141ddbe3f919e91a096ec739f49d686df8af254b2053ba21a910ae518bf", - "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78", - "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468", - "sha256:e8d5f8a8e3bc87334f025194c6193e408903d21ebaeb10952264943a985066ca", - "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef", - "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0", - "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556", - "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521", - "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b" - ], - "markers": "python_version >= '3.12'", - "version": "==2.1.1" + "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5", + "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b", + "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", + "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58", + "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b", + "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc", + "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089", + "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf", + "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15", + "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f", + "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3", + "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170", + "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910", + "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91", + "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45", + "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c", + "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f", + "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b", + "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89", + "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a", + "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220", + "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e", + "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab", + "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2", + "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b", + "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370", + "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2", + "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee", + "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619", + "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712", + "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1", + "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec", + "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a", + "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450", + "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a", + "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2", + "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168", + "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2", + "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73", + "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296", + "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9", + "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125", + "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0", + "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19", + "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b", + "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f", + "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2", + "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f", + "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a", + "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6", + "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286", + "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981", + "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f", + "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2", + "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0", + "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b", + "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b", + "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56", + "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5", + "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3", + "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8", + "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0", + "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036", + "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6", + "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8", + "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", + "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", + "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b", + "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b", + "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d", + "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0", + "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097", + "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be", + "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5" + ], + "markers": "python_version >= '3.11'", + "version": "==2.3.2" }, "packaging": { "hashes": [ - "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", - "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" + "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", + "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" ], "markers": "python_version >= '3.8'", - "version": "==24.1" + "version": "==25.0" }, "pandas": { "hashes": [ - "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863", - "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2", - "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1", - "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad", - "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db", - "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76", - "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51", - "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32", - "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08", - "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b", - "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4", - "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921", - "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288", - "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee", - "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0", - "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24", - "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99", - "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151", - "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd", - "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce", - "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57", - "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef", - "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54", - "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a", - "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238", - "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23", - "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772", - "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce", - "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad" + "sha256:025e92411c16cbe5bb2a4abc99732a6b132f439b8aab23a59fa593eb00704232", + "sha256:09e3b1587f0f3b0913e21e8b32c3119174551deb4a4eba4a89bc7377947977e7", + "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2", + "sha256:0f951fbb702dacd390561e0ea45cdd8ecfa7fb56935eb3dd78e306c19104b9b0", + "sha256:1b916a627919a247d865aed068eb65eb91a344b13f5b57ab9f610b7716c92de1", + "sha256:1c78cf43c8fde236342a1cb2c34bcff89564a7bfed7e474ed2fffa6aed03a956", + "sha256:1d12f618d80379fde6af007f65f0c25bd3e40251dbd1636480dfffce2cf1e6da", + "sha256:22c2e866f7209ebc3a8f08d75766566aae02bcc91d196935a1d9e59c7b990ac9", + "sha256:2323294c73ed50f612f67e2bf3ae45aea04dce5690778e08a09391897f35ff88", + "sha256:2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b", + "sha256:2ba6aff74075311fc88504b1db890187a3cd0f887a5b10f5525f8e2ef55bfdb9", + "sha256:2eb789ae0274672acbd3c575b0598d213345660120a257b47b5dafdc618aec83", + "sha256:2f4d6feeba91744872a600e6edbbd5b033005b431d5ae8379abee5bcfa479fab", + "sha256:342e59589cc454aaff7484d75b816a433350b3d7964d7847327edda4d532a2e3", + "sha256:3462c3735fe19f2638f2c3a40bd94ec2dc5ba13abbb032dd2fa1f540a075509d", + "sha256:3583d348546201aff730c8c47e49bc159833f971c2899d6097bce68b9112a4f1", + "sha256:4645f770f98d656f11c69e81aeb21c6fca076a44bed3dcbb9396a4311bc7f6d8", + "sha256:4d544806b485ddf29e52d75b1f559142514e60ef58a832f74fb38e48d757b299", + "sha256:56a342b231e8862c96bdb6ab97170e203ce511f4d0429589c8ede1ee8ece48b8", + "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444", + "sha256:689968e841136f9e542020698ee1c4fbe9caa2ed2213ae2388dc7b81721510d3", + "sha256:6de8547d4fdb12421e2d047a2c446c623ff4c11f47fddb6b9169eb98ffba485a", + "sha256:6f3bf5ec947526106399a9e1d26d40ee2b259c66422efdf4de63c848492d91bb", + "sha256:782647ddc63c83133b2506912cc6b108140a38a37292102aaa19c81c83db2928", + "sha256:7dcb79bf373a47d2a40cf7232928eb7540155abbc460925c2c96d2d30b006eb4", + "sha256:8dfc17328e8da77be3cf9f47509e5637ba8f137148ed0e9b5241e1baf526e20a", + "sha256:9026bd4a80108fac2239294a15ef9003c4ee191a0f64b90f170b40cfb7cf2d22", + "sha256:911580460fc4884d9b05254b38a6bfadddfcc6aaef856fb5859e7ca202e45275", + "sha256:98bcc8b5bf7afed22cc753a28bc4d9e26e078e777066bc53fac7904ddef9a678", + "sha256:9b7ff55f31c4fcb3e316e8f7fa194566b286d6ac430afec0d461163312c5841e", + "sha256:ac942bfd0aca577bef61f2bc8da8147c4ef6879965ef883d8e8d5d2dc3e744b8", + "sha256:b3cd4273d3cb3707b6fffd217204c52ed92859533e31dc03b7c5008aa933aaab", + "sha256:b4b0de34dc8499c2db34000ef8baad684cfa4cbd836ecee05f323ebfba348c7d", + "sha256:ca7ed14832bce68baef331f4d7f294411bed8efd032f8109d690df45e00c4679", + "sha256:cd05b72ec02ebfb993569b4931b2e16fbb4d6ad6ce80224a3ee838387d83a191", + "sha256:dd71c47a911da120d72ef173aeac0bf5241423f9bfea57320110a978457e069e", + "sha256:e5635178b387bd2ba4ac040f82bc2ef6e6b500483975c4ebacd34bec945fda12", + "sha256:e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85", + "sha256:ec6c851509364c59a5344458ab935e6451b31b818be467eb24b0fe89bd05b6b9", + "sha256:fe37e757f462d31a9cd7580236a82f353f5713a80e059a29753cf938c6775d96", + "sha256:fe67dc676818c186d5a3d5425250e40f179c2a89145df477dd82945eaea89e97", + "sha256:fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==2.2.2" + "version": "==2.3.1" }, "pathspec": { "hashes": [ @@ -1623,19 +1719,19 @@ }, "platformdirs": { "hashes": [ - "sha256:50a5450e2e84f44539718293cbb1da0a0885c9d14adf21b77bae4e66fc99d9b5", - "sha256:d4e0b7d8ec176b341fb03cb11ca12d0276faa8c485f9cd218f613840463fc2c0" + "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", + "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4" ], - "markers": "python_version >= '3.8'", - "version": "==4.3.3" + "markers": "python_version >= '3.9'", + "version": "==4.3.8" }, "pluggy": { "hashes": [ - "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", - "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" ], - "markers": "python_version >= '3.8'", - "version": "==1.5.0" + "markers": "python_version >= '3.9'", + "version": "==1.6.0" }, "py-cpuinfo": { "hashes": [ @@ -1644,50 +1740,58 @@ ], "version": "==9.0.0" }, + "pygments": { + "hashes": [ + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" + ], + "markers": "python_version >= '3.8'", + "version": "==2.19.2" + }, "pytest": { "hashes": [ - "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", - "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2" + "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", + "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==8.3.3" + "markers": "python_version >= '3.9'", + "version": "==8.4.1" }, "pytest-asyncio": { "hashes": [ - "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b", - "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276" + "sha256:5fe2d69607b0bd75c656d1211f969cadba035030156745ee09e7d71740e58ecf", + "sha256:796aa822981e01b68c12e4827b8697108f7205020f24b5793b3c41555dab68ea" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==0.24.0" + "markers": "python_version >= '3.9'", + "version": "==1.1.0" }, "pytest-benchmark": { "hashes": [ - "sha256:fb0785b83efe599a6a956361c0691ae1dbb5318018561af10f3e915caa0048d1", - "sha256:fdb7db64e31c8b277dff9850d2a2556d8b60bcb0ea6524e36e28ffd7c87f71d6" + "sha256:922de2dfa3033c227c96da942d1878191afa135a29485fb942e85dff1c592c89", + "sha256:9ea661cdc292e8231f7cd4c10b0319e56a2118e2c09d9f50e1b3d150d2aca105" ], "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==4.0.0" + "markers": "python_version >= '3.9'", + "version": "==5.1.0" }, "pytest-cov": { "hashes": [ - "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652", - "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857" + "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", + "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==5.0.0" + "markers": "python_version >= '3.9'", + "version": "==6.2.1" }, "pytest-datadir": { "hashes": [ - "sha256:1617ed92f9afda0c877e4eac91904b5f779d24ba8f5e438752e3ae39d8d2ee3f", - "sha256:34adf361bcc7b37961bbc1dfa8d25a4829e778bab461703c38a5c50ca9c36dc8" + "sha256:5c677bc097d907ac71ca418109adc3abe34cf0bddfe6cf78aecfbabd96a15cf0", + "sha256:7a15faed76cebe87cc91941dd1920a9a38eba56a09c11e9ddf1434d28a0f78eb" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.5.0" + "version": "==1.8.0" }, "pytest-monkeytype": { "hashes": [ @@ -1702,7 +1806,7 @@ "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.9.0.post0" }, "python-rapidjson": { @@ -1797,10 +1901,10 @@ }, "pytz": { "hashes": [ - "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", - "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725" + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" ], - "version": "==2024.2" + "version": "==2025.2" }, "pyyaml": { "hashes": [ @@ -1863,11 +1967,11 @@ }, "requests": { "hashes": [ - "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", - "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", + "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422" ], "markers": "python_version >= '3.8'", - "version": "==2.32.3" + "version": "==2.32.4" }, "requests-mock": { "hashes": [ @@ -1880,45 +1984,45 @@ }, "rope": { "hashes": [ - "sha256:51437d2decc8806cd5e9dd1fd9c1306a6d9075ecaf78d191af85fc1dfface880", - "sha256:b435a0c0971244fdcd8741676a9fae697ae614c20cc36003678a7782f25c0d6c" + "sha256:00a7ea8c0c376fc0b053b2f2f8ef3bfb8b50fecf1ebf3eb80e4f8bd7f1941918", + "sha256:8803e3b667315044f6270b0c69a10c0679f9f322ed8efe6245a93ceb7658da69" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.13.0" + "version": "==1.14.0" }, "ruff": { "hashes": [ - "sha256:005256d977021790cc52aa23d78f06bb5090dc0bfbd42de46d49c201533982ae", - "sha256:09c72a833fd3551135ceddcba5ebdb68ff89225d30758027280968c9acdc7810", - "sha256:381413ec47f71ce1d1c614f7779d88886f406f1fd53d289c77e4e533dc6ea200", - "sha256:3a8d42d11fff8d3143ff4da41742a98f8f233bf8890e9fe23077826818f8d680", - "sha256:3e42a57b58e3612051a636bc1ac4e6b838679530235520e8f095f7c44f706ff9", - "sha256:482c1e6bfeb615eafc5899127b805d28e387bd87db38b2c0c41d271f5e58d8cc", - "sha256:4d32d87fab433c0cf285c3683dd4dae63be05fd7a1d65b3f5bf7cdd05a6b96fb", - "sha256:51935067740773afdf97493ba9b8231279e9beef0f2a8079188c4776c25688e0", - "sha256:52e75a82bbc9b42e63c08d22ad0ac525117e72aee9729a069d7c4f235fc4d276", - "sha256:7291e64d7129f24d1b0c947ec3ec4c0076e958d1475c61202497c6aced35dd19", - "sha256:794ada3400a0d0b89e3015f1a7e01f4c97320ac665b7bc3ade24b50b54cb2972", - "sha256:7e4e308f16e07c95fc7753fc1aaac690a323b2bb9f4ec5e844a97bb7fbebd748", - "sha256:800c50371bdcb99b3c1551d5691e14d16d6f07063a518770254227f7f6e8c178", - "sha256:8e25ddd9cd63ba1f3bd51c1f09903904a6adf8429df34f17d728a8fa11174253", - "sha256:932cd69eefe4daf8c7d92bd6689f7e8182571cb934ea720af218929da7bd7d69", - "sha256:9ad7dfbd138d09d9a7e6931e6a7e797651ce29becd688be8a0d4d5f8177b4b0c", - "sha256:a50af6e828ee692fb10ff2dfe53f05caecf077f4210fae9677e06a808275754f", - "sha256:cf4d3fa53644137f6a4a27a2b397381d16454a1566ae5335855c187fbf67e4f5" + "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", + "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71", + "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3", + "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860", + "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa", + "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c", + "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb", + "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e", + "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5", + "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd", + "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303", + "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb", + "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f", + "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4", + "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423", + "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77", + "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69", + "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.6.5" + "version": "==0.12.7" }, "six": { "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", + "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.17.0" }, "types-python-dateutil": { "hashes": [ @@ -1930,54 +2034,54 @@ }, "types-pytz": { "hashes": [ - "sha256:4433b5df4a6fc587bbed41716d86a5ba5d832b4378e506f40d34bc9c81df2c24", - "sha256:a1eebf57ebc6e127a99d2fa2ba0a88d2b173784ef9b3defcc2004ab6855a44df" + "sha256:e0e0c8a57e2791c19f718ed99ab2ba623856b11620cb6b637e5f62ce285a7451", + "sha256:e1216306f8c0d5da6dafd6492e72eb080c9a166171fa80dd7a1990fd8be7a7b3" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2024.2.0.20240913" + "markers": "python_version >= '3.9'", + "version": "==2025.2.0.20250516" }, "types-requests": { "hashes": [ - "sha256:2850e178db3919d9bf809e434eef65ba49d0e7e33ac92d588f4a5e295fffd405", - "sha256:59c2f673eb55f32a99b2894faf6020e1a9f4a402ad0f192bfee0b64469054310" + "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", + "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.32.0.20240914" + "markers": "python_version >= '3.9'", + "version": "==2.32.4.20250611" }, "types-setuptools": { "hashes": [ - "sha256:0abdb082552ca966c1e5fc244e4853adc62971f6cd724fb1d8a3713b580e5a65", - "sha256:15b38c8e63ca34f42f6063ff4b1dd662ea20086166d5ad6a102e670a52574120" + "sha256:e1e92682fa07226415396bb4e2d31f116a16ffbe583b05b01f9910fcdea3b7e8", + "sha256:ec908f825134af3964932e6b011dce90f54c291015139cd9cdf79741b7d31b3c" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==74.1.0.20240907" + "markers": "python_version >= '3.9'", + "version": "==80.9.0.20250801" }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", + "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76" ], - "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "markers": "python_version >= '3.9'", + "version": "==4.14.1" }, "tzdata": { "hashes": [ - "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd", - "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252" + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" ], "markers": "python_version >= '2'", - "version": "==2024.1" + "version": "==2025.2" }, "urllib3": { "hashes": [ - "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", - "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9" + "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", + "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" ], - "markers": "python_version >= '3.8'", - "version": "==2.2.3" + "markers": "python_version >= '3.9'", + "version": "==2.5.0" }, "yarl": { "hashes": [ diff --git a/pyproject.toml b/pyproject.toml index 21d1591..4c11294 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,5 @@ [tool.black] line-length = 120 -target_version = ['py37'] include = '\.pyi?$' exclude = ''' ( From 13d8d640ce5cdb02bae4d436c8268f03790e439a Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 00:45:35 -0400 Subject: [PATCH 04/13] Formats with ruff instead of black --- Pipfile | 1 - Pipfile.lock | 31 +------------------------------ pyproject.toml | 30 +++++++++--------------------- 3 files changed, 10 insertions(+), 52 deletions(-) diff --git a/Pipfile b/Pipfile index 09b257b..39f2704 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,6 @@ rope = "*" mygeotab = {editable = true,path = "."} mypy = "*" pytest-asyncio = "*" -black = "*" requests-mock = "*" pytest-datadir = "*" pytest-benchmark = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 8a63da2..a496a8a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "73f1154538ae649b1845f2255ffb7f12078492832bb95df514b42f250a58a9b3" + "sha256": "5c80a0bebdcc1adfd0d6ad22498803cef6f7800fac9f3bc0559d7f8f91c06909" }, "pipfile-spec": 6, "requires": {}, @@ -1002,35 +1002,6 @@ "markers": "python_version >= '3.7'", "version": "==24.2.0" }, - "black": { - "hashes": [ - "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", - "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", - "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", - "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", - "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", - "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", - "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", - "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", - "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", - "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", - "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", - "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", - "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0", - "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", - "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", - "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", - "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355", - "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", - "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e", - "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", - "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", - "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==25.1.0" - }, "certifi": { "hashes": [ "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", diff --git a/pyproject.toml b/pyproject.toml index 4c11294..6c008e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,23 +1,3 @@ -[tool.black] -line-length = 120 -include = '\.pyi?$' -exclude = ''' -( - /( - \.eggs # exclude a few common directories in the - | \.git # root of the project - | \.mypy_cache - | \.venv - | _build - | build - | dist - | docs - )/ - | foo.py # also separately exclude a file named foo.py in - # the root of the project -) -''' - [tool.ruff] line-length = 127 @@ -26,4 +6,12 @@ select = ["E", "F", "B"] exclude = [ "docs" ] -mccabe.max-complexity = 10 \ No newline at end of file +mccabe.max-complexity = 10 + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto" +docstring-code-format = false +docstring-code-line-length = "dynamic" \ No newline at end of file From 1e04031b8a3d8aa361943abe902d0fbad208ab15 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 00:47:01 -0400 Subject: [PATCH 05/13] Formatted with ruff format --- docs/conf.py | 156 +++++++++--------- ...isualizing MyGeotab Data with Python.ipynb | 17 +- mygeotab/altitude/daas_definition.py | 1 - tests/test_api_async.py | 4 +- tests/test_api_call.py | 4 +- 5 files changed, 86 insertions(+), 96 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index cfd071b..4578d02 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,39 +20,39 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath('..')) +sys.path.append(os.path.abspath("..")) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.coverage', - 'sphinx.ext.viewcode', - 'sphinx_copybutton', + "sphinx.ext.autodoc", + "sphinx.ext.doctest", + "sphinx.ext.coverage", + "sphinx.ext.viewcode", + "sphinx_copybutton", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'MyGeotab Python SDK' -copyright = u'{}, {}'.format(datetime.datetime.utcnow().year, mygeotab.__author__) +project = "MyGeotab Python SDK" +copyright = "{}, {}".format(datetime.datetime.utcnow().year, mygeotab.__author__) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -65,51 +65,49 @@ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # -- Options for HTML output ---------------------------------------------- -html_theme = 'furo' +html_theme = "furo" html_theme_options = { - "light_css_variables": { - "font-stack": "Roboto, Helvetica Neue, Helvetica, Arial, sans-serif" - }, + "light_css_variables": {"font-stack": "Roboto, Helvetica Neue, Helvetica, Arial, sans-serif"}, } # otherwise, readthedocs.org uses their theme by default, so no need to specify it @@ -119,125 +117,119 @@ html_title = project # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'MyGeotabPythonSDKdoc' +htmlhelp_basename = "MyGeotabPythonSDKdoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'MyGeotabPythonSDK.tex', u'MyGeotab Python SDK Documentation', - mygeotab.__author__, 'manual'), + ("index", "MyGeotabPythonSDK.tex", "MyGeotab Python SDK Documentation", mygeotab.__author__, "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'mygeotabpythonsdk', u'MyGeotab Python SDK Documentation', - [mygeotab.__author__], 1) -] +man_pages = [("index", "mygeotabpythonsdk", "MyGeotab Python SDK Documentation", [mygeotab.__author__], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -246,27 +238,33 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'MyGeotabPythonSDK', u'MyGeotab Python SDK Documentation', - mygeotab.__author__, 'MyGeotabPythonSDK', 'One line description of project.', - 'Miscellaneous'), + ( + "index", + "MyGeotabPythonSDK", + "MyGeotab Python SDK Documentation", + mygeotab.__author__, + "MyGeotabPythonSDK", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False autodoc_default_options = { - 'members': True, - 'member-order': 'bysource', - 'special-members': '__init__', - 'undoc-members': True, - 'exclude-members': '__weakref__' + "members": True, + "member-order": "bysource", + "special-members": "__init__", + "undoc-members": True, + "exclude-members": "__weakref__", } diff --git a/examples/notebooks/Visualizing MyGeotab Data with Python.ipynb b/examples/notebooks/Visualizing MyGeotab Data with Python.ipynb index 9caca16..1e98fbc 100644 --- a/examples/notebooks/Visualizing MyGeotab Data with Python.ipynb +++ b/examples/notebooks/Visualizing MyGeotab Data with Python.ipynb @@ -41,9 +41,9 @@ "metadata": {}, "outputs": [], "source": [ - "username = input('Username: ')\n", - "database = input('Database: ')\n", - "client = mygeotab.API(username=username, password=getpass.getpass('Password: '), database=database)" + "username = input(\"Username: \")\n", + "database = input(\"Database: \")\n", + "client = mygeotab.API(username=username, password=getpass.getpass(\"Password: \"), database=database)" ] }, { @@ -63,7 +63,7 @@ }, "outputs": [], "source": [ - "device_statuses = client.get('DeviceStatusInfo')" + "device_statuses = client.get(\"DeviceStatusInfo\")" ] }, { @@ -108,12 +108,9 @@ "outputs": [], "source": [ "for status in device_statuses:\n", - " if status.get('latitude'):\n", - " device = status['device']\n", - " folium.Marker(\n", - " location=[status.get('latitude'), status.get('longitude')],\n", - " popup=device['id']\n", - " ).add_to(marker_cluster)\n" + " if status.get(\"latitude\"):\n", + " device = status[\"device\"]\n", + " folium.Marker(location=[status.get(\"latitude\"), status.get(\"longitude\")], popup=device[\"id\"]).add_to(marker_cluster)" ] }, { diff --git a/mygeotab/altitude/daas_definition.py b/mygeotab/altitude/daas_definition.py index 994fa40..9c9536f 100644 --- a/mygeotab/altitude/daas_definition.py +++ b/mygeotab/altitude/daas_definition.py @@ -25,7 +25,6 @@ class DaasResult: """ def __init__(self, call_result: dict): - if not call_result: self.errors = [Exception("result is empty"), NOT_FULL_API_CALL_EXCEPTION] raise NOT_FULL_API_CALL_EXCEPTION diff --git a/tests/test_api_async.py b/tests/test_api_async.py index 76386f5..ed224a9 100644 --- a/tests/test_api_async.py +++ b/tests/test_api_async.py @@ -44,9 +44,7 @@ def async_populated_api(): yield session else: pytest.skip( - "Can't make calls to the API without the " - "MYGEOTAB_USERNAME and MYGEOTAB_PASSWORD " - "environment variables being set" + "Can't make calls to the API without the MYGEOTAB_USERNAME and MYGEOTAB_PASSWORD environment variables being set" ) diff --git a/tests/test_api_call.py b/tests/test_api_call.py index c4cda59..e954f48 100644 --- a/tests/test_api_call.py +++ b/tests/test_api_call.py @@ -54,9 +54,7 @@ def populated_api(): yield session else: pytest.skip( - "Can't make calls to the API without the " - "MYGEOTAB_USERNAME and MYGEOTAB_PASSWORD " - "environment variables being set" + "Can't make calls to the API without the MYGEOTAB_USERNAME and MYGEOTAB_PASSWORD environment variables being set" ) From 7025a745a51a2c597a632c1e395af26482a6c1c0 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 00:48:46 -0400 Subject: [PATCH 06/13] Formatted parameters.py with ruff format --- mygeotab/parameters.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mygeotab/parameters.py b/mygeotab/parameters.py index 2b19a8a..a67f456 100644 --- a/mygeotab/parameters.py +++ b/mygeotab/parameters.py @@ -59,7 +59,7 @@ def convert_get_parameters(parameters: dict[str, Any]) -> dict[str, Any]: if "search" in parameters: parameters.update(parameters["search"]) del parameters["search"] - result = {'search': parameters} + result = {"search": parameters} if results_limit is not None: - result['resultsLimit'] = results_limit + result["resultsLimit"] = results_limit return result From a1962d09363c8ece32d3dd17dda9c10a13208459 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 11:14:56 -0400 Subject: [PATCH 07/13] Adds tests for parameters utilities --- tests/test_parameters.py | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/test_parameters.py diff --git a/tests/test_parameters.py b/tests/test_parameters.py new file mode 100644 index 0000000..7648ebb --- /dev/null +++ b/tests/test_parameters.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +import pytest +from mygeotab.parameters import camelcaseify_parameters, convert_get_parameters + + +def test_camelcaseify_parameters_basic(): + params = {"some_param": 1, "another_param": 2} + result = camelcaseify_parameters(params) + assert "someParam" in result + assert "anotherParam" in result + assert result["someParam"] == 1 + assert result["anotherParam"] == 2 + + +def test_camelcaseify_parameters_nested(): + params = {"outer_param": {"inner_param": 3}} + result = camelcaseify_parameters(params) + assert "outerParam" in result + assert isinstance(result["outerParam"], dict) + assert "innerParam" in result["outerParam"] + assert result["outerParam"]["innerParam"] == 3 + + +def test_camelcaseify_parameters_empty(): + assert camelcaseify_parameters({}) == {} + + +def test_camelcaseify_parameters_no_underscore(): + params = {"param": 5} + result = camelcaseify_parameters(params) + assert "param" in result + assert result["param"] == 5 + + +def test_convert_get_parameters_with_search_and_results_limit(): + params = {"search": {"foo": "bar"}, "results_limit": 10} + result = convert_get_parameters(params) + assert "search" in result + assert result["search"]["foo"] == "bar" + assert "resultsLimit" in result + assert result["resultsLimit"] == 10 + + +def test_convert_get_parameters_with_search_and_resultsLimit(): + params = {"search": {"foo": "bar"}, "resultsLimit": 5} + result = convert_get_parameters(params) + assert "search" in result + assert result["search"]["foo"] == "bar" + assert "resultsLimit" in result + assert result["resultsLimit"] == 5 + + +def test_convert_get_parameters_flatten_search(): + params = {"search": {"foo": "bar", "baz": 2}} + result = convert_get_parameters(params) + assert "search" in result + assert result["search"]["foo"] == "bar" + assert result["search"]["baz"] == 2 + + +def test_convert_get_parameters_no_search(): + params = {"foo": "bar", "resultsLimit": 3} + result = convert_get_parameters(params) + assert "search" in result + assert result["search"]["foo"] == "bar" + assert "resultsLimit" in result + assert result["resultsLimit"] == 3 + + +def test_convert_get_parameters_empty(): + assert convert_get_parameters({}) == {} + + +def test_convert_get_parameters_removes_results_limit_from_search(): + params = {"search": {"foo": "bar"}, "results_limit": 7} + result = convert_get_parameters(params) + assert "resultsLimit" in result + assert result["resultsLimit"] == 7 + assert "results_limit" not in result["search"] From 7709fbce725e853f07679c4370e4d1d804deebc0 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 11:44:29 -0400 Subject: [PATCH 08/13] Adds handling for sort and propertySelector (beta) parameters Cleans up some handling code for snake_case variant parameters Adds tests for the above --- mygeotab/parameters.py | 39 ++++++++++++++++++++++---------- tests/test_parameters.py | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/mygeotab/parameters.py b/mygeotab/parameters.py index a67f456..ba36446 100644 --- a/mygeotab/parameters.py +++ b/mygeotab/parameters.py @@ -9,7 +9,7 @@ import re from copy import copy -from typing import Any +from typing import Any, Optional def camelcaseify_parameters(parameters: dict[str, Any]) -> dict[str, Any]: @@ -37,8 +37,8 @@ def camelcaseify_parameters(parameters: dict[str, Any]) -> dict[str, Any]: def convert_get_parameters(parameters: dict[str, Any]) -> dict[str, Any]: """Converts parameters passed into a get() call to a format suitable for the MyGeotab API. It detects if a 'search' dictionary is passed and flattens it into the top-level parameters. - It also detects 'resultsLimit' or 'results_limit' and removes it from the parameters - so it doesn't become part of the search. + It also detects 'resultsLimit'/'results_limit' or 'sort' parameters and removes them from the parameters + so they doesn't become part of the search. :param parameters: The parameters object. :type parameters: dict @@ -48,18 +48,33 @@ def convert_get_parameters(parameters: dict[str, Any]) -> dict[str, Any]: if not parameters: return dict() - results_limit = parameters.get("resultsLimit") - if results_limit is not None: - del parameters["resultsLimit"] - else: - results_limit = parameters.get("results_limit") - if results_limit is not None: - del parameters["results_limit"] + parameters = copy(parameters) + + results_limit_param = _try_extract_get_parameter(parameters, "resultsLimit", "results_limit") + property_selector_param = _try_extract_get_parameter(parameters, "propertySelector", "property_selector") + sort_param = _try_extract_get_parameter(parameters, "sort") if "search" in parameters: parameters.update(parameters["search"]) del parameters["search"] + result = {"search": parameters} - if results_limit is not None: - result["resultsLimit"] = results_limit + if results_limit_param is not None: + result["resultsLimit"] = results_limit_param + if property_selector_param is not None: + result["propertySelector"] = property_selector_param + if sort_param is not None: + result["sort"] = sort_param return result + + +def _try_extract_get_parameter(parameters: dict[str, Any], name: str, pythonic_name: Optional[str] = None) -> Any | None: + """Helper to get a parameter from a dictionary, returning None if it doesn't exist.""" + parameter = parameters.get(name) + if parameter is not None: + del parameters[name] + elif pythonic_name is not None: + parameter = parameters.get(pythonic_name) + if parameter is not None: + del parameters[pythonic_name] + return parameter diff --git a/tests/test_parameters.py b/tests/test_parameters.py index 7648ebb..d314245 100644 --- a/tests/test_parameters.py +++ b/tests/test_parameters.py @@ -78,3 +78,52 @@ def test_convert_get_parameters_removes_results_limit_from_search(): assert "resultsLimit" in result assert result["resultsLimit"] == 7 assert "results_limit" not in result["search"] + + +def test_convert_get_parameters_with_sort(): + params = { + "search": {"foo": "bar"}, + "sort": {"sortBy": "name", "sortDirection": "asc", "offset": "Delivery Truck 12", "lastId": "b1234"}, + } + result = convert_get_parameters(params) + assert "sort" in result + assert isinstance(result["sort"], dict) + assert result["sort"]["sortBy"] == "name" + assert result["sort"]["sortDirection"] == "asc" + assert result["sort"]["offset"] == "Delivery Truck 12" + assert result["sort"]["lastId"] == "b1234" + + +def test_convert_get_parameters_with_property_selector(): + params = {"search": {"foo": "bar"}, "propertySelector": {"fields": ["id", "name"], "isIncluded": True}} + result = convert_get_parameters(params) + assert "propertySelector" in result + assert isinstance(result["propertySelector"], dict) + assert "fields" in result["propertySelector"] + assert "isIncluded" in result["propertySelector"] + + +def test_convert_get_parameters_with_property_selector_snake_case(): + params = {"search": {"foo": "bar"}, "property_selector": {"fields": ["id", "name"], "isIncluded": True}} + result = convert_get_parameters(params) + assert "propertySelector" in result + assert isinstance(result["propertySelector"], dict) + assert "fields" in result["propertySelector"] + assert "isIncluded" in result["propertySelector"] + + +def test_convert_get_parameters_with_sort_and_property_selector(): + params = { + "search": {"foo": "bar"}, + "sort": {"sortBy": "name", "sortDirection": "asc", "offset": "Delivery Truck 12", "lastId": "b1234"}, + "property_selector": {"fields": ["id", "status"], "isIncluded": True}, + } + result = convert_get_parameters(params) + assert "sort" in result + assert result["sort"]["sortBy"] == "name" + assert result["sort"]["sortDirection"] == "asc" + assert result["sort"]["offset"] == "Delivery Truck 12" + assert result["sort"]["lastId"] == "b1234" + assert "propertySelector" in result + assert "fields" in result["propertySelector"] + assert "isIncluded" in result["propertySelector"] From 4ba783dd1aa07cddb480a13d42bb26f564651595 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 11:56:49 -0400 Subject: [PATCH 09/13] Removes un-needed rope from dev dependencies --- Pipfile | 1 - Pipfile.lock | 30 +----------------------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/Pipfile b/Pipfile index 39f2704..9e2a8f1 100644 --- a/Pipfile +++ b/Pipfile @@ -7,7 +7,6 @@ verify_ssl = true coverage = "*" pytest = "*" pytest-cov = "*" -rope = "*" mygeotab = {editable = true,path = "."} mypy = "*" pytest-asyncio = "*" diff --git a/Pipfile.lock b/Pipfile.lock index a496a8a..4e24e4f 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "5c80a0bebdcc1adfd0d6ad22498803cef6f7800fac9f3bc0559d7f8f91c06909" + "sha256": "451af10baefbb37c4fc9d816fe1280c0a2e51a7f71ebe90e8351495792154135" }, "pipfile-spec": 6, "requires": {}, @@ -1688,14 +1688,6 @@ "markers": "python_version >= '3.8'", "version": "==0.12.1" }, - "platformdirs": { - "hashes": [ - "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", - "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4" - ], - "markers": "python_version >= '3.9'", - "version": "==4.3.8" - }, "pluggy": { "hashes": [ "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", @@ -1859,17 +1851,6 @@ "markers": "python_version >= '3.6'", "version": "==1.20" }, - "pytoolconfig": { - "extras": [ - "global" - ], - "hashes": [ - "sha256:51e6bd1a6f108238ae6aab6a65e5eed5e75d456be1c2bf29b04e5c1e7d7adbae", - "sha256:5d8cea8ae1996938ec3eaf44567bbc5ef1bc900742190c439a44a704d6e1b62b" - ], - "markers": "python_version >= '3.8'", - "version": "==1.3.1" - }, "pytz": { "hashes": [ "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", @@ -1953,15 +1934,6 @@ "markers": "python_version >= '3.5'", "version": "==1.12.1" }, - "rope": { - "hashes": [ - "sha256:00a7ea8c0c376fc0b053b2f2f8ef3bfb8b50fecf1ebf3eb80e4f8bd7f1941918", - "sha256:8803e3b667315044f6270b0c69a10c0679f9f322ed8efe6245a93ceb7658da69" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.14.0" - }, "ruff": { "hashes": [ "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", From a9bbb09b5cd986df3b25101e2e427dfd037d6c7b Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 11:59:56 -0400 Subject: [PATCH 10/13] Fixes runner issue --- .github/workflows/pythonpackage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 112a4f2..6651878 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -11,7 +11,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 environment: test strategy: max-parallel: 1 From 7a3d211d6ecde11baf39989ce121d75034a94bef Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Wed, 6 Aug 2025 12:07:23 -0400 Subject: [PATCH 11/13] Fixes typing issues for Python 3.7 --- mygeotab/parameters.py | 8 ++++---- pyproject.toml | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mygeotab/parameters.py b/mygeotab/parameters.py index ba36446..378959e 100644 --- a/mygeotab/parameters.py +++ b/mygeotab/parameters.py @@ -9,10 +9,10 @@ import re from copy import copy -from typing import Any, Optional +from typing import Any, Optional, Dict, Union -def camelcaseify_parameters(parameters: dict[str, Any]) -> dict[str, Any]: +def camelcaseify_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]: """Allows the use of Pythonic-style parameters with underscores instead of camel-case. :param parameters: The parameters object. @@ -34,7 +34,7 @@ def camelcaseify_parameters(parameters: dict[str, Any]) -> dict[str, Any]: return params -def convert_get_parameters(parameters: dict[str, Any]) -> dict[str, Any]: +def convert_get_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]: """Converts parameters passed into a get() call to a format suitable for the MyGeotab API. It detects if a 'search' dictionary is passed and flattens it into the top-level parameters. It also detects 'resultsLimit'/'results_limit' or 'sort' parameters and removes them from the parameters @@ -68,7 +68,7 @@ def convert_get_parameters(parameters: dict[str, Any]) -> dict[str, Any]: return result -def _try_extract_get_parameter(parameters: dict[str, Any], name: str, pythonic_name: Optional[str] = None) -> Any | None: +def _try_extract_get_parameter(parameters: Dict[str, Any], name: str, pythonic_name: Optional[str] = None) -> Union[Any, None]: """Helper to get a parameter from a dictionary, returning None if it doesn't exist.""" parameter = parameters.get(name) if parameter is not None: diff --git a/pyproject.toml b/pyproject.toml index 6c008e3..68aaba4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,6 @@ [tool.ruff] line-length = 127 +target-version = "py37" [tool.ruff.lint] select = ["E", "F", "B"] From 404ab9e5e587ae2575baae706ef8b5428629147b Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Thu, 4 Sep 2025 16:48:28 -0400 Subject: [PATCH 12/13] Removes unneeded test --- tests/test_api.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 59b8276..11daaed 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -15,19 +15,6 @@ def test_should_verify_ssl(self): assert my_api._is_verify_ssl is False -class TestProcessParameters: - def test_camel_case_transformer(self): - params = dict(search=dict(device_search=dict(id=123), include_overlapped_trips=True)) - fixed_params = api.process_parameters(params) - assert fixed_params is not None - assert "search" in fixed_params - assert "deviceSearch" in fixed_params["search"] - assert "id" in fixed_params["search"]["deviceSearch"] - assert fixed_params["search"]["deviceSearch"]["id"] == 123 - assert "includeOverlappedTrips" in fixed_params["search"] - assert fixed_params["search"]["includeOverlappedTrips"] - - class TestProcessResults: def test_handle_server_exception(self): exception_response = dict( From 556879bbef77bc81375f060cff8a42526893e988 Mon Sep 17 00:00:00 2001 From: Aaron Toth Date: Thu, 4 Sep 2025 17:02:18 -0400 Subject: [PATCH 13/13] Updates changelog --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7831fc8..99bddce 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,14 @@ Changes ------- +TBD ++++ + +**Improvements** + +- Centralized and better handling of new parameters in API calls (like `resultsLimit`, `search`, and `propertySelector`) `#127 __`. + + 0.9.2 (2024-10-08) ++++++++++++++++++