From b747f7e3b502acdff511b070c30c423549c11266 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Tue, 19 Sep 2023 12:15:48 -0700 Subject: [PATCH 01/48] Add support for UUIDs in request payloads Resolves #77 --- test/test_util.py | 3 +++ welkin/util.py | 48 +++++++++++++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/test/test_util.py b/test/test_util.py index 1d479a8..adf45d2 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -1,4 +1,5 @@ import sys +import uuid from datetime import date, datetime, timedelta, timezone from welkin.util import ( @@ -24,6 +25,7 @@ def test_clean_request_payload(): "int": [-sys.maxsize, 0, sys.maxsize], "float": [sys.float_info.min, 1, sys.float_info.max], "bool": [True, False], + "uuid4": uuid.uuid4(), "none": None, } payload_copy = dict(payload) @@ -35,6 +37,7 @@ def test_clean_request_payload(): assert cleaned["date"] == "2022-09-15T00:00:00.000Z" assert cleaned["dict"]["nested"]["date"] == "2022-09-15T00:00:00.000Z" assert cleaned["list"][0] == "2022-09-15T23:00:00.000Z" + assert isinstance(cleaned["uuid4"], str) def test_clean_json_list(): diff --git a/welkin/util.py b/welkin/util.py index ed2764a..1a06dcf 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,4 +1,6 @@ from datetime import date, datetime, timezone +from typing import Any +from uuid import UUID from welkin.models.base import SchemaBase @@ -38,19 +40,34 @@ def _build_resources(instance: type, attribute_name: str, value: type = None) -> setattr(val, attribute_name, value) +def clean_data(value: Any) -> Any: + """Clean data for JSON serialization. + + Args: + value (Any): The value to clean. + + Returns: + Any: The cleaned value. + """ + if isinstance(value, datetime): + return clean_datetime(value) + elif isinstance(value, date): + return clean_date(value) + elif isinstance(value, dict): + return clean_request_payload(value) + elif isinstance(value, list): + return clean_json_list(value) + elif isinstance(value, UUID): + return str(value) + + # No cleaning needed + return value + + def clean_request_payload(payload: dict) -> dict: result = {} for k, v in payload.items(): - if isinstance(v, datetime): - result[k] = clean_datetime(v) - elif isinstance(v, date): - result[k] = clean_date(v) - elif isinstance(v, dict): - result[k] = clean_request_payload(v) - elif isinstance(v, list): - result[k] = clean_json_list(v) - else: - result[k] = v + result[k] = clean_data(v) return result @@ -58,16 +75,7 @@ def clean_request_payload(payload: dict) -> dict: def clean_json_list(data: list) -> list: result = [] for item in data: - if isinstance(item, datetime): - result.append(clean_datetime(item)) - elif isinstance(item, date): - result.append(clean_date(item)) - elif isinstance(item, dict): - result.append(clean_request_payload(item)) - elif isinstance(item, list): - result.append(clean_json_list(item)) - else: - result.append(item) + result.append(clean_data(item)) return result From 8e399d90906659805f07a78d4a6433b93ca5de7f Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Tue, 19 Sep 2023 13:04:14 -0700 Subject: [PATCH 02/48] Refactor util tests --- test/conftest.py | 52 ++++++++++++ test/test_util.py | 198 ++++++++++++++++++++++++---------------------- 2 files changed, 157 insertions(+), 93 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 4678078..0ee1327 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,6 +1,8 @@ import json import os import uuid +from datetime import date, datetime, time, timedelta, timezone +from uuid import uuid4 import pytest @@ -103,3 +105,53 @@ def hook(dct): return dct return hook + + +@pytest.fixture +def base_date(): + return date(year=2022, month=9, day=15) + + +@pytest.fixture +def base_date_str(): + return "2022-09-15T00:00:00.000Z" + + +@pytest.fixture +def base_time(): + return time(hour=23, minute=0, second=0, microsecond=0) + + +@pytest.fixture +def utc_datetime(base_date, base_time): + return datetime.combine(base_date, base_time, tzinfo=timezone.utc) + + +@pytest.fixture +def utc_datetime_str(): + return "2022-09-15T23:00:00.000Z" + + +@pytest.fixture +def pst_datetime(base_date, base_time): + return datetime.combine(base_date, base_time, tzinfo=timezone(timedelta(hours=-8))) + + +@pytest.fixture +def pst_datetime_str(): + return "2022-09-16T07:00:00.000Z" + + +@pytest.fixture +def est_datetime(base_date, base_time): + return datetime.combine(base_date, base_time, tzinfo=timezone(timedelta(hours=-5))) + + +@pytest.fixture +def est_datetime_str(): + return "2022-09-16T04:00:00.000Z" + + +@pytest.fixture +def _uuid(): + return uuid4() diff --git a/test/test_util.py b/test/test_util.py index adf45d2..fdfb784 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -1,6 +1,7 @@ +import copy import sys -import uuid -from datetime import date, datetime, timedelta, timezone + +import pytest from welkin.util import ( clean_date, @@ -10,95 +11,106 @@ clean_request_payload, ) -UTC = timezone.utc -PST = timezone(timedelta(hours=-8)) -EST = timezone(timedelta(hours=-5)) - - -def test_clean_request_payload(): - payload = { - "datetime": datetime(2022, 9, 15, 23, 0, 0, 0, PST), - "date": date(2022, 9, 15), - "dict": {"foo": "bar", "nested": {"date": date(2022, 9, 15)}}, - "list": [datetime(2022, 9, 15, 23, 0, 0, 0, UTC)], - "str": "Don't clean me please.", - "int": [-sys.maxsize, 0, sys.maxsize], - "float": [sys.float_info.min, 1, sys.float_info.max], - "bool": [True, False], - "uuid4": uuid.uuid4(), - "none": None, - } - payload_copy = dict(payload) - - cleaned = clean_request_payload(payload) - assert payload == payload_copy, "Payload was modified" - - assert cleaned["datetime"] == "2022-09-16T07:00:00.000Z" - assert cleaned["date"] == "2022-09-15T00:00:00.000Z" - assert cleaned["dict"]["nested"]["date"] == "2022-09-15T00:00:00.000Z" - assert cleaned["list"][0] == "2022-09-15T23:00:00.000Z" - assert isinstance(cleaned["uuid4"], str) - - -def test_clean_json_list(): - json_list = [ - datetime(2022, 9, 15, 23, 0, 0, 0, UTC), - date(2022, 9, 15), - [ - { - "foo": [datetime(2022, 9, 15, 23, 0, 0, 0, PST)], + +class TestCleanRequestPayload: + @pytest.fixture + def payload(self, _uuid, base_date, utc_datetime, pst_datetime): + return { + "datetime": pst_datetime, + "date": base_date, + "dict": { + "foo": "bar", + "nested": {"date": base_date}, }, - ], - "Strings don't get cleaned", - ] - json_list_copy = list(json_list) - - cleaned = clean_json_list(json_list) - assert json_list == json_list_copy, "JSON list was modified" - - assert cleaned[0] == "2022-09-15T23:00:00.000Z" - assert cleaned[1] == "2022-09-15T00:00:00.000Z" - assert cleaned[2][0]["foo"][0] == "2022-09-16T07:00:00.000Z" - - -def test_clean_request_params(): - params = { - "datetime": datetime(2022, 9, 15, 23, 0, 0, 0, PST), - "date": date(2022, 9, 15), - "list": ["foo", "bar", "baz"], - } - params_copy = dict(params) - cleaned = clean_request_params(params) - - assert params == params_copy, "Parameter dict was modified" - - assert cleaned["datetime"] == "2022-09-16T07:00:00.000Z" - assert cleaned["date"] == "2022-09-15T00:00:00.000Z" - assert cleaned["list"] == "foo,bar,baz" - - -def test_clean_date(): - cleaned = clean_date(date(2022, 9, 15)) - - assert cleaned == "2022-09-15T00:00:00.000Z" - - -def test_clean_datetime(): - datetime_tests = { - "utc": { - "dt": datetime(2022, 9, 15, 23, 0, 0, 0, UTC), - "expected": "2022-09-15T23:00:00.000Z", - }, - "pst": { - "dt": datetime(2022, 9, 15, 23, 0, 0, 0, PST), - "expected": "2022-09-16T07:00:00.000Z", - }, - "est": { - "dt": datetime(2022, 9, 15, 23, 0, 0, 0, EST), - "expected": "2022-09-16T04:00:00.000Z", - }, - } - timedelta() - for name, data in datetime_tests.items(): - cleaned = clean_datetime(data["dt"]) - assert cleaned == data["expected"], f"Unexpected result for '{name}'" + "list": [utc_datetime], + "str": "Don't clean me please.", + "int": [-sys.maxsize, 0, sys.maxsize], + "float": [sys.float_info.min, 1, sys.float_info.max], + "bool": [True, False], + "_uuid4": _uuid, + "none": None, + } + + def test_clean_request_payload( + self, payload, _uuid, pst_datetime_str, base_date_str, utc_datetime_str + ): + payload_copy = copy.deepcopy(payload) + cleaned = clean_request_payload(payload) + assert payload == payload_copy, "Payload was modified" + + assert cleaned["datetime"] == pst_datetime_str + assert cleaned["date"] == base_date_str + assert cleaned["dict"]["nested"]["date"] == base_date_str + assert cleaned["list"][0] == utc_datetime_str + assert cleaned["_uuid4"] == str(_uuid) + + +class TestCleanJsonList: + @pytest.fixture + def json_list(self, utc_datetime, base_date, pst_datetime): + return [ + utc_datetime, + base_date, + [ + { + "foo": [pst_datetime], + }, + ], + "Strings don't get cleaned", + ] + + def test_clean_json_list( + self, json_list, utc_datetime_str, base_date_str, pst_datetime_str + ): + json_list_copy = copy.deepcopy(json_list) + cleaned = clean_json_list(json_list) + assert json_list == json_list_copy, "JSON list was modified" + + assert cleaned[0] == utc_datetime_str + assert cleaned[1] == base_date_str + assert cleaned[2][0]["foo"][0] == pst_datetime_str + + +class TestCleanRequestParams: + @pytest.fixture + def params(self, pst_datetime, base_date): + return { + "datetime": pst_datetime, + "date": base_date, + "list": ["foo", "bar", "baz"], + } + + def test_clean_request_params(self, params, pst_datetime_str, base_date_str): + params_copy = copy.deepcopy(params) + cleaned = clean_request_params(params) + assert params == params_copy, "Parameter dict was modified" + + assert cleaned["datetime"] == pst_datetime_str + assert cleaned["date"] == base_date_str + assert cleaned["list"] == "foo,bar,baz" + + +def test_clean_date(base_date, base_date_str): + assert clean_date(base_date) == base_date_str + + +@pytest.mark.parametrize( + "dt,expected", + [ + ( + "utc_datetime", + "utc_datetime_str", + ), + ( + "pst_datetime", + "pst_datetime_str", + ), + ( + "est_datetime", + "est_datetime_str", + ), + ], +) +def test_clean_datetime(dt, expected, request): + cleaned = clean_datetime(request.getfixturevalue(dt)) + assert cleaned == request.getfixturevalue(expected) From 5caec440f25981edbd3b7c1a90a1883113ad8543 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 26 Oct 2023 19:05:09 -0700 Subject: [PATCH 03/48] Unify parent accessor methods --- test/test_base.py | 49 ++++++++++++++++----- test/test_util.py | 47 ++++++++++++++++++++ welkin/models/assessment.py | 88 +++++++++++++------------------------ welkin/models/care_plan.py | 21 +++------ welkin/models/cdt.py | 69 ++++++++++++----------------- welkin/models/chat.py | 15 ++++--- welkin/models/document.py | 56 +++++++++-------------- welkin/models/email.py | 11 +++-- welkin/models/encounter.py | 33 +++++++------- welkin/models/sms.py | 10 ++--- welkin/models/util.py | 63 -------------------------- welkin/util.py | 45 +++++++++++++++++++ 12 files changed, 250 insertions(+), 257 deletions(-) delete mode 100644 welkin/models/util.py diff --git a/test/test_base.py b/test/test_base.py index 010ac8a..d62b1b6 100644 --- a/test/test_base.py +++ b/test/test_base.py @@ -1,20 +1,45 @@ import inspect +import pytest + +from welkin.models import Patient, __all__ from welkin.models.base import Collection from welkin.pagination import PageIterator -def test_collection_pageable(client): - for v in vars(client).values(): - try: - if not issubclass(v, Collection): - continue - except TypeError: - continue +@pytest.mark.parametrize("class_name", __all__) +def test_collection_pageable(client, class_name: str): + cls = getattr(client, class_name) + if not issubclass(cls, Collection): + return + + assert hasattr(cls, "get"), f"{cls} has no get method" + assert issubclass(cls.iterator, PageIterator) + + method = cls.get + args = inspect.getfullargspec(method) + assert args.varargs is not None, f"{method} must accept variable args" + assert args.varkw is not None, f"{method} must accept variable kwargs" + + +@pytest.mark.parametrize("class_name", __all__) +def test_method_args(client, class_name: str): + cls = getattr(client, class_name) + + for method_name, method in inspect.getmembers(cls, predicate=inspect.isfunction): + if method_name.startswith("__"): + continue # skip dunder methods + + if hasattr(method, "__wrapped__"): + method = method.__wrapped__ # unwrap decorated functions + + if method.__qualname__ != f"{class_name}.{method_name}": + continue # skip methods from parent classes - assert hasattr(v, "get"), f"{v} has no get method" - assert issubclass(v.iterator, PageIterator) + args = inspect.getfullargspec(method) - args = inspect.getfullargspec(v.get) - assert args.varargs is not None, f"{v}.get must accept variable args" - assert args.varkw is not None, f"{v}.get must accept variable kwargs" + if cls in Patient.subresources: + try: + assert args.args.index("patient_id") == 1, f"patient_id must be first" + except ValueError: + pytest.fail(f"{method} must accept patient_id") diff --git a/test/test_util.py b/test/test_util.py index fdfb784..e8cde7e 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -9,6 +9,8 @@ clean_json_list, clean_request_params, clean_request_payload, + find_model_id, + to_snake_case, ) @@ -114,3 +116,48 @@ def test_clean_date(base_date, base_date_str): def test_clean_datetime(dt, expected, request): cleaned = clean_datetime(request.getfixturevalue(dt)) assert cleaned == request.getfixturevalue(expected) + + +@pytest.mark.parametrize( + "input", + [ + "foo_bar", + "fooBar", + "FooBar", + "FOO_BAR", + "fooBAR", + "FOOBar", + ], +) +def test_to_snake_case(input): + assert to_snake_case(input) == "foo_bar" + + +def test_find_model_id(client): + patient = client.Patient() + encounter = patient.Encounter() + + with pytest.raises(AttributeError): + find_model_id(encounter, "Patient") + + patient.id = "123" + assert find_model_id(patient, "Patient") == patient.id + assert find_model_id(encounter, "Patient") == patient.id + + patient.pop("id") + encounter.patientId = "456" + assert find_model_id(encounter, "Patient") == encounter.patientId + + +def test_model_id(client): + encounter = client.Patient().Encounter() + with pytest.raises(TypeError) as exc_info: + encounter.get() + + assert "missing 1 required positional argument" in exc_info.value.args[0] + + disposition = encounter.EncounterDisposition() + with pytest.raises(TypeError) as exc_info: + disposition.get() + + assert "missing 2 required positional arguments" in exc_info.value.args[0] diff --git a/welkin/models/assessment.py b/welkin/models/assessment.py index 5efa5af..e37f615 100644 --- a/welkin/models/assessment.py +++ b/welkin/models/assessment.py @@ -1,43 +1,33 @@ -from sys import modules - from welkin.models.base import Collection, Resource -from welkin.models.util import EncounterSubResource, patient_id from welkin.pagination import PageableIterator +from welkin.util import model_id -class Assessment(Resource, EncounterSubResource): - def create(self, patient_id: str = None, encounter_id: str = None): - patient_id, encounter_id = self.get_patient_encounter_id( - patient_id, encounter_id - ) +class Assessment(Resource): + @model_id("Patient", "Encounter") + def create(self, patient_id: str, encounter_id: str): return super().post( f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}" "/assessments" ) - def get(self, patient_id: str = None, encounter_id: str = None): - patient_id, encounter_id = self.get_patient_encounter_id( - patient_id, encounter_id - ) + @model_id("Patient", "Encounter") + def get(self, patient_id: str, encounter_id: str): return super().get( f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}/" f"assessments/{self.id}" ) - def update(self, patient_id: str = None, encounter_id: str = None, **kwargs): - patient_id, encounter_id = self.get_patient_encounter_id( - patient_id, encounter_id - ) + @model_id("Patient", "Encounter") + def update(self, patient_id: str, encounter_id: str, **kwargs): return super().patch( f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}/" f"assessments/{self.id}", kwargs, ) - def delete(self, patient_id: str = None, encounter_id: str = None): - patient_id, encounter_id = self.get_patient_encounter_id( - patient_id, encounter_id - ) + @model_id("Patient", "Encounter") + def delete(self, patient_id: str, encounter_id: str): return super().delete( f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}/" f"assessments/{self.id}" @@ -48,34 +38,19 @@ class Assessments(Collection): resource = Assessment iterator = PageableIterator - def get(self, patient_id: str = None, encounter_id: str = None, *args, **kwargs): - - root = f"{self._client.instance}/patients/" - if self._parent: - encounter_id = self._parent.id - if isinstance( - self._parent._parent, getattr(modules["welkin.models"], "Patient") - ): - patient_id = self._parent._parent.id - elif hasattr(self._parent, "patientId"): - patient_id = self._parent.patientId - else: - # this is the related_data = True case on encounters - patient_id = self._parent.encounter.patientId - - path = f"{patient_id}/encounters/{encounter_id}/assessments" - - return super().get(f"{root}{path}", *args, **kwargs) + @model_id("Patient", "Encounter") + def get(self, patient_id: str, encounter_id: str, *args, **kwargs): + return super().get( + f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}/" + f"assessments", + *args, + **kwargs, + ) class AssessmentRecordAnswers(Resource): - def update(self, patient_id: str = None, assessment_record_id: str = None): - if not assessment_record_id: - assessment_record_id = self._parent.id - - if not patient_id: - patient_id = self._parent.get_patient_id(patient_id) - + @model_id("Patient", "AssessmentRecord") + def update(self, patient_id: str, assessment_record_id: str): return super().put( f"{self._client.instance}/patients/{patient_id}/" f"assessment-records/{assessment_record_id}/answers" @@ -85,43 +60,40 @@ def update(self, patient_id: str = None, assessment_record_id: str = None): class AssessmentRecord(Resource): subresources = [AssessmentRecordAnswers] - @patient_id - def create(self, patient_id: str = None): + @model_id("Patient") + def create(self, patient_id: str): return super().post( f"{self._client.instance}/patients/{patient_id}/assessment-records" ) - @patient_id - def get(self, patient_id: str = None): + @model_id("Patient") + def get(self, patient_id: str): return super().get( f"{self._client.instance}/patients/" f"{patient_id}/assessment-records/{self.id}" ) - @patient_id - def update(self, patient_id: str = None): + @model_id("Patient") + def update(self, patient_id: str): return super().put( f"{self._client.instance}/patients/" f"{patient_id}/assessment-records/{self.id}" ) - @patient_id - def delete(self, patient_id: str = None): + @model_id("Patient") + def delete(self, patient_id: str): return super().delete( f"{self._client.instance}/patients/" f"{patient_id}/assessment-records/{self.id}", ) - def get_patient_id(self, patient_id): - return patient_id if patient_id else self._parent.id - class AssessmentRecords(Collection): resource = AssessmentRecord iterator = PageableIterator - @patient_id - def get(self, patient_id: str = None, **kwargs): + @model_id("Patient") + def get(self, patient_id: str, **kwargs): path = f"{self._client.instance}/patients/{patient_id}/assessment-records" return super().get(path, **kwargs) diff --git a/welkin/models/care_plan.py b/welkin/models/care_plan.py index 1d2a04c..1423b36 100644 --- a/welkin/models/care_plan.py +++ b/welkin/models/care_plan.py @@ -1,13 +1,10 @@ from welkin.models.base import Resource -from welkin.models.util import find_patient_id_in_parents +from welkin.util import model_id class CarePlanOverview(Resource): - def update(self, patient_id: str = None): - if not patient_id: - # self._parent -> CarePlan - # CarePlan._parent -> Patient - patient_id = find_patient_id_in_parents(self) + @model_id("Patient") + def update(self, patient_id: str): return super().put( f"{self._client.instance}/patients/{patient_id}/care-plan/overview" ) @@ -16,16 +13,12 @@ def update(self, patient_id: str = None): class CarePlan(Resource): subresources = [CarePlanOverview] - def create(self, patient_id: str = None): - if not patient_id: - # self._parent -> Patient - patient_id = find_patient_id_in_parents(self) + @model_id("Patient") + def create(self, patient_id: str): return super().post( f"{self._client.instance}/patients/{patient_id}/care-plan/overview" ) - def get(self, patient_id: str = None): - if not patient_id: - # self._parent -> Patient - patient_id = find_patient_id_in_parents(self) + @model_id("Patient") + def get(self, patient_id: str): return super().get(f"{self._client.instance}/patients/{patient_id}/care-plan") diff --git a/welkin/models/cdt.py b/welkin/models/cdt.py index 98cf848..7d45588 100644 --- a/welkin/models/cdt.py +++ b/welkin/models/cdt.py @@ -2,28 +2,33 @@ from welkin.models.base import Collection, Resource from welkin.pagination import PageNumberIterator +from welkin.util import model_id class CDT(Resource): - def create(self): + @model_id("Patient") + def create(self, patient_id: str): return super().post( - f"{self._client.instance}/patients/{self._parent.id}/cdts/{self.cdtName}" + f"{self._client.instance}/patients/{patient_id}/cdts/{self.cdtName}" ) - def get(self): + @model_id("Patient") + def get(self, patient_id: str): return super().get( - f"{self._client.instance}/patients/{self._parent.id}/cdts/{self.cdtName}/{self.id}" + f"{self._client.instance}/patients/{patient_id}/cdts/{self.cdtName}/{self.id}" ) - def update(self, **kwargs): + @model_id("Patient") + def update(self, patient_id: str, **kwargs): return super().patch( - f"{self._client.instance}/patients/{self._parent.id}/cdts/{self.cdtName}/{self.id}", + f"{self._client.instance}/patients/{patient_id}/cdts/{self.cdtName}/{self.id}", kwargs, ) - def delete(self): + @model_id("Patient") + def delete(self, patient_id: str): return super().delete( - f"{self._client.instance}/patients/{self._parent.id}/cdts/{self.cdtName}/{self.id}" + f"{self._client.instance}/patients/{patient_id}/cdts/{self.cdtName}/{self.id}" ) @@ -31,10 +36,11 @@ class CDTs(Collection): resource = CDT iterator = PageNumberIterator + @model_id("Patient") def get( self, - patient_id: str = None, - cdt_name: str = None, + patient_id: str, + cdt_name: str, fields: list = None, filters: dict = None, date_start: datetime = None, @@ -43,19 +49,6 @@ def get( *args, **kwargs, ): - - root = "" - if patient_id: - root = f"patients/{patient_id}" - else: - root = f"patients/{self._parent.id}" - - cdt_path = "" - if cdt_name: - cdt_path = f"cdts/{cdt_name}" - - path = f"{self._client.instance}/{root}/{cdt_path}" - params = { "fields": fields, "filters": filters, @@ -64,21 +57,17 @@ def get( "dateEnd": date_end, } - return super().get(path, params=params, *args, **kwargs) - - def update( - self, patient_id: str = None, cdt_name: str = None, body: dict = None, **kwargs - ): - root = "" - if patient_id: - root = f"patients/{patient_id}" - else: - root = f"patients/{self._parent.id}" - - cdt_path = "" - if cdt_name: - cdt_path = f"cdts/{cdt_name}" - - path = f"{self._client.instance}/{root}/{cdt_path}" + return super().get( + f"{self._client.instance}/patients/{patient_id}/cdts/{cdt_name}", + params=params, + *args, + **kwargs, + ) - return super().patch(path, json=body, **kwargs) + @model_id("Patient") + def update(self, patient_id: str, cdt_name: str, body: dict = None, **kwargs): + return super().patch( + f"{self._client.instance}/patients/{patient_id}/cdts/{cdt_name}", + json=body, + **kwargs, + ) diff --git a/welkin/models/chat.py b/welkin/models/chat.py index 562ebbe..64d8c3e 100644 --- a/welkin/models/chat.py +++ b/welkin/models/chat.py @@ -1,11 +1,13 @@ from welkin.models.base import Collection, Resource from welkin.pagination import MetaIterator +from welkin.util import model_id class Chat(Resource): - def create(self): + @model_id("Patient") + def create(self, patient_id: str): return super().post( - f"{self._client.instance}/patients/{self._parent.id}/chat/inbound" + f"{self._client.instance}/patients/{patient_id}/chat/inbound" ) def __str__(self): @@ -16,13 +18,14 @@ class Chats(Collection): resource = Chat iterator = MetaIterator - def get(self, include_archived: bool = False, *args, **kwargs): + @model_id("Patient") + def get(self, patient_id: str, include_archived: bool = False, *args, **kwargs): params = { "includeArchived": include_archived, } return super().get( - f"{self._client.instance}/patients/{self._parent.id}/chat", + f"{self._client.instance}/patients/{patient_id}/chat", params=params, *args, **kwargs, @@ -37,8 +40,10 @@ class SearchChats(Collection): resource = ChatSearchResult iterator = MetaIterator + @model_id("Patient") def get( self, + patient_id: str, query: str, content_page_size: int = 20, include_archived: bool = False, @@ -52,7 +57,7 @@ def get( } return super().get( - f"{self._client.instance}/patients/{self._parent.id}/chat/search", + f"{self._client.instance}/patients/{patient_id}/chat/search", params=params, *args, **kwargs, diff --git a/welkin/models/document.py b/welkin/models/document.py index 11a1d74..5286338 100644 --- a/welkin/models/document.py +++ b/welkin/models/document.py @@ -1,45 +1,37 @@ from io import BytesIO from welkin.models.base import Collection, Resource -from welkin.models.util import find_patient_id_in_parents from welkin.pagination import PageableIterator +from welkin.util import model_id class DocumentSummaryFile(Resource): - def get(self, patient_id: str = None, document_summary_id: str = None) -> BytesIO: - if not patient_id: - patient_id = find_patient_id_in_parents(self) - - if not document_summary_id: - document_summary_id = self._parent.id - - content = self._client.get( - f"{self._client.instance}/patients/{patient_id}/document-summary/{document_summary_id}/files/{self.id}" + @model_id("Patient", "DocumentSummary") + def get(self, patient_id: str, document_summary_id: str) -> BytesIO: + response = self._client.get( + f"{self._client.instance}/patients/{patient_id}/document-summary/" + f"{document_summary_id}/files/{self.id}" ) - return BytesIO(content) + return BytesIO(response) class DocumentSummaryFiles(Collection): resource = DocumentSummaryFile iterator = PageableIterator + @model_id("Patient", "DocumentSummary") def create( self, - patient_id: str = None, - document_summary_id: str = None, + patient_id: str, + document_summary_id: str, files: list = None, *args, **kwargs, ): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - - if not document_summary_id: - document_summary_id = self._parent.id - return super().post( - f"{self._client.instance}/patients/{patient_id}/document-summary/{document_summary_id}/files", + f"{self._client.instance}/patients/{patient_id}/document-summary/" + f"{document_summary_id}/files", files=files, *args, **kwargs, @@ -49,26 +41,20 @@ def create( class DocumentSummary(Resource): subresources = [DocumentSummaryFile, DocumentSummaryFiles] - def get(self, patient_id: str = None): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - + @model_id("Patient") + def get(self, patient_id: str): return super().get( f"{self._client.instance}/patients/{patient_id}/document-summary/{self.id}" ) - def create(self, patient_id: str = None): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - + @model_id("Patient") + def create(self, patient_id: str): return super().post( f"{self._client.instance}/patients/{patient_id}/document-summary" ) - def delete(self, patient_id: str = None): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - + @model_id("Patient") + def delete(self, patient_id: str): return super().delete( f"{self._client.instance}/patients/{patient_id}/document-summary/{self.id}" ) @@ -78,10 +64,8 @@ class DocumentSummaries(Collection): resource = DocumentSummary iterator = PageableIterator - def get(self, patient_id: str = None, *args, **kwargs): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - + @model_id("Patient") + def get(self, patient_id: str, *args, **kwargs): return super().get( f"{self._client.instance}/patients/{patient_id}/document-summary", *args, diff --git a/welkin/models/email.py b/welkin/models/email.py index f900361..4890adc 100644 --- a/welkin/models/email.py +++ b/welkin/models/email.py @@ -1,11 +1,11 @@ from welkin.models.base import Collection, Resource -from welkin.models.util import patient_id from welkin.pagination import PageableIterator +from welkin.util import model_id class Email(Resource): - @patient_id - def get(self, patient_id: str = None, *args, **kwargs): + @model_id("Patient") + def get(self, patient_id: str, *args, **kwargs): return super().get( f"{self._client.instance}/patients/{patient_id}/emails/{self.id}", *args, @@ -17,9 +17,8 @@ class Emails(Collection): resource = Email iterator = PageableIterator - @patient_id - def get(self, patient_id: str = None, sort: str = None, *args, **kwargs): - + @model_id("Patient") + def get(self, patient_id: str, sort: str = None, *args, **kwargs): params = { "sort": sort, } diff --git a/welkin/models/encounter.py b/welkin/models/encounter.py index 04ebbb3..5b576e8 100644 --- a/welkin/models/encounter.py +++ b/welkin/models/encounter.py @@ -2,23 +2,19 @@ from welkin.models.assessment import Assessment, Assessments from welkin.models.base import Collection, Resource -from welkin.models.util import EncounterSubResource, patient_id from welkin.pagination import MetaInfoIterator +from welkin.util import model_id -class EncounterDisposition(Resource, EncounterSubResource): - def get(self, patient_id: str = None, encounter_id: str = None): - patient_id, encounter_id = self.get_patient_encounter_id( - patient_id, encounter_id - ) +class EncounterDisposition(Resource): + @model_id("Patient", "Encounter") + def get(self, patient_id: str, encounter_id: str): return super().get( f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}/disposition" ) - def update(self, patient_id: str = None, encounter_id: str = None, **kwargs): - patient_id, encounter_id = self.get_patient_encounter_id( - patient_id, encounter_id - ) + @model_id("Patient", "Encounter") + def update(self, patient_id: str, encounter_id: str, **kwargs): return super().patch( f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}/disposition", kwargs, @@ -40,12 +36,12 @@ class Encounter(Resource): "disposition": "EncounterDisposition", } - @patient_id - def create(self, patient_id: str = None): + @model_id("Patient") + def create(self, patient_id: str): return super().post(f"{self._client.instance}/patients/{patient_id}/encounters") - @patient_id - def get(self, patient_id: str = None, related_data: bool = False): + @model_id("Patient") + def get(self, patient_id: str, related_data: bool = False): encounters = "encounters" if related_data: encounters = "full-encounters" @@ -54,15 +50,15 @@ def get(self, patient_id: str = None, related_data: bool = False): f"{self._client.instance}/patients/{patient_id}/{encounters}/{self.id}" ) - @patient_id - def update(self, patient_id: str = None, **kwargs): + @model_id("Patient") + def update(self, patient_id: str, **kwargs): return super().patch( f"{self._client.instance}/patients/{patient_id}/encounters/{self.id}", kwargs, ) - @patient_id - def delete(self, patient_id: str = None): + @model_id("Patient") + def delete(self, patient_id: str): return super().delete( f"{self._client.instance}/patients/{patient_id}/encounters/{self.id}" ) @@ -94,6 +90,7 @@ def get( root = f"patients/{self._parent.id}" elif self._parent.__class__.__name__ == "User": root = f"users/{self._parent.id}" + encounters = "encounters" if related_data: encounters = "full-encounters" diff --git a/welkin/models/sms.py b/welkin/models/sms.py index 6bcfcb0..5551ab8 100644 --- a/welkin/models/sms.py +++ b/welkin/models/sms.py @@ -1,11 +1,11 @@ from welkin.models.base import Collection, Resource -from welkin.models.util import patient_id from welkin.pagination import PageableIterator +from welkin.util import model_id class SMS(Resource): - @patient_id - def get(self, patient_id: str = None, *args, **kwargs): + @model_id("Patient") + def get(self, patient_id: str, *args, **kwargs): return super().get( f"{self._client.instance}/patients/{patient_id}/sms/{self.id}", *args, @@ -17,8 +17,8 @@ class SMSes(Collection): resource = SMS iterator = PageableIterator - @patient_id - def get(self, patient_id: str = None, sort: str = None, *args, **kwargs): + @model_id("Patient") + def get(self, patient_id: str, sort: str = None, *args, **kwargs): params = { "sort": sort, diff --git a/welkin/models/util.py b/welkin/models/util.py deleted file mode 100644 index f6b938e..0000000 --- a/welkin/models/util.py +++ /dev/null @@ -1,63 +0,0 @@ -from sys import modules - - -def find_patient_id_in_parents(model_instance): - if isinstance( - model_instance, - getattr(modules["welkin.models"], "Patient"), - ): - return model_instance.id - elif hasattr(model_instance, "patientId"): - return model_instance.patientId - elif model_instance._parent: - return find_patient_id_in_parents(model_instance._parent) - else: - raise Exception( - f"Cannot find patient id. Model._parent chain ends in {model_instance}" - ) - - -class EncounterSubResource: - """Utility class for subresources of Encounters to get patient and encounter ids""" - - @property - def patient_id(self): - if isinstance( - self._parent._parent, - getattr(modules["welkin.models"], "Patient"), - ): - return self._parent._parent.id - - if hasattr(self._parent, "patientId"): - return self._parent.patientId - - # this is the related_data = True case on encounters - return self._parent.encounter.patientId - - def get_patient_encounter_id(self, patient_id, encounter_id): - """Helper to retrieve the necessary patient and encounter Ids""" - if not patient_id: - patient_id = self.patient_id - - if not encounter_id: - encounter_id = self._parent.id - - return patient_id, encounter_id - - -def patient_id(func): - """Wrapper for getting the patient id on patient subresources""" - - def wrapper(cls, *args, **kwargs): - if "patient_id" not in kwargs: - try: - kwargs["patient_id"] = cls._parent.id - except AttributeError: - raise TypeError( - f"{func.__name__} is missing 1 required positional argument: " - "'patient_id" - ) from None - - return func(cls, *args, **kwargs) - - return wrapper diff --git a/welkin/util.py b/welkin/util.py index 1a06dcf..4424dd8 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,3 +1,5 @@ +import functools +import re from datetime import date, datetime, timezone from typing import Any from uuid import UUID @@ -107,3 +109,46 @@ def clean_datetime(dt: datetime) -> str: .isoformat(timespec="milliseconds") .replace("+00:00", "Z") ) + + +def find_model_id(obj, model: str): + if obj.__class__.__name__ == model: + return obj.id + elif hasattr(obj, f"{to_snake_case(model)}Id"): + return obj.patientId + elif obj._parent: + return find_model_id(obj._parent, model) + + raise AttributeError(f"Cannot find {model} id. Model._parent chain ends in {obj}") + + +def model_id(*models): + def decorator(f): + @functools.wraps(f) + def wrapper(self, *args, **kwargs): + outer_exc = None + for model in models: + key = f"{to_snake_case(model)}_id" + + if not args and key not in kwargs: + try: + kwargs[key] = find_model_id(self, model) + except AttributeError as exc: + outer_exc = exc + + try: + return f(self, *args, **kwargs) + except TypeError as exc: + raise exc from outer_exc + + return wrapper + + return decorator + + +def to_snake_case(s): + first = re.compile(r"(.)([A-Z][a-z]+)") + second = re.compile(r"([a-z0-9])([A-Z])") + repl = r"\1_\2" + + return second.sub(repl, first.sub(repl, s)).lower() From 3e367858cb4397758c69c2e4150c560966e677e7 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 26 Oct 2023 19:09:53 -0700 Subject: [PATCH 04/48] Implement `delattr` --- test/test_util.py | 2 +- welkin/models/base.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test_util.py b/test/test_util.py index e8cde7e..021194c 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -144,7 +144,7 @@ def test_find_model_id(client): assert find_model_id(patient, "Patient") == patient.id assert find_model_id(encounter, "Patient") == patient.id - patient.pop("id") + del patient.id encounter.patientId = "456" assert find_model_id(encounter, "Patient") == encounter.patientId diff --git a/welkin/models/base.py b/welkin/models/base.py index cc04598..a438c8c 100644 --- a/welkin/models/base.py +++ b/welkin/models/base.py @@ -45,6 +45,9 @@ def __getattr__(self, name): def __setattr__(self, name, value): super().__setitem__(name, value) + def __delattr__(self, name): + super().__delitem__(name) + def __str__(self): id = getattr(self, "id", "") From 8b50af11c81740a40416c40e0041ed8cf8b6adb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20D=C3=ADaz?= Date: Tue, 3 Oct 2023 11:14:30 -0700 Subject: [PATCH 05/48] temp commit --- .envrc | 1 + welkin/models/__init__.py | 10 ++++ welkin/models/patient.py | 4 ++ welkin/models/program.py | 108 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 .envrc create mode 100644 welkin/models/program.py diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..fe7c01a --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +dotenv diff --git a/welkin/models/__init__.py b/welkin/models/__init__.py index dbeb508..f797c98 100644 --- a/welkin/models/__init__.py +++ b/welkin/models/__init__.py @@ -19,6 +19,12 @@ from welkin.models.encounter import Encounter, EncounterDisposition, Encounters from welkin.models.formation import Formation from welkin.models.patient import Patient, Patients +from welkin.models.program import ( + CurrentPrograms, + Program, + ProgramHistory, + ProgramPhases, +) from welkin.models.sms import SMS, SMSes from welkin.models.user import User, Users @@ -36,6 +42,7 @@ "CDTs", "Chat", "Chats", + "CurrentPrograms", "DocumentSummaries", "DocumentSummary", "DocumentSummaryFile", @@ -48,6 +55,9 @@ "Formation", "Patient", "Patients", + "Program", + "ProgramHistory", + "ProgramPhases", "Schedules", "SearchChats", "SMS", diff --git a/welkin/models/patient.py b/welkin/models/patient.py index fea6592..43c7303 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -10,6 +10,7 @@ ) from welkin.models.email import Email, Emails from welkin.models.encounter import Encounter, Encounters +from welkin.models.program import CurrentPrograms, Program, ProgramHistory from welkin.models.sms import SMS, SMSes from welkin.pagination import PageableIterator @@ -23,6 +24,7 @@ class Patient(Resource): CDTs, Chat, Chats, + CurrentPrograms, DocumentSummaries, DocumentSummary, DocumentSummaryFile, @@ -30,6 +32,8 @@ class Patient(Resource): Emails, Encounter, Encounters, + Program, + ProgramHistory, SearchChats, SMS, SMSes, diff --git a/welkin/models/program.py b/welkin/models/program.py new file mode 100644 index 0000000..6fed059 --- /dev/null +++ b/welkin/models/program.py @@ -0,0 +1,108 @@ +from welkin.models.base import Collection, Resource +from welkin.models.util import find_patient_id_in_parents +from welkin.pagination import PageIterator + + +class ProgramPhases(Resource): + def _url(self, patient_id: str = None, program_name: str = None): + if not patient_id: + patient_id = find_patient_id_in_parents(self) + + if not program_name: + program_name = self._parent.name + + return f"{self._client.instance}/patients/{patient_id}/programs/{program_name}/phases" + + def update(self, phase_name: str, patient_id: str = None, program_name: str = None): + return super().patch( + self._url(patient_id, program_name), {"phaseName": phase_name} + ) + + +class Program(Resource): + subresources = [ProgramPhases] + + def _url(self, patient_id: str = None, program_name: str = None): + if not patient_id: + patient_id = find_patient_id_in_parents(self) + + if not program_name: + program_name = self.name + + return f"{self._client.instance}/patients/{patient_id}/programs/{program_name}" + + def delete(self, patient_id: str = None, program_name: str = None): + return super().delete(self._url(patient_id, program_name)) + + def update( + self, + patient_id: str = None, + program_name: str = None, + ): + return super().patch( + self._url(patient_id, program_name), + {"assigned": True, "status": "IN_PROGRESS"}, + ) + + +class CurrentPrograms(Collection): + resource = Program + iterator = PageIterator + + def _url(self, patient_id: str = None, program_name: str = None): + if not patient_id: + patient_id = find_patient_id_in_parents(self) + + if not program_name: + raise ValueError("A program name must be provided.") + + return f"{self._client.instance}/patients/{patient_id}/programs/current/{program_name}" + + def get( + self, + patient_id: str = None, + program_name: str = None, + assigned_programs: bool = None, + sort: str = None, + **kwargs, + ): + return super().get( + self._url(patient_id, program_name), + params={ + "assignedPrograms": assigned_programs, + "sort": sort, + }, + ) + + +class ProgramHistory(Resource): + resource = Program + iterator = PageIterator + + def _url(self, patient_id: str = None, program_id: str = None): + if not patient_id: + patient_id = find_patient_id_in_parents(self) + + if not program_id: + raise ValueError("A program ID must be provided.") + + return f"{self._client.instance}/patients/{patient_id}/programs/history/{program_id}" + + def get( + self, + patient_id: str = None, + program_id: str = None, + assigned_programs: bool = None, + sort: str = None, + ): + if not patient_id: + patient_id = find_patient_id_in_parents(self) + + params = { + "assignedPrograms": assigned_programs, + "sort": sort, + } + return super().get( + self._url(patient_id, program_id), + params=params, + ) From 5b3275f84db843d3144463fb1b5fd995e743121b Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 4 Oct 2023 17:06:46 -0700 Subject: [PATCH 06/48] Add Program formations --- .../TestFormation.test_program_read.yaml | 67 ++++++++++++++ .../TestFormation.test_programs_read.yaml | 89 +++++++++++++++++++ test/test_formation.py | 20 +++++ welkin/models/formation.py | 11 +++ 4 files changed, 187 insertions(+) create mode 100644 test/cassettes/TestFormation.test_program_read.yaml create mode 100644 test/cassettes/TestFormation.test_programs_read.yaml diff --git a/test/cassettes/TestFormation.test_program_read.yaml b/test/cassettes/TestFormation.test_program_read.yaml new file mode 100644 index 0000000..5e19883 --- /dev/null +++ b/test/cassettes/TestFormation.test_program_read.yaml @@ -0,0 +1,67 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_0c8270ba-29f2-44f3-b5cc-a804f4d9840f + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/formations/current/programs/prog-non-target-patient + response: + body: + string: '{"name": "prog-non-target-patient", "title": "Non-Target Patient", + "description": "All other non-target patients that do not meet the criteria + for other care plans.", "phases": [{"name": "start", "title": "Start", "type": + "START", "description": "", "autoFinishProgram": false, "navigateTo": [{"name": + "finish"}]}, {"name": "finish", "title": "Finish", "type": "FINISH", "description": + "", "autoFinishProgram": false, "navigateTo": []}], "nodes": [{"id": "start", + "data": {"label": "Start"}, "type": "graphNode", "position": {"x": 20, "y": + 20}}, {"id": "finish", "data": {"label": "Finish"}, "type": "graphNode", "position": + {"x": 1520, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_34f0e25d-bb67-4d65-9dd2-b7bca6e1bd73-finishHandleTargetLeft_4c1007b4-98fa-45fc-b64b-678f7fbc880a", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 05 Oct 2023 00:06:21 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '914' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/TestFormation.test_programs_read.yaml b/test/cassettes/TestFormation.test_programs_read.yaml new file mode 100644 index 0000000..dc0b7e5 --- /dev/null +++ b/test/cassettes/TestFormation.test_programs_read.yaml @@ -0,0 +1,89 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_5c7de3d2-1fe1-4a28-9a14-c1fe9fd0be66 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/formations/current/programs?page=0 + response: + body: + string: '[{"name": "prog-target-patient", "title": "Target Patient", "description": + "Moderate to severe patients, either on biologics or oral treatment.", "phases": + [{"name": "start", "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}]}, {"name": "finish", "title": "Finish", + "type": "FINISH", "description": "", "autoFinishProgram": false, "navigateTo": + []}], "nodes": [{"id": "start", "data": {"type": "START", "label": "Start"}, + "type": "graphNode", "position": {"x": 340, "y": 20}}, {"id": "finish", "data": + {"type": "FINISH", "label": "Finish"}, "type": "graphNode", "position": {"x": + 680, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_025adb09-c24a-45f9-b5a5-d1a44450ff43-finishHandleTargetLeft_5f5f5e64-5959-46b2-8e36-c85a86e60456", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-target-2-patient", "title": + "Target 2 Patient", "description": "Delayers - en route to top of treatment.", + "phases": [{"name": "start", "title": "Start", "type": "START", "description": + "", "autoFinishProgram": false, "navigateTo": [{"name": "finish"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}], "nodes": [{"id": "start", "data": {"label": "Start"}, + "type": "graphNode", "position": {"x": 20, "y": 20}}, {"id": "finish", "data": + {"type": "FINISH", "label": "Finish"}, "type": "graphNode", "position": {"x": + 300, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_713b0fea-09cb-4c09-98da-bcb71c6cc9e5-finishHandleTargetLeft_d0fe8672-eafd-4b25-98b8-8845e89953a8", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-non-target-patient", "title": + "Non-Target Patient", "description": "All other non-target patients that do + not meet the criteria for other care plans.", "phases": [{"name": "start", + "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}]}, {"name": "finish", "title": "Finish", + "type": "FINISH", "description": "", "autoFinishProgram": false, "navigateTo": + []}], "nodes": [{"id": "start", "data": {"label": "Start"}, "type": "graphNode", + "position": {"x": 20, "y": 20}}, {"id": "finish", "data": {"label": "Finish"}, + "type": "graphNode", "position": {"x": 1520, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_34f0e25d-bb67-4d65-9dd2-b7bca6e1bd73-finishHandleTargetLeft_4c1007b4-98fa-45fc-b64b-678f7fbc880a", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}]' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 05 Oct 2023 00:05:14 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '2725' + status: + code: 200 + message: OK +version: 1 diff --git a/test/test_formation.py b/test/test_formation.py index a2eb71e..953c443 100644 --- a/test/test_formation.py +++ b/test/test_formation.py @@ -13,6 +13,8 @@ Formation, Goal, Goals, + Program, + Programs, ) @@ -121,3 +123,21 @@ def test_goal_read(self, formation, vcr_cassette): assert goal_template.name == "eat-fruit" assert len(vcr_cassette) == 1 + + @pytest.mark.vcr + def test_programs_read(self, formation, vcr_cassette): + programs = formation.Programs().get() + + assert isinstance(programs, Programs) + assert isinstance(programs[0], Program) + + assert len(vcr_cassette) == 1 + + @pytest.mark.vcr + def test_program_read(self, formation, vcr_cassette): + programs = formation.Program(name="prog-non-target-patient").get() + + assert isinstance(programs, Program) + assert programs.name == "prog-non-target-patient" + + assert len(vcr_cassette) == 1 diff --git a/welkin/models/formation.py b/welkin/models/formation.py index 8b88294..699dc49 100644 --- a/welkin/models/formation.py +++ b/welkin/models/formation.py @@ -92,6 +92,15 @@ class Goals(FormationCollection): endpoint = "goal-templates" +class Program(FormationResource): + endpoint = "programs" + + +class Programs(FormationCollection): + resource = Program + endpoint = "programs" + + class Formation(Target): Assessment = Assessment Assessments = Assessments @@ -104,6 +113,8 @@ class Formation(Target): Encounters = Encounters Goal = Goal Goals = Goals + Program = Program + Programs = Programs def __init__(self, version: Union[int, str] = "current"): super().__init__() From 96dab5e14bcabf985a960369123f69eece04f3fe Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 08:41:54 -0700 Subject: [PATCH 07/48] WIP --- welkin/client.py | 3 ++ welkin/models/__init__.py | 11 ++-- welkin/models/patient.py | 5 +- welkin/models/program.py | 111 ++++++++++++-------------------------- 4 files changed, 42 insertions(+), 88 deletions(-) diff --git a/welkin/client.py b/welkin/client.py index dc51d46..cddb0f8 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -94,6 +94,9 @@ class Client(Session): Formation = models.Formation Patient = models.Patient Patients = models.Patients + Program = models.Program + ProgramPhase = models.ProgramPhase + Programs = models.Programs Schedules = models.Schedules SearchChats = models.SearchChats SMS = models.SMS diff --git a/welkin/models/__init__.py b/welkin/models/__init__.py index f797c98..ba2ac01 100644 --- a/welkin/models/__init__.py +++ b/welkin/models/__init__.py @@ -19,12 +19,7 @@ from welkin.models.encounter import Encounter, EncounterDisposition, Encounters from welkin.models.formation import Formation from welkin.models.patient import Patient, Patients -from welkin.models.program import ( - CurrentPrograms, - Program, - ProgramHistory, - ProgramPhases, -) +from welkin.models.program import Program, ProgramPhase, Programs from welkin.models.sms import SMS, SMSes from welkin.models.user import User, Users @@ -56,8 +51,8 @@ "Patient", "Patients", "Program", - "ProgramHistory", - "ProgramPhases", + "Programs", + "ProgramPhase", "Schedules", "SearchChats", "SMS", diff --git a/welkin/models/patient.py b/welkin/models/patient.py index 43c7303..9832792 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -10,7 +10,7 @@ ) from welkin.models.email import Email, Emails from welkin.models.encounter import Encounter, Encounters -from welkin.models.program import CurrentPrograms, Program, ProgramHistory +from welkin.models.program import Program, Programs from welkin.models.sms import SMS, SMSes from welkin.pagination import PageableIterator @@ -24,7 +24,7 @@ class Patient(Resource): CDTs, Chat, Chats, - CurrentPrograms, + Programs, DocumentSummaries, DocumentSummary, DocumentSummaryFile, @@ -33,7 +33,6 @@ class Patient(Resource): Encounter, Encounters, Program, - ProgramHistory, SearchChats, SMS, SMSes, diff --git a/welkin/models/program.py b/welkin/models/program.py index 6fed059..84fc88c 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -1,108 +1,65 @@ from welkin.models.base import Collection, Resource -from welkin.models.util import find_patient_id_in_parents from welkin.pagination import PageIterator +from welkin.util import model_id -class ProgramPhases(Resource): - def _url(self, patient_id: str = None, program_name: str = None): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - - if not program_name: - program_name = self._parent.name - - return f"{self._client.instance}/patients/{patient_id}/programs/{program_name}/phases" - - def update(self, phase_name: str, patient_id: str = None, program_name: str = None): +class ProgramPhase(Resource): + @model_id("Patient") + def update(self, patient_id: str, program_name: str = None, **kwargs): + program_name = program_name or self._parent.name return super().patch( - self._url(patient_id, program_name), {"phaseName": phase_name} + f"{self._client.instance}/patients/{patient_id}/programs/" + f"{program_name or self._parent.name}/phases", + kwargs, ) class Program(Resource): - subresources = [ProgramPhases] - - def _url(self, patient_id: str = None, program_name: str = None): - if not patient_id: - patient_id = find_patient_id_in_parents(self) + subresources = [ProgramPhase] - if not program_name: - program_name = self.name - - return f"{self._client.instance}/patients/{patient_id}/programs/{program_name}" - - def delete(self, patient_id: str = None, program_name: str = None): - return super().delete(self._url(patient_id, program_name)) + @model_id("Patient") + def delete(self, patient_id: str): + return super().delete( + f"{self._client.instance}/patients/{patient_id}/programs/{self.name}" + ) - def update( - self, - patient_id: str = None, - program_name: str = None, - ): + @model_id("Patient") + def update(self, patient_id: str, **kwargs): return super().patch( - self._url(patient_id, program_name), - {"assigned": True, "status": "IN_PROGRESS"}, + f"{self._client.instance}/patients/{patient_id}/programs/{self.name}", + kwargs, ) -class CurrentPrograms(Collection): +class Programs(Collection): resource = Program iterator = PageIterator - def _url(self, patient_id: str = None, program_name: str = None): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - - if not program_name: - raise ValueError("A program name must be provided.") - - return f"{self._client.instance}/patients/{patient_id}/programs/current/{program_name}" - + @model_id("Patient") def get( self, - patient_id: str = None, - program_name: str = None, + patient_id: str, assigned_programs: bool = None, sort: str = None, + *args, **kwargs, ): - return super().get( - self._url(patient_id, program_name), - params={ - "assignedPrograms": assigned_programs, - "sort": sort, - }, - ) - - -class ProgramHistory(Resource): - resource = Program - iterator = PageIterator - - def _url(self, patient_id: str = None, program_id: str = None): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - - if not program_id: - raise ValueError("A program ID must be provided.") - - return f"{self._client.instance}/patients/{patient_id}/programs/history/{program_id}" - - def get( - self, - patient_id: str = None, - program_id: str = None, - assigned_programs: bool = None, - sort: str = None, - ): - if not patient_id: - patient_id = find_patient_id_in_parents(self) - params = { "assignedPrograms": assigned_programs, "sort": sort, } + + path = f"{self._client.instance}/patients/{patient_id}/programs" + if hasattr(self, "programName"): + path = f"{path}/current/{self.programName}" + elif hasattr(self, "id"): + path = f"{path}/history/{self.id}" + else: + raise AttributeError + return super().get( - self._url(patient_id, program_id), + path, params=params, + *args, + **kwargs, ) From 690031d1021689b8cee62f5f7d57657f27bd3616 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 09:34:21 -0700 Subject: [PATCH 08/48] Remove decorators --- welkin/models/program.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/welkin/models/program.py b/welkin/models/program.py index 84fc88c..7076faa 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -1,12 +1,13 @@ from welkin.models.base import Collection, Resource +from welkin.models.util import find_patient_id_in_parents from welkin.pagination import PageIterator -from welkin.util import model_id class ProgramPhase(Resource): - @model_id("Patient") - def update(self, patient_id: str, program_name: str = None, **kwargs): + def update(self, patient_id: str = None, program_name: str = None, **kwargs): + patient_id = patient_id or find_patient_id_in_parents(self) program_name = program_name or self._parent.name + return super().patch( f"{self._client.instance}/patients/{patient_id}/programs/" f"{program_name or self._parent.name}/phases", @@ -17,17 +18,19 @@ def update(self, patient_id: str, program_name: str = None, **kwargs): class Program(Resource): subresources = [ProgramPhase] - @model_id("Patient") - def delete(self, patient_id: str): + def delete(self, patient_id: str = None): + patient_id = patient_id or find_patient_id_in_parents(self) + return super().delete( f"{self._client.instance}/patients/{patient_id}/programs/{self.name}" ) - @model_id("Patient") - def update(self, patient_id: str, **kwargs): + def update(self, patient_id: str = None, **kwargs): + patient_id = patient_id or find_patient_id_in_parents(self) + return super().patch( f"{self._client.instance}/patients/{patient_id}/programs/{self.name}", - kwargs, + **kwargs, ) @@ -35,15 +38,15 @@ class Programs(Collection): resource = Program iterator = PageIterator - @model_id("Patient") def get( self, - patient_id: str, + patient_id: str = None, assigned_programs: bool = None, sort: str = None, *args, **kwargs, ): + patient_id = patient_id or find_patient_id_in_parents(self) params = { "assignedPrograms": assigned_programs, "sort": sort, @@ -51,11 +54,11 @@ def get( path = f"{self._client.instance}/patients/{patient_id}/programs" if hasattr(self, "programName"): - path = f"{path}/current/{self.programName}" + path += f"/current/{self.programName}" elif hasattr(self, "id"): - path = f"{path}/history/{self.id}" + path += f"/history/{self.id}" else: - raise AttributeError + raise AttributeError("At least one of programName or id must be set.") return super().get( path, From c30f2175e780e728a64938a99d2c6374cb84845e Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 10:59:16 -0700 Subject: [PATCH 09/48] Fix bug in `find_model_id` and improve docs --- poetry.lock | 13 ++++++- pyproject.toml | 1 + test/test_util.py | 4 ++- welkin/util.py | 86 ++++++++++++++++++++++++++++++++++++----------- 4 files changed, 82 insertions(+), 22 deletions(-) diff --git a/poetry.lock b/poetry.lock index fe390e8..58e0745 100644 --- a/poetry.lock +++ b/poetry.lock @@ -367,6 +367,17 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker perf = ["ipython"] testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +[[package]] +name = "inflection" +version = "0.5.1" +description = "A port of Ruby on Rails inflector to Python" +optional = false +python-versions = ">=3.5" +files = [ + {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, + {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -1505,4 +1516,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "bc16e9c8d9b067e6cee6870a30473e74a8c641305f5da551b9157f96c1546bee" +content-hash = "e29038a3548768e3be7cc1bce96c0170325667dff52ebf2126f63536fbd82e0f" diff --git a/pyproject.toml b/pyproject.toml index 3ab7e97..909700d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ classifiers = [ python = "^3.7" requests = "^2.28.1" portalocker = "^2.7.0" +inflection = "^0.5.1" [tool.poetry.group.dev] optional = true diff --git a/test/test_util.py b/test/test_util.py index 021194c..4f58f19 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -10,6 +10,7 @@ clean_request_params, clean_request_payload, find_model_id, + to_camel_case, to_snake_case, ) @@ -129,7 +130,8 @@ def test_clean_datetime(dt, expected, request): "FOOBar", ], ) -def test_to_snake_case(input): +def test_case_converters(input): + assert to_camel_case(input) == "fooBar" assert to_snake_case(input) == "foo_bar" diff --git a/welkin/util.py b/welkin/util.py index 4424dd8..c92cdc5 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,10 +1,12 @@ -import functools -import re from datetime import date, datetime, timezone +from functools import cache, wraps +from types import FunctionType from typing import Any from uuid import UUID -from welkin.models.base import SchemaBase +import inflection + +from welkin.models.base import Collection, Resource, SchemaBase # NOTE: `clean_request_payload` and `clean_request_params` are intentionally DRY # violations. The code may be the same, but they represent different knowledge. @@ -111,21 +113,46 @@ def clean_datetime(dt: datetime) -> str: ) -def find_model_id(obj, model: str): - if obj.__class__.__name__ == model: - return obj.id - elif hasattr(obj, f"{to_snake_case(model)}Id"): - return obj.patientId - elif obj._parent: - return find_model_id(obj._parent, model) +def find_model_id(instance: Collection | Resource, model_name: str) -> str: + """Recursively traverse the `_parent` chain searching for a model id. - raise AttributeError(f"Cannot find {model} id. Model._parent chain ends in {obj}") + Args: + instance (Collection | Resource): The instanceect instance to inspect. + model_name (str): The class name of the model to find. + Raises: + AttributeError: If recursion ends without finding the model id. -def model_id(*models): - def decorator(f): - @functools.wraps(f) - def wrapper(self, *args, **kwargs): + Returns: + str: The model id. + """ + body_id_key = f"{to_camel_case(model_name)}Id" + + if instance.__class__.__name__ == model_name: + return instance.id + elif hasattr(instance, body_id_key): + return getattr(instance, body_id_key) + elif instance._parent: + return find_model_id(instance._parent, model_name) + + raise AttributeError( + f"Cannot find {model_name} id. Model._parent chain ends in {instance}" + ) + + +def model_id(*models: tuple[str]) -> FunctionType: + """Insert values for `model_id` arguments if not provided. + + Args: + *models (tuple[str]): The model names to search for. + + Raises: + TypeError: If no ID is found and no arguments are provided. + """ + + def decorator(f: FunctionType): + @wraps(f) + def wrapper(self, *args, **kwargs) -> FunctionType: outer_exc = None for model in models: key = f"{to_snake_case(model)}_id" @@ -139,6 +166,7 @@ def wrapper(self, *args, **kwargs): try: return f(self, *args, **kwargs) except TypeError as exc: + # Raise from the outer `AttributeError` so we don't lose context. raise exc from outer_exc return wrapper @@ -146,9 +174,27 @@ def wrapper(self, *args, **kwargs): return decorator -def to_snake_case(s): - first = re.compile(r"(.)([A-Z][a-z]+)") - second = re.compile(r"([a-z0-9])([A-Z])") - repl = r"\1_\2" +@cache +def to_camel_case(s: str) -> str: + """Convert a string to camelCase. + + Args: + s (str): The string to convert. + + Returns: + str: The converted camelCase string. + """ + return inflection.camelize(to_snake_case(s), uppercase_first_letter=False) + + +@cache +def to_snake_case(s: str) -> str: + """Convert a string to snake_case. + + Args: + s (str): The string to convert. - return second.sub(repl, first.sub(repl, s)).lower() + Returns: + str: The converted snake_case string. + """ + return inflection.underscore(s) From 0cee0966c864d84887632adab1ca2a6606d946fc Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 11:02:48 -0700 Subject: [PATCH 10/48] Fix type hint for backwards-compatibility --- welkin/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/welkin/util.py b/welkin/util.py index c92cdc5..1d5e151 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,7 +1,7 @@ from datetime import date, datetime, timezone from functools import cache, wraps from types import FunctionType -from typing import Any +from typing import Any, Union from uuid import UUID import inflection @@ -113,7 +113,7 @@ def clean_datetime(dt: datetime) -> str: ) -def find_model_id(instance: Collection | Resource, model_name: str) -> str: +def find_model_id(instance: Union[Collection, Resource], model_name: str) -> str: """Recursively traverse the `_parent` chain searching for a model id. Args: From d6a7a665cd58599866490bb054321d721c9d0e64 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 11:05:45 -0700 Subject: [PATCH 11/48] Fix cache for older versions of Python --- welkin/util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/welkin/util.py b/welkin/util.py index 1d5e151..73b4358 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,5 +1,5 @@ from datetime import date, datetime, timezone -from functools import cache, wraps +from functools import lru_cache, wraps from types import FunctionType from typing import Any, Union from uuid import UUID @@ -174,7 +174,7 @@ def wrapper(self, *args, **kwargs) -> FunctionType: return decorator -@cache +@lru_cache(maxsize=None) def to_camel_case(s: str) -> str: """Convert a string to camelCase. @@ -187,7 +187,7 @@ def to_camel_case(s: str) -> str: return inflection.camelize(to_snake_case(s), uppercase_first_letter=False) -@cache +@lru_cache(maxsize=None) def to_snake_case(s: str) -> str: """Convert a string to snake_case. From e1f854a7189445216a574980b5f0b62f60572cca Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 11:10:41 -0700 Subject: [PATCH 12/48] Fix type annotation for function --- welkin/util.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/welkin/util.py b/welkin/util.py index 73b4358..5bc48ad 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,7 +1,6 @@ from datetime import date, datetime, timezone from functools import lru_cache, wraps -from types import FunctionType -from typing import Any, Union +from typing import Any, Callable, Union from uuid import UUID import inflection @@ -140,7 +139,7 @@ def find_model_id(instance: Union[Collection, Resource], model_name: str) -> str ) -def model_id(*models: tuple[str]) -> FunctionType: +def model_id(*models: tuple[str]) -> Callable: """Insert values for `model_id` arguments if not provided. Args: @@ -150,9 +149,9 @@ def model_id(*models: tuple[str]) -> FunctionType: TypeError: If no ID is found and no arguments are provided. """ - def decorator(f: FunctionType): + def decorator(f: Callable): @wraps(f) - def wrapper(self, *args, **kwargs) -> FunctionType: + def wrapper(self, *args, **kwargs) -> Callable: outer_exc = None for model in models: key = f"{to_snake_case(model)}_id" From e4eefb362ec8f443245e53de1116b3bf856da1ac Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 11:18:40 -0700 Subject: [PATCH 13/48] Fix another type annotation --- welkin/util.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/welkin/util.py b/welkin/util.py index 5bc48ad..2817c3d 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,6 +1,6 @@ from datetime import date, datetime, timezone from functools import lru_cache, wraps -from typing import Any, Callable, Union +from typing import Any, Callable, Tuple, Union from uuid import UUID import inflection @@ -116,7 +116,7 @@ def find_model_id(instance: Union[Collection, Resource], model_name: str) -> str """Recursively traverse the `_parent` chain searching for a model id. Args: - instance (Collection | Resource): The instanceect instance to inspect. + instance (Union[Collection, Resource]): The instanceect instance to inspect. model_name (str): The class name of the model to find. Raises: @@ -139,11 +139,11 @@ def find_model_id(instance: Union[Collection, Resource], model_name: str) -> str ) -def model_id(*models: tuple[str]) -> Callable: +def model_id(*models: Tuple[str]) -> Callable: """Insert values for `model_id` arguments if not provided. Args: - *models (tuple[str]): The model names to search for. + *models (Tuple[str]): The model names to search for. Raises: TypeError: If no ID is found and no arguments are provided. From b451953da6bbaa8e60684d68ea000e7802bdda6d Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 12:13:02 -0700 Subject: [PATCH 14/48] Chain all `AttributeErrors` for better traceback --- welkin/util.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/welkin/util.py b/welkin/util.py index 2817c3d..c6a439b 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -159,8 +159,11 @@ def wrapper(self, *args, **kwargs) -> Callable: if not args and key not in kwargs: try: kwargs[key] = find_model_id(self, model) - except AttributeError as exc: - outer_exc = exc + except AttributeError as e: + try: + raise e from outer_exc + except AttributeError as exc: + outer_exc = exc try: return f(self, *args, **kwargs) From 4a00a2377b703a5561cd2bef4f5131382a6ce932 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 12:29:12 -0700 Subject: [PATCH 15/48] Fix parent recursion --- welkin/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/welkin/util.py b/welkin/util.py index c6a439b..05ae8b7 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -131,7 +131,7 @@ def find_model_id(instance: Union[Collection, Resource], model_name: str) -> str return instance.id elif hasattr(instance, body_id_key): return getattr(instance, body_id_key) - elif instance._parent: + elif instance._parent is not None: return find_model_id(instance._parent, model_name) raise AttributeError( From 3a32fd4c45fa1123e2469fe4b3f5d1ecf2a25ca5 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 15:37:02 -0700 Subject: [PATCH 16/48] Clean up paths --- welkin/models/assessment.py | 7 ++++--- welkin/models/encounter.py | 23 ++++++++--------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/welkin/models/assessment.py b/welkin/models/assessment.py index e37f615..9f58276 100644 --- a/welkin/models/assessment.py +++ b/welkin/models/assessment.py @@ -94,6 +94,7 @@ class AssessmentRecords(Collection): @model_id("Patient") def get(self, patient_id: str, **kwargs): - path = f"{self._client.instance}/patients/{patient_id}/assessment-records" - - return super().get(path, **kwargs) + return super().get( + f"{self._client.instance}/patients/{patient_id}/assessment-records", + **kwargs, + ) diff --git a/welkin/models/encounter.py b/welkin/models/encounter.py index 5b576e8..49255e9 100644 --- a/welkin/models/encounter.py +++ b/welkin/models/encounter.py @@ -80,24 +80,17 @@ def get( *args, **kwargs, ): - root = "" + path = f"{self._client.instance}/" if patient_id: - root = f"patients/{patient_id}" + path += f"patients/{patient_id}/" elif user_id: - root = f"users/{user_id}" - elif self._parent: - if self._parent.__class__.__name__ == "Patient": - root = f"patients/{self._parent.id}" - elif self._parent.__class__.__name__ == "User": - root = f"users/{self._parent.id}" + path += f"users/{user_id}/" + elif self._parent.__class__.__name__ == "Patient": + path += f"patients/{self._parent.id}/" + elif self._parent.__class__.__name__ == "User": + path += f"users/{self._parent.id}/" - encounters = "encounters" - if related_data: - encounters = "full-encounters" - - path = f"{self._client.instance}/{encounters}" - if root: - path = f"{self._client.instance}/{root}/{encounters}" + path += "full-encounters" if related_data else "encounters" params = { "withCareTeam": with_care_team, From 54417f890f37f66deee5cd779bf77ca5ea093499 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 16:21:04 -0700 Subject: [PATCH 17/48] Add dynamic patient fixture --- test/conftest.py | 20 ++++++++++++++++++++ welkin/models/__init__.py | 1 - welkin/models/patient.py | 24 ++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 0ee1327..2d940dc 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -2,11 +2,13 @@ import os import uuid from datetime import date, datetime, time, timedelta, timezone +from http import HTTPStatus from uuid import uuid4 import pytest from welkin import Client +from welkin.exceptions import WelkinHTTPError def pytest_collection_modifyitems(items): @@ -107,6 +109,24 @@ def hook(dct): return hook +@pytest.fixture +def patient(client): + patient = client.Patient( + firstName="Test", + lastName="Patient", + email="test.patient@example.com", + externalGuid=uuid.UUID("12345678-1234-1234-1234-1234567890ab"), + ) + + try: + return patient.get() + except WelkinHTTPError as exc: + if exc.response.status_code != HTTPStatus.NOT_FOUND: + raise + + return patient.create() + + @pytest.fixture def base_date(): return date(year=2022, month=9, day=15) diff --git a/welkin/models/__init__.py b/welkin/models/__init__.py index ba2ac01..893c661 100644 --- a/welkin/models/__init__.py +++ b/welkin/models/__init__.py @@ -37,7 +37,6 @@ "CDTs", "Chat", "Chats", - "CurrentPrograms", "DocumentSummaries", "DocumentSummary", "DocumentSummaryFile", diff --git a/welkin/models/patient.py b/welkin/models/patient.py index 9832792..609c11e 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -41,8 +41,28 @@ class Patient(Resource): def create(self): return super().post(f"{self._client.instance}/patients") - def get(self): - return super().get(f"{self._client.instance}/patients/{self.id}") + def get(self, expand: bool = None): + _id = None + if hasattr(self, "id"): + type = None + _id = self.id + elif hasattr(self, "externalId"): + type = "EID" + _id = self.externalId + elif hasattr(self, "externalGuid"): + type = "EGUID" + _id = self.externalGuid + elif hasattr(self, "mrn"): + type = "MRN" + _id = self.mrn + + return super().get( + f"{self._client.instance}/patients/{_id}", + params={ + "type": type, + expand: expand, + }, + ) def update(self, **kwargs): return super().patch(f"{self._client.instance}/patients/{self.id}", kwargs) From eaf20c937b8d4d05ec4f94e45614ab259d31ebd0 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 27 Oct 2023 17:15:31 -0700 Subject: [PATCH 18/48] WIP - `Program` read tested --- .../fixtures/patient__test_program_read.yaml | 70 +++ test/cassettes/test_program_read.yaml | 407 ++++++++++++++++++ test/conftest.py | 18 +- test/test_program.py | 62 +++ welkin/client.py | 1 - welkin/models/__init__.py | 3 +- welkin/models/patient.py | 3 +- welkin/models/program.py | 46 +- welkin/models/util.py | 2 +- 9 files changed, 574 insertions(+), 38 deletions(-) create mode 100644 test/cassettes/fixtures/patient__test_program_read.yaml create mode 100644 test/cassettes/test_program_read.yaml create mode 100644 test/test_program.py diff --git a/test/cassettes/fixtures/patient__test_program_read.yaml b/test/cassettes/fixtures/patient__test_program_read.yaml new file mode 100644 index 0000000..b92f301 --- /dev/null +++ b/test/cassettes/fixtures/patient__test_program_read.yaml @@ -0,0 +1,70 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_35e1fe22-32fa-4b05-abbf-bc5d1fb46440 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/12345678-1234-1234-1234-1234567890ab?type=EGUID + response: + body: + string: '{"createdByName": "createdByName_REDACTED_1843844d-59a3-4e88-ba9a-7935ee896082", + "lastName": "Patient", "country": null, "secondaryEmail": null, "gender": + "UNKNOWN", "city": null, "timezone": null, "careTeamMembers": [], "secondaryPhoneCapabilities": + [], "createdAt": "2023-10-27T23:19:20.506Z", "accessCode": null, "addressLine1": + null, "addressLine2": null, "id": "de5e1a93-70b0-4ed4-868f-3854becc383c", + "state": null, "secondaryLanguage": null, "email": "test.patient@example.com", + "careTeam": [], "updatedAt": "2023-10-27T23:19:20.506Z", "primaryPhoneCapabilities": + [], "pointOfContact": null, "zip": null, "updatedBy": "updatedBy_REDACTED_c9f6370a-e068-441c-91c4-9ce5421a9887", + "preferableInstancePhoneId": null, "updatedByName": "updatedByName_REDACTED_87c90d81-8a1a-4a09-855c-710cc5fe5ca5", + "mrn": null, "externalId": null, "externalGuid": "12345678-1234-1234-1234-1234567890ab", + "patientPrograms": [], "nric": null, "birthDate": null, "cadence": [], "firstName": + "Test", "patientRegionTitle": null, "createdBy": "createdBy_REDACTED_7ffa726b-0d5e-4c2c-8f68-4a1af1b6e38b", + "phone": null, "middleName": null, "patientTerritories": [], "patientRegion": + null, "maritalStatus": "UKN", "primaryLanguage": "ENGLISH", "secondaryPhone": + null, "patientTerritory": null}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Fri, 27 Oct 2023 23:34:52 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '1071' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/test_program_read.yaml b/test/cassettes/test_program_read.yaml new file mode 100644 index 0000000..960ecea --- /dev/null +++ b/test/cassettes/test_program_read.yaml @@ -0,0 +1,407 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/formations/current/programs?page=0 + response: + body: + string: '[{"name": "prog-target-patient", "title": "Target Patient", "description": + "Moderate to severe patients, either on biologics or oral treatment.", "phases": + [{"name": "start", "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}, {"name": "continuing-old-treatment"}, + {"name": "stopping-old-treatment"}, {"name": "consent-requested"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "records-requested", "title": "Records + Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": false, + "navigateTo": [{"name": "records-received"}]}, {"name": "records-received", + "title": "Records Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "starting-new-treatment", "title": "Starting + New Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, + {"name": "continuing-old-treatment", "title": "Continuing Old Treatment", + "type": "DEFAULT", "description": "", "autoFinishProgram": false, "navigateTo": + [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, {"name": + "prior-auth-requested", "title": "Prior Auth Requested", "type": "DEFAULT", + "description": "", "autoFinishProgram": false, "navigateTo": [{"name": "prior-auth-approved"}, + {"name": "prior-auth-abandoned"}]}, {"name": "prior-auth-approved", "title": + "Prior Auth Approved", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "sent-to-pharmacy"}]}, {"name": "prior-auth-abandoned", + "title": "Prior Auth Abandoned", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-approved"}]}, {"name": "sent-to-pharmacy", + "title": "Sent to Pharmacy", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "confirmed-patient-filled"}]}, {"name": "confirmed-patient-filled", + "title": "Confirmed Patient Filled", "type": "DEFAULT", "description": "", + "autoFinishProgram": false, "navigateTo": []}, {"name": "stopping-old-treatment", + "title": "Stopping Old Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "starting-new-treatment"}]}, {"name": "consent-requested", + "title": "Consent Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "consent-received"}]}, {"name": "consent-received", + "title": "Consent Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "records-requested"}]}], "nodes": [{"id": "start", + "data": {"type": "START", "label": "Start"}, "type": "graphNode", "position": + {"x": 340, "y": 20}}, {"id": "finish", "data": {"type": "FINISH", "label": + "Finish"}, "type": "graphNode", "position": {"x": 1120, "y": 20}}, {"id": + "reactflow__edge-startHandleSrcRight_025adb09-c24a-45f9-b5a5-d1a44450ff43-finishHandleTargetLeft_5f5f5e64-5959-46b2-8e36-c85a86e60456", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}, {"id": "records-requested", "data": {"type": + "DEFAULT", "label": "Records Requested"}, "type": "graphNode", "position": + {"x": 800, "y": -40}}, {"id": "records-received", "data": {"type": "DEFAULT", + "label": "Records Received"}, "type": "graphNode", "position": {"x": 980, + "y": -40}}, {"id": "starting-new-treatment", "data": {"type": "DEFAULT", "label": + "Starting New Treatment"}, "type": "graphNode", "position": {"x": 640, "y": + 80}}, {"id": "continuing-old-treatment", "data": {"type": "DEFAULT", "label": + "Continuing Old Treatment"}, "type": "graphNode", "position": {"x": 440, "y": + 140}}, {"id": "prior-auth-requested", "data": {"type": "DEFAULT", "label": + "Prior Auth Requested"}, "type": "graphNode", "position": {"x": 660, "y": + 160}}, {"id": "prior-auth-approved", "data": {"type": "DEFAULT", "label": + "Prior Auth Approved"}, "type": "graphNode", "position": {"x": 840, "y": 160}}, + {"id": "prior-auth-abandoned", "data": {"type": "DEFAULT", "label": "Prior + Auth Abandoned"}, "type": "graphNode", "position": {"x": 760, "y": 220}}, + {"id": "sent-to-pharmacy", "data": {"type": "DEFAULT", "label": "Sent to Pharmacy"}, + "type": "graphNode", "position": {"x": 860, "y": 80}}, {"id": "confirmed-patient-filled", + "data": {"type": "DEFAULT", "label": "Confirmed Patient Filled"}, "type": + "graphNode", "position": {"x": 1020, "y": 80}}, {"id": "reactflow__edge-records-requestedHandleSrcRight_6672da4b-34f4-42fb-81b3-5d7e785c5e1d-records-receivedHandleTargetLeft_1c3c44da-11c5-4da6-9e79-94f1eb86a5c5", + "type": "smoothstep", "source": "records-requested", "target": "records-received", + "animated": true, "sourceHandle": "HandleSrcRight_records-requested", "targetHandle": + "HandleTargetLeft_records-received", "arrowHeadType": "arrowclosed"}, {"id": + "stopping-old-treatment", "data": {"type": "DEFAULT", "label": "Stopping Old + Treatment"}, "type": "graphNode", "position": {"x": 440, "y": 80}}, {"id": + "reactflow__edge-stopping-old-treatmentHandleSrcRight_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36-starting-new-treatmentHandleTargetLeft_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6", + "type": "smoothstep", "source": "stopping-old-treatment", "target": "starting-new-treatment", + "animated": true, "sourceHandle": "HandleSrcRight_stopping-old-treatment", + "targetHandle": "HandleTargetLeft_starting-new-treatment", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-starting-new-treatmentHandleSrcBottom_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-prior-auth-requestedHandleTargetTop_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "starting-new-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcBottom_starting-new-treatment", + "targetHandle": "HandleTargetTop_prior-auth-requested", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcRight_40cd6e6c-c21c-45bf-b94c-62092b2b2510-prior-auth-requestedHandleTargetLeft_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcRight_continuing-old-treatment", + "targetHandle": "HandleTargetLeft_prior-auth-requested", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-requestedHandleSrcRight_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-approvedHandleTargetLeft_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcRight_prior-auth-requested", "targetHandle": + "HandleTargetLeft_prior-auth-approved", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-sent-to-pharmacyHandleSrcRight_e1ad3528-270a-45bf-9757-91fe3ecb9d23-confirmed-patient-filledHandleTargetLeft_2505253d-32d6-4020-8e16-722b4813a5a7", + "type": "smoothstep", "source": "sent-to-pharmacy", "target": "confirmed-patient-filled", + "animated": true, "sourceHandle": "HandleSrcRight_sent-to-pharmacy", "targetHandle": + "HandleTargetLeft_confirmed-patient-filled", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-starting-new-treatmentHandleSrcRight_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-sent-to-pharmacyHandleTargetLeft_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "starting-new-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcRight_starting-new-treatment", + "targetHandle": "HandleTargetLeft_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-requestedHandleSrcBottom_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-abandonedHandleTargetLeft_982c7e02-2cce-4202-b72c-bee08f44e11a", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-abandoned", + "animated": true, "sourceHandle": "HandleSrcBottom_prior-auth-requested", + "targetHandle": "HandleTargetLeft_prior-auth-abandoned", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-abandonedHandleSrcTop_982c7e02-2cce-4202-b72c-bee08f44e11a-prior-auth-approvedHandleTargetBottom_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-abandoned", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-abandoned", "targetHandle": + "HandleTargetBottom_prior-auth-approved", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcTop_40cd6e6c-c21c-45bf-b94c-62092b2b2510-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_continuing-old-treatment", + "targetHandle": "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-stopping-old-treatmentHandleTargetLeft_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36", + "type": "smoothstep", "source": "start", "target": "stopping-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_stopping-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-continuing-old-treatmentHandleTargetLeft_40cd6e6c-c21c-45bf-b94c-62092b2b2510", + "type": "smoothstep", "source": "start", "target": "continuing-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_continuing-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-approvedHandleSrcTop_7d04e809-9419-4673-800b-ea2c3d7c04aa-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "prior-auth-approved", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-approved", "targetHandle": + "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, {"id": + "consent-requested", "data": {"type": "DEFAULT", "label": "Consent Requested"}, + "type": "graphNode", "position": {"x": 460, "y": -40}}, {"id": "consent-received", + "data": {"type": "DEFAULT", "label": "Consent Received"}, "type": "graphNode", + "position": {"x": 640, "y": -40}}, {"id": "reactflow__edge-consent-receivedHandleSrcRight_2e7445fb-8611-43bd-b750-af720c1530c1-records-requestedHandleTargetLeft_99edae56-fbb6-4bd5-95d0-a02e8b53c097", + "type": "smoothstep", "source": "consent-received", "target": "records-requested", + "animated": true, "sourceHandle": "HandleSrcRight_consent-received", "targetHandle": + "HandleTargetLeft_records-requested", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-consent-requestedHandleSrcRight_b56feb59-d9ad-46e7-8741-a20ad73112b7-consent-receivedHandleTargetLeft_2e7445fb-8611-43bd-b750-af720c1530c1", + "type": "smoothstep", "source": "consent-requested", "target": "consent-received", + "animated": true, "sourceHandle": "HandleSrcRight_consent-requested", "targetHandle": + "HandleTargetLeft_consent-received", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-startHandleSrcTop_712c1b68-4ccd-4f94-8641-5721b6148ed8-consent-requestedHandleTargetLeft_b56feb59-d9ad-46e7-8741-a20ad73112b7", + "type": "smoothstep", "source": "start", "target": "consent-requested", "animated": + true, "sourceHandle": "HandleSrcTop_start", "targetHandle": "HandleTargetLeft_consent-requested", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-target-2-patient", "title": + "Target 2 Patient", "description": "Delayers - en route to top of treatment.", + "phases": [{"name": "start", "title": "Start", "type": "START", "description": + "", "autoFinishProgram": false, "navigateTo": [{"name": "finish"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}], "nodes": [{"id": "start", "data": {"label": "Start"}, + "type": "graphNode", "position": {"x": 20, "y": 20}}, {"id": "finish", "data": + {"type": "FINISH", "label": "Finish"}, "type": "graphNode", "position": {"x": + 300, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_713b0fea-09cb-4c09-98da-bcb71c6cc9e5-finishHandleTargetLeft_d0fe8672-eafd-4b25-98b8-8845e89953a8", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-non-target-patient", "title": + "Non-Target Patient", "description": "All other non-target patients that do + not meet the criteria for other care plans.", "phases": [{"name": "start", + "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}]}, {"name": "finish", "title": "Finish", + "type": "FINISH", "description": "", "autoFinishProgram": false, "navigateTo": + []}], "nodes": [{"id": "start", "data": {"label": "Start"}, "type": "graphNode", + "position": {"x": 20, "y": 20}}, {"id": "finish", "data": {"label": "Finish"}, + "type": "graphNode", "position": {"x": 1520, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_34f0e25d-bb67-4d65-9dd2-b7bca6e1bd73-finishHandleTargetLeft_4c1007b4-98fa-45fc-b64b-678f7fbc880a", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}]' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Sat, 28 Oct 2023 00:11:13 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '12829' + status: + code: 200 + message: OK +- request: + body: '{"assigned": true, "phaseName": "start"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d + Connection: + - keep-alive + Content-Length: + - '40' + Content-Type: + - application/json + User-Agent: + - python-welkin/0.1.1 + method: PATCH + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/prog-target-patient + response: + body: + string: '{"id": "a636bccc-d554-46c2-a7e5-c37f9520db31", "createdByName": "createdByName_REDACTED_edaa62a4-9920-4e38-bff2-54d254b898e0", + "createdAt": "2023-10-28T00:11:13.310Z", "updatedByName": "updatedByName_REDACTED_47021932-3f78-498e-96ce-45d8fa83e24d", + "updatedAt": "2023-10-28T00:11:13.316Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-28T00:11:13.314Z", + "createdBy": "createdBy_REDACTED_4fb78d5c-4778-420c-9710-8faa4e16e511", "createdByName": + "createdByName_REDACTED_c8fbe78a-ce5d-4070-b6e4-9210d9d029ce", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-28T00:11:13.314Z", "createdBy": "createdBy_REDACTED_b4389270-8e1a-423d-bb5d-f199dcb18029", + "createdByName": "createdByName_REDACTED_d4be070f-9819-49b1-b4ca-534192068678", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Sat, 28 Oct 2023 00:11:13 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + response: + body: + string: '{"id": "a636bccc-d554-46c2-a7e5-c37f9520db31", "createdByName": "createdByName_REDACTED_f1bbe71c-211d-4a02-83ba-a39bb1afdf03", + "createdAt": "2023-10-28T00:11:13.310Z", "updatedByName": "updatedByName_REDACTED_bbffc38b-aa65-403d-90cd-8847830d81eb", + "updatedAt": "2023-10-28T00:11:13.316Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-28T00:11:13.314Z", + "createdBy": "createdBy_REDACTED_1a5bc1c7-c703-4fae-9124-b15bc8ffad9b", "createdByName": + "createdByName_REDACTED_6cfe47b8-9e3e-414a-92b8-6ecc0ac4ae53", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-28T00:11:13.314Z", "createdBy": "createdBy_REDACTED_8902d24e-8de5-4836-9a49-d96d80dbe121", + "createdByName": "createdByName_REDACTED_310d4c31-40ba-495c-8f89-76e40d9e7c73", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Sat, 28 Oct 2023 00:11:39 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + response: + body: + string: '{"id": "a636bccc-d554-46c2-a7e5-c37f9520db31", "createdByName": "createdByName_REDACTED_1270b5a2-b661-4cc5-954f-23c467001188", + "createdAt": "2023-10-28T00:11:13.310Z", "updatedByName": "updatedByName_REDACTED_49f73c8d-b565-4fb1-bf9e-f1b79ff7d37e", + "updatedAt": "2023-10-28T00:11:13.316Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-28T00:11:13.314Z", + "createdBy": "createdBy_REDACTED_412bf14f-f5eb-4ff1-85d4-d309d40dcc44", "createdByName": + "createdByName_REDACTED_4713923d-cf5b-4458-94f4-df2206c7d1d4", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-28T00:11:13.314Z", "createdBy": "createdBy_REDACTED_2a352fe1-dde4-414e-88bb-eb57063e06cd", + "createdByName": "createdByName_REDACTED_badedad0-d666-46e2-a043-19fb4fe587e3", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Sat, 28 Oct 2023 00:13:21 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +version: 1 diff --git a/test/conftest.py b/test/conftest.py index 2d940dc..3b38bdf 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -3,6 +3,7 @@ import uuid from datetime import date, datetime, time, timedelta, timezone from http import HTTPStatus +from pathlib import Path from uuid import uuid4 import pytest @@ -110,21 +111,24 @@ def hook(dct): @pytest.fixture -def patient(client): +def patient(client, vcr, vcr_cassette_dir, request): patient = client.Patient( firstName="Test", lastName="Patient", email="test.patient@example.com", externalGuid=uuid.UUID("12345678-1234-1234-1234-1234567890ab"), ) + cassette_name = f"patient__{request.node.name}" + fixture_path = str(Path(vcr_cassette_dir, "fixtures")) - try: - return patient.get() - except WelkinHTTPError as exc: - if exc.response.status_code != HTTPStatus.NOT_FOUND: - raise + with vcr.use_cassette(cassette_name, cassette_library_dir=fixture_path): + try: + return patient.get() + except WelkinHTTPError as exc: + if exc.response.status_code != HTTPStatus.NOT_FOUND: + raise - return patient.create() + return patient.create() @pytest.fixture diff --git a/test/test_program.py b/test/test_program.py new file mode 100644 index 0000000..b751cf2 --- /dev/null +++ b/test/test_program.py @@ -0,0 +1,62 @@ +from datetime import date + +import pytest + +from welkin.exceptions import WelkinHTTPError +from welkin.models import Program, ProgramPhase + + +@pytest.fixture +def program(client): + return client.Formation().Programs().get()[0] + + +@pytest.fixture +def assigned_program(patient, program): + phase = program.phases[0]["name"] + return patient.Program(programName=program.name).update( + assigned=True, phaseName=phase + ) + + +@pytest.mark.vcr +def test_program_read(patient, assigned_program, vcr_cassette): + program = patient.Program(programName=assigned_program.programName).get() + + assert isinstance(program, Program) + assert program.id == assigned_program.id + assert len(vcr_cassette) == 4 + + +@pytest.mark.vcr +def test_program_update(client, patient, vcr_cassette): + program = client.Program(id="092ae416-1c0d-4e14-be22-9cc8dafacdbd").get() + name = program.firstName + + program.update(firstName="Baz") + + assert program.firstName != name + assert len(vcr_cassette) == 2 + + +@pytest.mark.vcr +def test_program_delete(client, patient, vcr_cassette): + program = client.Program(id="092ae416-1c0d-4e14-be22-9cc8dafacdbd") + + with pytest.raises(WelkinHTTPError) as excinfo: + program.delete() + + assert excinfo.value.response.status_code == 403 + + assert len(vcr_cassette) == 1 + + +@pytest.mark.vcr +def test_program_phase_update(client, patient, vcr_cassette): + program = client.Program(id="092ae416-1c0d-4e14-be22-9cc8dafacdbd").get() + name = program.firstName + + program.update(firstName="Baz") + + assert program.firstName != name + assert len(vcr_cassette) == 2 diff --git a/welkin/client.py b/welkin/client.py index cddb0f8..66fe74f 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -96,7 +96,6 @@ class Client(Session): Patients = models.Patients Program = models.Program ProgramPhase = models.ProgramPhase - Programs = models.Programs Schedules = models.Schedules SearchChats = models.SearchChats SMS = models.SMS diff --git a/welkin/models/__init__.py b/welkin/models/__init__.py index 893c661..1f6b333 100644 --- a/welkin/models/__init__.py +++ b/welkin/models/__init__.py @@ -19,7 +19,7 @@ from welkin.models.encounter import Encounter, EncounterDisposition, Encounters from welkin.models.formation import Formation from welkin.models.patient import Patient, Patients -from welkin.models.program import Program, ProgramPhase, Programs +from welkin.models.program import Program, ProgramPhase from welkin.models.sms import SMS, SMSes from welkin.models.user import User, Users @@ -50,7 +50,6 @@ "Patient", "Patients", "Program", - "Programs", "ProgramPhase", "Schedules", "SearchChats", diff --git a/welkin/models/patient.py b/welkin/models/patient.py index 609c11e..dd617b9 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -10,7 +10,7 @@ ) from welkin.models.email import Email, Emails from welkin.models.encounter import Encounter, Encounters -from welkin.models.program import Program, Programs +from welkin.models.program import Program from welkin.models.sms import SMS, SMSes from welkin.pagination import PageableIterator @@ -24,7 +24,6 @@ class Patient(Resource): CDTs, Chat, Chats, - Programs, DocumentSummaries, DocumentSummary, DocumentSummaryFile, diff --git a/welkin/models/program.py b/welkin/models/program.py index 7076faa..63f226f 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -18,26 +18,6 @@ def update(self, patient_id: str = None, program_name: str = None, **kwargs): class Program(Resource): subresources = [ProgramPhase] - def delete(self, patient_id: str = None): - patient_id = patient_id or find_patient_id_in_parents(self) - - return super().delete( - f"{self._client.instance}/patients/{patient_id}/programs/{self.name}" - ) - - def update(self, patient_id: str = None, **kwargs): - patient_id = patient_id or find_patient_id_in_parents(self) - - return super().patch( - f"{self._client.instance}/patients/{patient_id}/programs/{self.name}", - **kwargs, - ) - - -class Programs(Collection): - resource = Program - iterator = PageIterator - def get( self, patient_id: str = None, @@ -47,10 +27,6 @@ def get( **kwargs, ): patient_id = patient_id or find_patient_id_in_parents(self) - params = { - "assignedPrograms": assigned_programs, - "sort": sort, - } path = f"{self._client.instance}/patients/{patient_id}/programs" if hasattr(self, "programName"): @@ -62,7 +38,27 @@ def get( return super().get( path, - params=params, + params={ + "assignedPrograms": assigned_programs, + "sort": sort, + }, *args, **kwargs, ) + + def update(self, patient_id: str = None, **kwargs): + patient_id = patient_id or find_patient_id_in_parents(self) + + return super().patch( + f"{self._client.instance}/patients/{patient_id}/programs/" + f"{self.programName}", + kwargs, + ) + + def delete(self, patient_id: str = None): + patient_id = patient_id or find_patient_id_in_parents(self) + + return super().delete( + f"{self._client.instance}/patients/{patient_id}/programs/" + f"{self.programName}" + ) diff --git a/welkin/models/util.py b/welkin/models/util.py index f6b938e..592da68 100644 --- a/welkin/models/util.py +++ b/welkin/models/util.py @@ -9,7 +9,7 @@ def find_patient_id_in_parents(model_instance): return model_instance.id elif hasattr(model_instance, "patientId"): return model_instance.patientId - elif model_instance._parent: + elif model_instance._parent is not None: return find_patient_id_in_parents(model_instance._parent) else: raise Exception( From f870433552d006943c1202460cefffa502f097c3 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Mon, 30 Oct 2023 18:01:52 -0700 Subject: [PATCH 19/48] Remove tests from coverage check --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 3ab7e97..3bef3ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,9 @@ build-backend = "poetry.core.masonry.api" [tool.isort] profile = "black" +[tool.coverage.run] +omit = ["test/*"] + [tool.pytest.ini_options] addopts = ["-n=auto"] env_files = [".env", ".env.example"] From 730e1d6787e8fc2c28b05176f3448df908738725 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Mon, 30 Oct 2023 18:02:37 -0700 Subject: [PATCH 20/48] Fix patient fixture cassette dir --- test/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 3b38bdf..c87601d 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -111,14 +111,14 @@ def hook(dct): @pytest.fixture -def patient(client, vcr, vcr_cassette_dir, request): +def patient(client, vcr, vcr_cassette_dir, vcr_cassette_name): patient = client.Patient( firstName="Test", lastName="Patient", email="test.patient@example.com", externalGuid=uuid.UUID("12345678-1234-1234-1234-1234567890ab"), ) - cassette_name = f"patient__{request.node.name}" + cassette_name = f"patient__{vcr_cassette_name}" fixture_path = str(Path(vcr_cassette_dir, "fixtures")) with vcr.use_cassette(cassette_name, cassette_library_dir=fixture_path): From 2daf528aa2ebf734202abe8e716a6076505bde49 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Mon, 30 Oct 2023 18:04:09 -0700 Subject: [PATCH 21/48] Finish program tests --- test/test_program.py | 89 ++++++++++++++++++++++++--------------- welkin/client.py | 10 +++-- welkin/models/__init__.py | 4 +- welkin/models/patient.py | 3 +- welkin/models/program.py | 55 +++++++++++++++++------- 5 files changed, 106 insertions(+), 55 deletions(-) diff --git a/test/test_program.py b/test/test_program.py index b751cf2..5abeddc 100644 --- a/test/test_program.py +++ b/test/test_program.py @@ -1,62 +1,83 @@ -from datetime import date +from http import HTTPStatus import pytest +from welkin import Client from welkin.exceptions import WelkinHTTPError -from welkin.models import Program, ProgramPhase +from welkin.models import Patient, Program, ProgramPhase, ProgramPhases, Programs +from welkin.models.formation import Program as FormationProgram @pytest.fixture -def program(client): +def formation(client: Client) -> FormationProgram: return client.Formation().Programs().get()[0] @pytest.fixture -def assigned_program(patient, program): - phase = program.phases[0]["name"] - return patient.Program(programName=program.name).update( - assigned=True, phaseName=phase - ) +def first_phase(formation) -> str: + return formation.phases[0]["name"] -@pytest.mark.vcr -def test_program_read(patient, assigned_program, vcr_cassette): - program = patient.Program(programName=assigned_program.programName).get() +@pytest.fixture +def second_phase(formation) -> str: + return formation.phases[1]["name"] - assert isinstance(program, Program) - assert program.id == assigned_program.id - assert len(vcr_cassette) == 4 +@pytest.fixture +def model(patient: Patient, formation: FormationProgram, first_phase: str) -> Program: + model = patient.Program(programName=formation.name) + try: + model = model.get() + except WelkinHTTPError as exc: + if exc.response.status_code != HTTPStatus.NOT_FOUND: + raise -@pytest.mark.vcr -def test_program_update(client, patient, vcr_cassette): - program = client.Program(id="092ae416-1c0d-4e14-be22-9cc8dafacdbd").get() - name = program.firstName + return model.update(assigned=True, phaseName=first_phase) - program.update(firstName="Baz") + if len(model.pathHistory) > 1: + model.delete() + model = model.update(assigned=True, phaseName=first_phase) - assert program.firstName != name - assert len(vcr_cassette) == 2 + return model @pytest.mark.vcr -def test_program_delete(client, patient, vcr_cassette): - program = client.Program(id="092ae416-1c0d-4e14-be22-9cc8dafacdbd") - - with pytest.raises(WelkinHTTPError) as excinfo: +class TestProgram: + @pytest.mark.parametrize("identifier", ["id", "programName"]) + def test_read(self, patient: Patient, model: Program, identifier: str): + program = patient.Program(**{identifier: getattr(model, identifier)}).get() + + assert isinstance(program, Program) + assert isinstance(program.currentPhase, ProgramPhase) + assert isinstance(program.pathHistory, ProgramPhases) + + assert program.id == model.id + + def test_update(self, patient: Patient, model: Program, second_phase: str): + assert model.currentPhase.name != second_phase + assert len(model.pathHistory) == 1 + + program = patient.Program(programName=model.programName).update( + phaseName=second_phase + ) + assert program.currentPhase.name == second_phase + assert program.currentPhase.name != model.currentPhase.name + assert len(program.pathHistory) == 2 + + def test_delete(self, patient: Patient, model: Program): + program = patient.Program(id=model.id) program.delete() - assert excinfo.value.response.status_code == 403 + with pytest.raises(WelkinHTTPError) as excinfo: + program.get() - assert len(vcr_cassette) == 1 + assert excinfo.value.response.status_code == 404 @pytest.mark.vcr -def test_program_phase_update(client, patient, vcr_cassette): - program = client.Program(id="092ae416-1c0d-4e14-be22-9cc8dafacdbd").get() - name = program.firstName - - program.update(firstName="Baz") +class TestPrograms: + def test_read(self, patient): + programs = patient.Programs().get() - assert program.firstName != name - assert len(vcr_cassette) == 2 + assert isinstance(programs, Programs) + assert isinstance(programs[0], Program) diff --git a/welkin/client.py b/welkin/client.py index 66fe74f..22e58d6 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -11,10 +11,10 @@ from requests.compat import urljoin from requests.packages.urllib3.util.retry import Retry # type: ignore -from welkin import __version__, models -from welkin.authentication import WelkinAuth -from welkin.exceptions import WelkinHTTPError -from welkin.util import _build_resources, clean_request_params, clean_request_payload +from . import __version__, models +from .authentication import WelkinAuth +from .exceptions import WelkinHTTPError +from .util import _build_resources, clean_request_params, clean_request_payload logger = logging.getLogger(__name__) @@ -96,6 +96,8 @@ class Client(Session): Patients = models.Patients Program = models.Program ProgramPhase = models.ProgramPhase + ProgramPhases = models.ProgramPhases + Programs = models.Programs Schedules = models.Schedules SearchChats = models.SearchChats SMS = models.SMS diff --git a/welkin/models/__init__.py b/welkin/models/__init__.py index 1f6b333..52e97ed 100644 --- a/welkin/models/__init__.py +++ b/welkin/models/__init__.py @@ -19,7 +19,7 @@ from welkin.models.encounter import Encounter, EncounterDisposition, Encounters from welkin.models.formation import Formation from welkin.models.patient import Patient, Patients -from welkin.models.program import Program, ProgramPhase +from welkin.models.program import Program, ProgramPhase, ProgramPhases, Programs from welkin.models.sms import SMS, SMSes from welkin.models.user import User, Users @@ -51,6 +51,8 @@ "Patients", "Program", "ProgramPhase", + "ProgramPhases", + "Programs", "Schedules", "SearchChats", "SMS", diff --git a/welkin/models/patient.py b/welkin/models/patient.py index dd617b9..1a1b79c 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -10,7 +10,7 @@ ) from welkin.models.email import Email, Emails from welkin.models.encounter import Encounter, Encounters -from welkin.models.program import Program +from welkin.models.program import Program, Programs from welkin.models.sms import SMS, SMSes from welkin.pagination import PageableIterator @@ -32,6 +32,7 @@ class Patient(Resource): Encounter, Encounters, Program, + Programs, SearchChats, SMS, SMSes, diff --git a/welkin/models/program.py b/welkin/models/program.py index 63f226f..36f7f09 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -1,22 +1,23 @@ from welkin.models.base import Collection, Resource from welkin.models.util import find_patient_id_in_parents -from welkin.pagination import PageIterator +from welkin.pagination import MetaInfoIterator class ProgramPhase(Resource): - def update(self, patient_id: str = None, program_name: str = None, **kwargs): - patient_id = patient_id or find_patient_id_in_parents(self) - program_name = program_name or self._parent.name + pass - return super().patch( - f"{self._client.instance}/patients/{patient_id}/programs/" - f"{program_name or self._parent.name}/phases", - kwargs, - ) + +class ProgramPhases(Collection): + resource = ProgramPhase class Program(Resource): subresources = [ProgramPhase] + nested_objects = { + "phases": "ProgramPhase", + "currentPhase": "ProgramPhase", + "pathHistory": "ProgramPhases", + } def get( self, @@ -29,12 +30,12 @@ def get( patient_id = patient_id or find_patient_id_in_parents(self) path = f"{self._client.instance}/patients/{patient_id}/programs" - if hasattr(self, "programName"): - path += f"/current/{self.programName}" - elif hasattr(self, "id"): + if hasattr(self, "id"): path += f"/history/{self.id}" + elif hasattr(self, "programName"): + path += f"/current/{self.programName}" else: - raise AttributeError("At least one of programName or id must be set.") + raise ValueError("Program must have either programName or id attributes") return super().get( path, @@ -59,6 +60,30 @@ def delete(self, patient_id: str = None): patient_id = patient_id or find_patient_id_in_parents(self) return super().delete( - f"{self._client.instance}/patients/{patient_id}/programs/" - f"{self.programName}" + f"{self._client.instance}/patients/{patient_id}/programs/{self.id}" + ) + + +class Programs(Collection): + resource = Program + iterator = MetaInfoIterator + + def get( + self, + patient_id: str = None, + assigned_programs: bool = None, + sort: str = None, + *args, + **kwargs, + ): + patient_id = patient_id or find_patient_id_in_parents(self) + + return super().get( + f"{self._client.instance}/patients/{patient_id}/programs", + params={ + "assignedPrograms": assigned_programs, + "sort": sort, + }, + *args, + **kwargs, ) From fb491964e30132c5aeeb204d1ce733debb201f55 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Mon, 30 Oct 2023 19:11:39 -0700 Subject: [PATCH 22/48] Finish tests --- ...read.yaml => TestProgram.test_delete.yaml} | 136 ++------- test/cassettes/TestProgram.test_read[id].yaml | 269 +++++++++++++++++ .../TestProgram.test_read[programName].yaml | 269 +++++++++++++++++ test/cassettes/TestProgram.test_update.yaml | 276 ++++++++++++++++++ test/cassettes/TestPrograms.test_read.yaml | 75 +++++ .../patient__TestProgram.test_delete.yaml | 84 ++++++ .../patient__TestProgram.test_read[id].yaml | 84 ++++++ ...__TestProgram.test_read[programName].yaml} | 12 +- .../patient__TestProgram.test_update.yaml | 84 ++++++ .../patient__TestPrograms.test_read.yaml | 70 +++++ .../program__TestProgram.test_delete.yaml | 69 +++++ .../program__TestProgram.test_read[id].yaml | 69 +++++ ...m__TestProgram.test_read[programName].yaml | 130 +++++++++ .../program__TestProgram.test_update.yaml | 69 +++++ test/conftest.py | 19 +- test/test_program.py | 124 ++++---- 16 files changed, 1658 insertions(+), 181 deletions(-) rename test/cassettes/{test_program_read.yaml => TestProgram.test_delete.yaml} (75%) create mode 100644 test/cassettes/TestProgram.test_read[id].yaml create mode 100644 test/cassettes/TestProgram.test_read[programName].yaml create mode 100644 test/cassettes/TestProgram.test_update.yaml create mode 100644 test/cassettes/TestPrograms.test_read.yaml create mode 100644 test/cassettes/fixtures/patient__TestProgram.test_delete.yaml create mode 100644 test/cassettes/fixtures/patient__TestProgram.test_read[id].yaml rename test/cassettes/fixtures/{patient__test_program_read.yaml => patient__TestProgram.test_read[programName].yaml} (87%) create mode 100644 test/cassettes/fixtures/patient__TestProgram.test_update.yaml create mode 100644 test/cassettes/fixtures/patient__TestPrograms.test_read.yaml create mode 100644 test/cassettes/fixtures/program__TestProgram.test_delete.yaml create mode 100644 test/cassettes/fixtures/program__TestProgram.test_read[id].yaml create mode 100644 test/cassettes/fixtures/program__TestProgram.test_read[programName].yaml create mode 100644 test/cassettes/fixtures/program__TestProgram.test_update.yaml diff --git a/test/cassettes/test_program_read.yaml b/test/cassettes/TestProgram.test_delete.yaml similarity index 75% rename from test/cassettes/test_program_read.yaml rename to test/cassettes/TestProgram.test_delete.yaml index 960ecea..e6e375c 100644 --- a/test/cassettes/test_program_read.yaml +++ b/test/cassettes/TestProgram.test_delete.yaml @@ -7,7 +7,7 @@ interactions: Accept-Encoding: - gzip, deflate Authorization: - - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d + - API_TOKEN_cdbf8879-481a-4cdd-af08-c5a0fc54f3b1 Connection: - keep-alive User-Agent: @@ -181,7 +181,7 @@ interactions: Content-Type: - application/json Date: - - Sat, 28 Oct 2023 00:11:13 GMT + - Tue, 31 Oct 2023 02:10:14 GMT Expires: - '0' Pragma: @@ -200,107 +200,25 @@ interactions: code: 200 message: OK - request: - body: '{"assigned": true, "phaseName": "start"}' + body: null headers: Accept: - '*/*' Accept-Encoding: - gzip, deflate Authorization: - - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d + - API_TOKEN_cdbf8879-481a-4cdd-af08-c5a0fc54f3b1 Connection: - keep-alive Content-Length: - - '40' - Content-Type: - - application/json - User-Agent: - - python-welkin/0.1.1 - method: PATCH - uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/prog-target-patient - response: - body: - string: '{"id": "a636bccc-d554-46c2-a7e5-c37f9520db31", "createdByName": "createdByName_REDACTED_edaa62a4-9920-4e38-bff2-54d254b898e0", - "createdAt": "2023-10-28T00:11:13.310Z", "updatedByName": "updatedByName_REDACTED_47021932-3f78-498e-96ce-45d8fa83e24d", - "updatedAt": "2023-10-28T00:11:13.316Z", "programName": "prog-target-patient", - "programTitle": "Target Patient", "programDescription": "Moderate to severe - patients, either on biologics or oral treatment.", "assigned": true, "patientId": - "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-28T00:11:13.314Z", - "createdBy": "createdBy_REDACTED_4fb78d5c-4778-420c-9710-8faa4e16e511", "createdByName": - "createdByName_REDACTED_c8fbe78a-ce5d-4070-b6e4-9210d9d029ce", "name": "start", - "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, - "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": - [{"timestamp": "2023-10-28T00:11:13.314Z", "createdBy": "createdBy_REDACTED_b4389270-8e1a-423d-bb5d-f199dcb18029", - "createdByName": "createdByName_REDACTED_d4be070f-9819-49b1-b4ca-534192068678", - "name": "start", "title": "Start", "description": "", "currentVersion": "92", - "deleted": false}]}' - headers: - Access-Control-Allow-Headers: - - authorization, content-type, xsrf-token, security-role - Access-Control-Allow-Methods: - - GET, POST, PUT, DELETE, PATCH, OPTIONS - Access-Control-Allow-Origin: - - '*' - Access-Control-Expose-Headers: - - xsrf-token - Access-Control-Max-Age: - - '3600' - Cache-Control: - - no-cache, no-store, max-age=0, must-revalidate - Connection: - - keep-alive - Content-Type: - - application/json - Date: - - Sat, 28 Oct 2023 00:11:13 GMT - Expires: - '0' - Pragma: - - no-cache - Strict-Transport-Security: - - max-age=31536000 ; includeSubDomains - Transfer-Encoding: - - chunked - X-Content-Type-Options: - - nosniff - X-XSS-Protection: - - 1; mode=block - content-length: - - '963' - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Authorization: - - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d - Connection: - - keep-alive User-Agent: - python-welkin/0.1.1 - method: GET - uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + method: DELETE + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/53e7f5de-67d7-475f-9443-6b4dedf14848 response: body: - string: '{"id": "a636bccc-d554-46c2-a7e5-c37f9520db31", "createdByName": "createdByName_REDACTED_f1bbe71c-211d-4a02-83ba-a39bb1afdf03", - "createdAt": "2023-10-28T00:11:13.310Z", "updatedByName": "updatedByName_REDACTED_bbffc38b-aa65-403d-90cd-8847830d81eb", - "updatedAt": "2023-10-28T00:11:13.316Z", "programName": "prog-target-patient", - "programTitle": "Target Patient", "programDescription": "Moderate to severe - patients, either on biologics or oral treatment.", "assigned": true, "patientId": - "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-28T00:11:13.314Z", - "createdBy": "createdBy_REDACTED_1a5bc1c7-c703-4fae-9124-b15bc8ffad9b", "createdByName": - "createdByName_REDACTED_6cfe47b8-9e3e-414a-92b8-6ecc0ac4ae53", "name": "start", - "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, - "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": - [{"timestamp": "2023-10-28T00:11:13.314Z", "createdBy": "createdBy_REDACTED_8902d24e-8de5-4836-9a49-d96d80dbe121", - "createdByName": "createdByName_REDACTED_310d4c31-40ba-495c-8f89-76e40d9e7c73", - "name": "start", "title": "Start", "description": "", "currentVersion": "92", - "deleted": false}]}' + string: '' headers: Access-Control-Allow-Headers: - authorization, content-type, xsrf-token, security-role @@ -316,24 +234,20 @@ interactions: - no-cache, no-store, max-age=0, must-revalidate Connection: - keep-alive - Content-Type: - - application/json + Content-Length: + - '0' Date: - - Sat, 28 Oct 2023 00:11:39 GMT + - Tue, 31 Oct 2023 02:10:15 GMT Expires: - '0' Pragma: - no-cache Strict-Transport-Security: - max-age=31536000 ; includeSubDomains - Transfer-Encoding: - - chunked X-Content-Type-Options: - nosniff X-XSS-Protection: - 1; mode=block - content-length: - - '963' status: code: 200 message: OK @@ -345,29 +259,19 @@ interactions: Accept-Encoding: - gzip, deflate Authorization: - - API_TOKEN_70b27fc9-755a-40e6-ba68-ca1f5f7c629d + - API_TOKEN_cdbf8879-481a-4cdd-af08-c5a0fc54f3b1 Connection: - keep-alive User-Agent: - python-welkin/0.1.1 method: GET - uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/history/53e7f5de-67d7-475f-9443-6b4dedf14848 response: body: - string: '{"id": "a636bccc-d554-46c2-a7e5-c37f9520db31", "createdByName": "createdByName_REDACTED_1270b5a2-b661-4cc5-954f-23c467001188", - "createdAt": "2023-10-28T00:11:13.310Z", "updatedByName": "updatedByName_REDACTED_49f73c8d-b565-4fb1-bf9e-f1b79ff7d37e", - "updatedAt": "2023-10-28T00:11:13.316Z", "programName": "prog-target-patient", - "programTitle": "Target Patient", "programDescription": "Moderate to severe - patients, either on biologics or oral treatment.", "assigned": true, "patientId": - "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-28T00:11:13.314Z", - "createdBy": "createdBy_REDACTED_412bf14f-f5eb-4ff1-85d4-d309d40dcc44", "createdByName": - "createdByName_REDACTED_4713923d-cf5b-4458-94f4-df2206c7d1d4", "name": "start", - "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, - "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": - [{"timestamp": "2023-10-28T00:11:13.314Z", "createdBy": "createdBy_REDACTED_2a352fe1-dde4-414e-88bb-eb57063e06cd", - "createdByName": "createdByName_REDACTED_badedad0-d666-46e2-a043-19fb4fe587e3", - "name": "start", "title": "Start", "description": "", "currentVersion": "92", - "deleted": false}]}' + string: '[{"errorCode": "PATIENT_PROGRAM_NOT_FOUND", "componentType": "PATIENT_PROGRAM", + "message": "Patient related to program doesn''t exist", "details": {"id": + "53e7f5de-67d7-475f-9443-6b4dedf14848", "patientId": "de5e1a93-70b0-4ed4-868f-3854becc383c"}, + "date": "2023-10-31T02:10:15.236Z"}]' headers: Access-Control-Allow-Headers: - authorization, content-type, xsrf-token, security-role @@ -386,7 +290,7 @@ interactions: Content-Type: - application/json Date: - - Sat, 28 Oct 2023 00:13:21 GMT + - Tue, 31 Oct 2023 02:10:15 GMT Expires: - '0' Pragma: @@ -400,8 +304,8 @@ interactions: X-XSS-Protection: - 1; mode=block content-length: - - '963' + - '271' status: - code: 200 - message: OK + code: 404 + message: Not Found version: 1 diff --git a/test/cassettes/TestProgram.test_read[id].yaml b/test/cassettes/TestProgram.test_read[id].yaml new file mode 100644 index 0000000..a397850 --- /dev/null +++ b/test/cassettes/TestProgram.test_read[id].yaml @@ -0,0 +1,269 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/formations/current/programs?page=0 + response: + body: + string: '[{"name": "prog-target-patient", "title": "Target Patient", "description": + "Moderate to severe patients, either on biologics or oral treatment.", "phases": + [{"name": "start", "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}, {"name": "continuing-old-treatment"}, + {"name": "stopping-old-treatment"}, {"name": "consent-requested"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "records-requested", "title": "Records + Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": false, + "navigateTo": [{"name": "records-received"}]}, {"name": "records-received", + "title": "Records Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "starting-new-treatment", "title": "Starting + New Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, + {"name": "continuing-old-treatment", "title": "Continuing Old Treatment", + "type": "DEFAULT", "description": "", "autoFinishProgram": false, "navigateTo": + [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, {"name": + "prior-auth-requested", "title": "Prior Auth Requested", "type": "DEFAULT", + "description": "", "autoFinishProgram": false, "navigateTo": [{"name": "prior-auth-approved"}, + {"name": "prior-auth-abandoned"}]}, {"name": "prior-auth-approved", "title": + "Prior Auth Approved", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "sent-to-pharmacy"}]}, {"name": "prior-auth-abandoned", + "title": "Prior Auth Abandoned", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-approved"}]}, {"name": "sent-to-pharmacy", + "title": "Sent to Pharmacy", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "confirmed-patient-filled"}]}, {"name": "confirmed-patient-filled", + "title": "Confirmed Patient Filled", "type": "DEFAULT", "description": "", + "autoFinishProgram": false, "navigateTo": []}, {"name": "stopping-old-treatment", + "title": "Stopping Old Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "starting-new-treatment"}]}, {"name": "consent-requested", + "title": "Consent Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "consent-received"}]}, {"name": "consent-received", + "title": "Consent Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "records-requested"}]}], "nodes": [{"id": "start", + "data": {"type": "START", "label": "Start"}, "type": "graphNode", "position": + {"x": 340, "y": 20}}, {"id": "finish", "data": {"type": "FINISH", "label": + "Finish"}, "type": "graphNode", "position": {"x": 1120, "y": 20}}, {"id": + "reactflow__edge-startHandleSrcRight_025adb09-c24a-45f9-b5a5-d1a44450ff43-finishHandleTargetLeft_5f5f5e64-5959-46b2-8e36-c85a86e60456", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}, {"id": "records-requested", "data": {"type": + "DEFAULT", "label": "Records Requested"}, "type": "graphNode", "position": + {"x": 800, "y": -40}}, {"id": "records-received", "data": {"type": "DEFAULT", + "label": "Records Received"}, "type": "graphNode", "position": {"x": 980, + "y": -40}}, {"id": "starting-new-treatment", "data": {"type": "DEFAULT", "label": + "Starting New Treatment"}, "type": "graphNode", "position": {"x": 640, "y": + 80}}, {"id": "continuing-old-treatment", "data": {"type": "DEFAULT", "label": + "Continuing Old Treatment"}, "type": "graphNode", "position": {"x": 440, "y": + 140}}, {"id": "prior-auth-requested", "data": {"type": "DEFAULT", "label": + "Prior Auth Requested"}, "type": "graphNode", "position": {"x": 660, "y": + 160}}, {"id": "prior-auth-approved", "data": {"type": "DEFAULT", "label": + "Prior Auth Approved"}, "type": "graphNode", "position": {"x": 840, "y": 160}}, + {"id": "prior-auth-abandoned", "data": {"type": "DEFAULT", "label": "Prior + Auth Abandoned"}, "type": "graphNode", "position": {"x": 760, "y": 220}}, + {"id": "sent-to-pharmacy", "data": {"type": "DEFAULT", "label": "Sent to Pharmacy"}, + "type": "graphNode", "position": {"x": 860, "y": 80}}, {"id": "confirmed-patient-filled", + "data": {"type": "DEFAULT", "label": "Confirmed Patient Filled"}, "type": + "graphNode", "position": {"x": 1020, "y": 80}}, {"id": "reactflow__edge-records-requestedHandleSrcRight_6672da4b-34f4-42fb-81b3-5d7e785c5e1d-records-receivedHandleTargetLeft_1c3c44da-11c5-4da6-9e79-94f1eb86a5c5", + "type": "smoothstep", "source": "records-requested", "target": "records-received", + "animated": true, "sourceHandle": "HandleSrcRight_records-requested", "targetHandle": + "HandleTargetLeft_records-received", "arrowHeadType": "arrowclosed"}, {"id": + "stopping-old-treatment", "data": {"type": "DEFAULT", "label": "Stopping Old + Treatment"}, "type": "graphNode", "position": {"x": 440, "y": 80}}, {"id": + "reactflow__edge-stopping-old-treatmentHandleSrcRight_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36-starting-new-treatmentHandleTargetLeft_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6", + "type": "smoothstep", "source": "stopping-old-treatment", "target": "starting-new-treatment", + "animated": true, "sourceHandle": "HandleSrcRight_stopping-old-treatment", + "targetHandle": "HandleTargetLeft_starting-new-treatment", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-starting-new-treatmentHandleSrcBottom_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-prior-auth-requestedHandleTargetTop_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "starting-new-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcBottom_starting-new-treatment", + "targetHandle": "HandleTargetTop_prior-auth-requested", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcRight_40cd6e6c-c21c-45bf-b94c-62092b2b2510-prior-auth-requestedHandleTargetLeft_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcRight_continuing-old-treatment", + "targetHandle": "HandleTargetLeft_prior-auth-requested", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-requestedHandleSrcRight_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-approvedHandleTargetLeft_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcRight_prior-auth-requested", "targetHandle": + "HandleTargetLeft_prior-auth-approved", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-sent-to-pharmacyHandleSrcRight_e1ad3528-270a-45bf-9757-91fe3ecb9d23-confirmed-patient-filledHandleTargetLeft_2505253d-32d6-4020-8e16-722b4813a5a7", + "type": "smoothstep", "source": "sent-to-pharmacy", "target": "confirmed-patient-filled", + "animated": true, "sourceHandle": "HandleSrcRight_sent-to-pharmacy", "targetHandle": + "HandleTargetLeft_confirmed-patient-filled", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-starting-new-treatmentHandleSrcRight_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-sent-to-pharmacyHandleTargetLeft_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "starting-new-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcRight_starting-new-treatment", + "targetHandle": "HandleTargetLeft_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-requestedHandleSrcBottom_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-abandonedHandleTargetLeft_982c7e02-2cce-4202-b72c-bee08f44e11a", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-abandoned", + "animated": true, "sourceHandle": "HandleSrcBottom_prior-auth-requested", + "targetHandle": "HandleTargetLeft_prior-auth-abandoned", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-abandonedHandleSrcTop_982c7e02-2cce-4202-b72c-bee08f44e11a-prior-auth-approvedHandleTargetBottom_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-abandoned", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-abandoned", "targetHandle": + "HandleTargetBottom_prior-auth-approved", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcTop_40cd6e6c-c21c-45bf-b94c-62092b2b2510-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_continuing-old-treatment", + "targetHandle": "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-stopping-old-treatmentHandleTargetLeft_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36", + "type": "smoothstep", "source": "start", "target": "stopping-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_stopping-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-continuing-old-treatmentHandleTargetLeft_40cd6e6c-c21c-45bf-b94c-62092b2b2510", + "type": "smoothstep", "source": "start", "target": "continuing-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_continuing-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-approvedHandleSrcTop_7d04e809-9419-4673-800b-ea2c3d7c04aa-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "prior-auth-approved", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-approved", "targetHandle": + "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, {"id": + "consent-requested", "data": {"type": "DEFAULT", "label": "Consent Requested"}, + "type": "graphNode", "position": {"x": 460, "y": -40}}, {"id": "consent-received", + "data": {"type": "DEFAULT", "label": "Consent Received"}, "type": "graphNode", + "position": {"x": 640, "y": -40}}, {"id": "reactflow__edge-consent-receivedHandleSrcRight_2e7445fb-8611-43bd-b750-af720c1530c1-records-requestedHandleTargetLeft_99edae56-fbb6-4bd5-95d0-a02e8b53c097", + "type": "smoothstep", "source": "consent-received", "target": "records-requested", + "animated": true, "sourceHandle": "HandleSrcRight_consent-received", "targetHandle": + "HandleTargetLeft_records-requested", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-consent-requestedHandleSrcRight_b56feb59-d9ad-46e7-8741-a20ad73112b7-consent-receivedHandleTargetLeft_2e7445fb-8611-43bd-b750-af720c1530c1", + "type": "smoothstep", "source": "consent-requested", "target": "consent-received", + "animated": true, "sourceHandle": "HandleSrcRight_consent-requested", "targetHandle": + "HandleTargetLeft_consent-received", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-startHandleSrcTop_712c1b68-4ccd-4f94-8641-5721b6148ed8-consent-requestedHandleTargetLeft_b56feb59-d9ad-46e7-8741-a20ad73112b7", + "type": "smoothstep", "source": "start", "target": "consent-requested", "animated": + true, "sourceHandle": "HandleSrcTop_start", "targetHandle": "HandleTargetLeft_consent-requested", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-target-2-patient", "title": + "Target 2 Patient", "description": "Delayers - en route to top of treatment.", + "phases": [{"name": "start", "title": "Start", "type": "START", "description": + "", "autoFinishProgram": false, "navigateTo": [{"name": "finish"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}], "nodes": [{"id": "start", "data": {"label": "Start"}, + "type": "graphNode", "position": {"x": 20, "y": 20}}, {"id": "finish", "data": + {"type": "FINISH", "label": "Finish"}, "type": "graphNode", "position": {"x": + 300, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_713b0fea-09cb-4c09-98da-bcb71c6cc9e5-finishHandleTargetLeft_d0fe8672-eafd-4b25-98b8-8845e89953a8", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-non-target-patient", "title": + "Non-Target Patient", "description": "All other non-target patients that do + not meet the criteria for other care plans.", "phases": [{"name": "start", + "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}]}, {"name": "finish", "title": "Finish", + "type": "FINISH", "description": "", "autoFinishProgram": false, "navigateTo": + []}], "nodes": [{"id": "start", "data": {"label": "Start"}, "type": "graphNode", + "position": {"x": 20, "y": 20}}, {"id": "finish", "data": {"label": "Finish"}, + "type": "graphNode", "position": {"x": 1520, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_34f0e25d-bb67-4d65-9dd2-b7bca6e1bd73-finishHandleTargetLeft_4c1007b4-98fa-45fc-b64b-678f7fbc880a", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}]' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:14 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '12829' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/history/53e7f5de-67d7-475f-9443-6b4dedf14848 + response: + body: + string: '{"id": "53e7f5de-67d7-475f-9443-6b4dedf14848", "createdByName": "createdByName_REDACTED_d1f0948c-ca42-4732-b455-69627a84d64a", + "createdAt": "2023-10-31T02:05:28.717Z", "updatedByName": "updatedByName_REDACTED_096bd988-c5f3-496f-9e76-2b753de4c6b7", + "updatedAt": "2023-10-31T02:05:28.721Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:05:28.720Z", + "createdBy": "createdBy_REDACTED_d7ea081e-1536-4f22-964d-8ea9d9ff578b", "createdByName": + "createdByName_REDACTED_8509eaf7-95a2-4acb-9f51-fcc6681aad52", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:05:28.720Z", "createdBy": "createdBy_REDACTED_597490de-5966-4e40-ad13-bc33bd245d3e", + "createdByName": "createdByName_REDACTED_5730ba9f-d49a-43a8-ac61-8564d03c0ed0", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:15 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/TestProgram.test_read[programName].yaml b/test/cassettes/TestProgram.test_read[programName].yaml new file mode 100644 index 0000000..f5bc9eb --- /dev/null +++ b/test/cassettes/TestProgram.test_read[programName].yaml @@ -0,0 +1,269 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/formations/current/programs?page=0 + response: + body: + string: '[{"name": "prog-target-patient", "title": "Target Patient", "description": + "Moderate to severe patients, either on biologics or oral treatment.", "phases": + [{"name": "start", "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}, {"name": "continuing-old-treatment"}, + {"name": "stopping-old-treatment"}, {"name": "consent-requested"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "records-requested", "title": "Records + Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": false, + "navigateTo": [{"name": "records-received"}]}, {"name": "records-received", + "title": "Records Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "starting-new-treatment", "title": "Starting + New Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, + {"name": "continuing-old-treatment", "title": "Continuing Old Treatment", + "type": "DEFAULT", "description": "", "autoFinishProgram": false, "navigateTo": + [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, {"name": + "prior-auth-requested", "title": "Prior Auth Requested", "type": "DEFAULT", + "description": "", "autoFinishProgram": false, "navigateTo": [{"name": "prior-auth-approved"}, + {"name": "prior-auth-abandoned"}]}, {"name": "prior-auth-approved", "title": + "Prior Auth Approved", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "sent-to-pharmacy"}]}, {"name": "prior-auth-abandoned", + "title": "Prior Auth Abandoned", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-approved"}]}, {"name": "sent-to-pharmacy", + "title": "Sent to Pharmacy", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "confirmed-patient-filled"}]}, {"name": "confirmed-patient-filled", + "title": "Confirmed Patient Filled", "type": "DEFAULT", "description": "", + "autoFinishProgram": false, "navigateTo": []}, {"name": "stopping-old-treatment", + "title": "Stopping Old Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "starting-new-treatment"}]}, {"name": "consent-requested", + "title": "Consent Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "consent-received"}]}, {"name": "consent-received", + "title": "Consent Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "records-requested"}]}], "nodes": [{"id": "start", + "data": {"type": "START", "label": "Start"}, "type": "graphNode", "position": + {"x": 340, "y": 20}}, {"id": "finish", "data": {"type": "FINISH", "label": + "Finish"}, "type": "graphNode", "position": {"x": 1120, "y": 20}}, {"id": + "reactflow__edge-startHandleSrcRight_025adb09-c24a-45f9-b5a5-d1a44450ff43-finishHandleTargetLeft_5f5f5e64-5959-46b2-8e36-c85a86e60456", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}, {"id": "records-requested", "data": {"type": + "DEFAULT", "label": "Records Requested"}, "type": "graphNode", "position": + {"x": 800, "y": -40}}, {"id": "records-received", "data": {"type": "DEFAULT", + "label": "Records Received"}, "type": "graphNode", "position": {"x": 980, + "y": -40}}, {"id": "starting-new-treatment", "data": {"type": "DEFAULT", "label": + "Starting New Treatment"}, "type": "graphNode", "position": {"x": 640, "y": + 80}}, {"id": "continuing-old-treatment", "data": {"type": "DEFAULT", "label": + "Continuing Old Treatment"}, "type": "graphNode", "position": {"x": 440, "y": + 140}}, {"id": "prior-auth-requested", "data": {"type": "DEFAULT", "label": + "Prior Auth Requested"}, "type": "graphNode", "position": {"x": 660, "y": + 160}}, {"id": "prior-auth-approved", "data": {"type": "DEFAULT", "label": + "Prior Auth Approved"}, "type": "graphNode", "position": {"x": 840, "y": 160}}, + {"id": "prior-auth-abandoned", "data": {"type": "DEFAULT", "label": "Prior + Auth Abandoned"}, "type": "graphNode", "position": {"x": 760, "y": 220}}, + {"id": "sent-to-pharmacy", "data": {"type": "DEFAULT", "label": "Sent to Pharmacy"}, + "type": "graphNode", "position": {"x": 860, "y": 80}}, {"id": "confirmed-patient-filled", + "data": {"type": "DEFAULT", "label": "Confirmed Patient Filled"}, "type": + "graphNode", "position": {"x": 1020, "y": 80}}, {"id": "reactflow__edge-records-requestedHandleSrcRight_6672da4b-34f4-42fb-81b3-5d7e785c5e1d-records-receivedHandleTargetLeft_1c3c44da-11c5-4da6-9e79-94f1eb86a5c5", + "type": "smoothstep", "source": "records-requested", "target": "records-received", + "animated": true, "sourceHandle": "HandleSrcRight_records-requested", "targetHandle": + "HandleTargetLeft_records-received", "arrowHeadType": "arrowclosed"}, {"id": + "stopping-old-treatment", "data": {"type": "DEFAULT", "label": "Stopping Old + Treatment"}, "type": "graphNode", "position": {"x": 440, "y": 80}}, {"id": + "reactflow__edge-stopping-old-treatmentHandleSrcRight_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36-starting-new-treatmentHandleTargetLeft_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6", + "type": "smoothstep", "source": "stopping-old-treatment", "target": "starting-new-treatment", + "animated": true, "sourceHandle": "HandleSrcRight_stopping-old-treatment", + "targetHandle": "HandleTargetLeft_starting-new-treatment", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-starting-new-treatmentHandleSrcBottom_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-prior-auth-requestedHandleTargetTop_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "starting-new-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcBottom_starting-new-treatment", + "targetHandle": "HandleTargetTop_prior-auth-requested", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcRight_40cd6e6c-c21c-45bf-b94c-62092b2b2510-prior-auth-requestedHandleTargetLeft_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcRight_continuing-old-treatment", + "targetHandle": "HandleTargetLeft_prior-auth-requested", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-requestedHandleSrcRight_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-approvedHandleTargetLeft_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcRight_prior-auth-requested", "targetHandle": + "HandleTargetLeft_prior-auth-approved", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-sent-to-pharmacyHandleSrcRight_e1ad3528-270a-45bf-9757-91fe3ecb9d23-confirmed-patient-filledHandleTargetLeft_2505253d-32d6-4020-8e16-722b4813a5a7", + "type": "smoothstep", "source": "sent-to-pharmacy", "target": "confirmed-patient-filled", + "animated": true, "sourceHandle": "HandleSrcRight_sent-to-pharmacy", "targetHandle": + "HandleTargetLeft_confirmed-patient-filled", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-starting-new-treatmentHandleSrcRight_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-sent-to-pharmacyHandleTargetLeft_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "starting-new-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcRight_starting-new-treatment", + "targetHandle": "HandleTargetLeft_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-requestedHandleSrcBottom_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-abandonedHandleTargetLeft_982c7e02-2cce-4202-b72c-bee08f44e11a", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-abandoned", + "animated": true, "sourceHandle": "HandleSrcBottom_prior-auth-requested", + "targetHandle": "HandleTargetLeft_prior-auth-abandoned", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-abandonedHandleSrcTop_982c7e02-2cce-4202-b72c-bee08f44e11a-prior-auth-approvedHandleTargetBottom_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-abandoned", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-abandoned", "targetHandle": + "HandleTargetBottom_prior-auth-approved", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcTop_40cd6e6c-c21c-45bf-b94c-62092b2b2510-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_continuing-old-treatment", + "targetHandle": "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-stopping-old-treatmentHandleTargetLeft_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36", + "type": "smoothstep", "source": "start", "target": "stopping-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_stopping-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-continuing-old-treatmentHandleTargetLeft_40cd6e6c-c21c-45bf-b94c-62092b2b2510", + "type": "smoothstep", "source": "start", "target": "continuing-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_continuing-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-approvedHandleSrcTop_7d04e809-9419-4673-800b-ea2c3d7c04aa-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "prior-auth-approved", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-approved", "targetHandle": + "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, {"id": + "consent-requested", "data": {"type": "DEFAULT", "label": "Consent Requested"}, + "type": "graphNode", "position": {"x": 460, "y": -40}}, {"id": "consent-received", + "data": {"type": "DEFAULT", "label": "Consent Received"}, "type": "graphNode", + "position": {"x": 640, "y": -40}}, {"id": "reactflow__edge-consent-receivedHandleSrcRight_2e7445fb-8611-43bd-b750-af720c1530c1-records-requestedHandleTargetLeft_99edae56-fbb6-4bd5-95d0-a02e8b53c097", + "type": "smoothstep", "source": "consent-received", "target": "records-requested", + "animated": true, "sourceHandle": "HandleSrcRight_consent-received", "targetHandle": + "HandleTargetLeft_records-requested", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-consent-requestedHandleSrcRight_b56feb59-d9ad-46e7-8741-a20ad73112b7-consent-receivedHandleTargetLeft_2e7445fb-8611-43bd-b750-af720c1530c1", + "type": "smoothstep", "source": "consent-requested", "target": "consent-received", + "animated": true, "sourceHandle": "HandleSrcRight_consent-requested", "targetHandle": + "HandleTargetLeft_consent-received", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-startHandleSrcTop_712c1b68-4ccd-4f94-8641-5721b6148ed8-consent-requestedHandleTargetLeft_b56feb59-d9ad-46e7-8741-a20ad73112b7", + "type": "smoothstep", "source": "start", "target": "consent-requested", "animated": + true, "sourceHandle": "HandleSrcTop_start", "targetHandle": "HandleTargetLeft_consent-requested", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-target-2-patient", "title": + "Target 2 Patient", "description": "Delayers - en route to top of treatment.", + "phases": [{"name": "start", "title": "Start", "type": "START", "description": + "", "autoFinishProgram": false, "navigateTo": [{"name": "finish"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}], "nodes": [{"id": "start", "data": {"label": "Start"}, + "type": "graphNode", "position": {"x": 20, "y": 20}}, {"id": "finish", "data": + {"type": "FINISH", "label": "Finish"}, "type": "graphNode", "position": {"x": + 300, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_713b0fea-09cb-4c09-98da-bcb71c6cc9e5-finishHandleTargetLeft_d0fe8672-eafd-4b25-98b8-8845e89953a8", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-non-target-patient", "title": + "Non-Target Patient", "description": "All other non-target patients that do + not meet the criteria for other care plans.", "phases": [{"name": "start", + "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}]}, {"name": "finish", "title": "Finish", + "type": "FINISH", "description": "", "autoFinishProgram": false, "navigateTo": + []}], "nodes": [{"id": "start", "data": {"label": "Start"}, "type": "graphNode", + "position": {"x": 20, "y": 20}}, {"id": "finish", "data": {"label": "Finish"}, + "type": "graphNode", "position": {"x": 1520, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_34f0e25d-bb67-4d65-9dd2-b7bca6e1bd73-finishHandleTargetLeft_4c1007b4-98fa-45fc-b64b-678f7fbc880a", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}]' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:15 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '12829' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + response: + body: + string: '{"id": "77d60b23-6d23-4292-b007-836a0b14be8f", "createdByName": "createdByName_REDACTED_9f40c537-90c1-4de8-a830-d3f25be8348d", + "createdAt": "2023-10-31T02:10:16.204Z", "updatedByName": "updatedByName_REDACTED_694a7649-af7b-44b4-8e33-4f70c82cd43a", + "updatedAt": "2023-10-31T02:10:16.210Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:10:16.209Z", + "createdBy": "createdBy_REDACTED_b582ffef-4dfa-442e-851a-74b4cdcef786", "createdByName": + "createdByName_REDACTED_d41d8d98-b425-47e6-9290-7d204d008ea4", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:10:16.209Z", "createdBy": "createdBy_REDACTED_5cc41318-2817-47b2-a3ce-a0a9384e3431", + "createdByName": "createdByName_REDACTED_c4fb329d-791a-47c0-897d-f1de24dcf457", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:16 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/TestProgram.test_update.yaml b/test/cassettes/TestProgram.test_update.yaml new file mode 100644 index 0000000..0421980 --- /dev/null +++ b/test/cassettes/TestProgram.test_update.yaml @@ -0,0 +1,276 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_9a3dfce4-1178-4f45-8e58-f683604bd00f + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/formations/current/programs?page=0 + response: + body: + string: '[{"name": "prog-target-patient", "title": "Target Patient", "description": + "Moderate to severe patients, either on biologics or oral treatment.", "phases": + [{"name": "start", "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}, {"name": "continuing-old-treatment"}, + {"name": "stopping-old-treatment"}, {"name": "consent-requested"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "records-requested", "title": "Records + Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": false, + "navigateTo": [{"name": "records-received"}]}, {"name": "records-received", + "title": "Records Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": []}, {"name": "starting-new-treatment", "title": "Starting + New Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, + {"name": "continuing-old-treatment", "title": "Continuing Old Treatment", + "type": "DEFAULT", "description": "", "autoFinishProgram": false, "navigateTo": + [{"name": "prior-auth-requested"}, {"name": "sent-to-pharmacy"}]}, {"name": + "prior-auth-requested", "title": "Prior Auth Requested", "type": "DEFAULT", + "description": "", "autoFinishProgram": false, "navigateTo": [{"name": "prior-auth-approved"}, + {"name": "prior-auth-abandoned"}]}, {"name": "prior-auth-approved", "title": + "Prior Auth Approved", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "sent-to-pharmacy"}]}, {"name": "prior-auth-abandoned", + "title": "Prior Auth Abandoned", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "prior-auth-approved"}]}, {"name": "sent-to-pharmacy", + "title": "Sent to Pharmacy", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "confirmed-patient-filled"}]}, {"name": "confirmed-patient-filled", + "title": "Confirmed Patient Filled", "type": "DEFAULT", "description": "", + "autoFinishProgram": false, "navigateTo": []}, {"name": "stopping-old-treatment", + "title": "Stopping Old Treatment", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "starting-new-treatment"}]}, {"name": "consent-requested", + "title": "Consent Requested", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "consent-received"}]}, {"name": "consent-received", + "title": "Consent Received", "type": "DEFAULT", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "records-requested"}]}], "nodes": [{"id": "start", + "data": {"type": "START", "label": "Start"}, "type": "graphNode", "position": + {"x": 340, "y": 20}}, {"id": "finish", "data": {"type": "FINISH", "label": + "Finish"}, "type": "graphNode", "position": {"x": 1120, "y": 20}}, {"id": + "reactflow__edge-startHandleSrcRight_025adb09-c24a-45f9-b5a5-d1a44450ff43-finishHandleTargetLeft_5f5f5e64-5959-46b2-8e36-c85a86e60456", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}, {"id": "records-requested", "data": {"type": + "DEFAULT", "label": "Records Requested"}, "type": "graphNode", "position": + {"x": 800, "y": -40}}, {"id": "records-received", "data": {"type": "DEFAULT", + "label": "Records Received"}, "type": "graphNode", "position": {"x": 980, + "y": -40}}, {"id": "starting-new-treatment", "data": {"type": "DEFAULT", "label": + "Starting New Treatment"}, "type": "graphNode", "position": {"x": 640, "y": + 80}}, {"id": "continuing-old-treatment", "data": {"type": "DEFAULT", "label": + "Continuing Old Treatment"}, "type": "graphNode", "position": {"x": 440, "y": + 140}}, {"id": "prior-auth-requested", "data": {"type": "DEFAULT", "label": + "Prior Auth Requested"}, "type": "graphNode", "position": {"x": 660, "y": + 160}}, {"id": "prior-auth-approved", "data": {"type": "DEFAULT", "label": + "Prior Auth Approved"}, "type": "graphNode", "position": {"x": 840, "y": 160}}, + {"id": "prior-auth-abandoned", "data": {"type": "DEFAULT", "label": "Prior + Auth Abandoned"}, "type": "graphNode", "position": {"x": 760, "y": 220}}, + {"id": "sent-to-pharmacy", "data": {"type": "DEFAULT", "label": "Sent to Pharmacy"}, + "type": "graphNode", "position": {"x": 860, "y": 80}}, {"id": "confirmed-patient-filled", + "data": {"type": "DEFAULT", "label": "Confirmed Patient Filled"}, "type": + "graphNode", "position": {"x": 1020, "y": 80}}, {"id": "reactflow__edge-records-requestedHandleSrcRight_6672da4b-34f4-42fb-81b3-5d7e785c5e1d-records-receivedHandleTargetLeft_1c3c44da-11c5-4da6-9e79-94f1eb86a5c5", + "type": "smoothstep", "source": "records-requested", "target": "records-received", + "animated": true, "sourceHandle": "HandleSrcRight_records-requested", "targetHandle": + "HandleTargetLeft_records-received", "arrowHeadType": "arrowclosed"}, {"id": + "stopping-old-treatment", "data": {"type": "DEFAULT", "label": "Stopping Old + Treatment"}, "type": "graphNode", "position": {"x": 440, "y": 80}}, {"id": + "reactflow__edge-stopping-old-treatmentHandleSrcRight_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36-starting-new-treatmentHandleTargetLeft_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6", + "type": "smoothstep", "source": "stopping-old-treatment", "target": "starting-new-treatment", + "animated": true, "sourceHandle": "HandleSrcRight_stopping-old-treatment", + "targetHandle": "HandleTargetLeft_starting-new-treatment", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-starting-new-treatmentHandleSrcBottom_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-prior-auth-requestedHandleTargetTop_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "starting-new-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcBottom_starting-new-treatment", + "targetHandle": "HandleTargetTop_prior-auth-requested", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcRight_40cd6e6c-c21c-45bf-b94c-62092b2b2510-prior-auth-requestedHandleTargetLeft_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "prior-auth-requested", + "animated": true, "sourceHandle": "HandleSrcRight_continuing-old-treatment", + "targetHandle": "HandleTargetLeft_prior-auth-requested", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-requestedHandleSrcRight_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-approvedHandleTargetLeft_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcRight_prior-auth-requested", "targetHandle": + "HandleTargetLeft_prior-auth-approved", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-sent-to-pharmacyHandleSrcRight_e1ad3528-270a-45bf-9757-91fe3ecb9d23-confirmed-patient-filledHandleTargetLeft_2505253d-32d6-4020-8e16-722b4813a5a7", + "type": "smoothstep", "source": "sent-to-pharmacy", "target": "confirmed-patient-filled", + "animated": true, "sourceHandle": "HandleSrcRight_sent-to-pharmacy", "targetHandle": + "HandleTargetLeft_confirmed-patient-filled", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-starting-new-treatmentHandleSrcRight_0fec4bd7-99f2-4f0f-b21f-7875bf7b00a6-sent-to-pharmacyHandleTargetLeft_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "starting-new-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcRight_starting-new-treatment", + "targetHandle": "HandleTargetLeft_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-requestedHandleSrcBottom_d27d5d34-3c7d-4a7d-b222-25b99dbeeb10-prior-auth-abandonedHandleTargetLeft_982c7e02-2cce-4202-b72c-bee08f44e11a", + "type": "smoothstep", "source": "prior-auth-requested", "target": "prior-auth-abandoned", + "animated": true, "sourceHandle": "HandleSrcBottom_prior-auth-requested", + "targetHandle": "HandleTargetLeft_prior-auth-abandoned", "arrowHeadType": + "arrowclosed"}, {"id": "reactflow__edge-prior-auth-abandonedHandleSrcTop_982c7e02-2cce-4202-b72c-bee08f44e11a-prior-auth-approvedHandleTargetBottom_7d04e809-9419-4673-800b-ea2c3d7c04aa", + "type": "smoothstep", "source": "prior-auth-abandoned", "target": "prior-auth-approved", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-abandoned", "targetHandle": + "HandleTargetBottom_prior-auth-approved", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-continuing-old-treatmentHandleSrcTop_40cd6e6c-c21c-45bf-b94c-62092b2b2510-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "continuing-old-treatment", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_continuing-old-treatment", + "targetHandle": "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-stopping-old-treatmentHandleTargetLeft_26bbcfc7-e81d-48ac-88aa-7bdcb209dc36", + "type": "smoothstep", "source": "start", "target": "stopping-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_stopping-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-startHandleSrcBottom_a8a336be-e2ef-4336-bb18-0dfa4b5b9727-continuing-old-treatmentHandleTargetLeft_40cd6e6c-c21c-45bf-b94c-62092b2b2510", + "type": "smoothstep", "source": "start", "target": "continuing-old-treatment", + "animated": true, "sourceHandle": "HandleSrcBottom_start", "targetHandle": + "HandleTargetLeft_continuing-old-treatment", "arrowHeadType": "arrowclosed"}, + {"id": "reactflow__edge-prior-auth-approvedHandleSrcTop_7d04e809-9419-4673-800b-ea2c3d7c04aa-sent-to-pharmacyHandleTargetBottom_e1ad3528-270a-45bf-9757-91fe3ecb9d23", + "type": "smoothstep", "source": "prior-auth-approved", "target": "sent-to-pharmacy", + "animated": true, "sourceHandle": "HandleSrcTop_prior-auth-approved", "targetHandle": + "HandleTargetBottom_sent-to-pharmacy", "arrowHeadType": "arrowclosed"}, {"id": + "consent-requested", "data": {"type": "DEFAULT", "label": "Consent Requested"}, + "type": "graphNode", "position": {"x": 460, "y": -40}}, {"id": "consent-received", + "data": {"type": "DEFAULT", "label": "Consent Received"}, "type": "graphNode", + "position": {"x": 640, "y": -40}}, {"id": "reactflow__edge-consent-receivedHandleSrcRight_2e7445fb-8611-43bd-b750-af720c1530c1-records-requestedHandleTargetLeft_99edae56-fbb6-4bd5-95d0-a02e8b53c097", + "type": "smoothstep", "source": "consent-received", "target": "records-requested", + "animated": true, "sourceHandle": "HandleSrcRight_consent-received", "targetHandle": + "HandleTargetLeft_records-requested", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-consent-requestedHandleSrcRight_b56feb59-d9ad-46e7-8741-a20ad73112b7-consent-receivedHandleTargetLeft_2e7445fb-8611-43bd-b750-af720c1530c1", + "type": "smoothstep", "source": "consent-requested", "target": "consent-received", + "animated": true, "sourceHandle": "HandleSrcRight_consent-requested", "targetHandle": + "HandleTargetLeft_consent-received", "arrowHeadType": "arrowclosed"}, {"id": + "reactflow__edge-startHandleSrcTop_712c1b68-4ccd-4f94-8641-5721b6148ed8-consent-requestedHandleTargetLeft_b56feb59-d9ad-46e7-8741-a20ad73112b7", + "type": "smoothstep", "source": "start", "target": "consent-requested", "animated": + true, "sourceHandle": "HandleSrcTop_start", "targetHandle": "HandleTargetLeft_consent-requested", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-target-2-patient", "title": + "Target 2 Patient", "description": "Delayers - en route to top of treatment.", + "phases": [{"name": "start", "title": "Start", "type": "START", "description": + "", "autoFinishProgram": false, "navigateTo": [{"name": "finish"}]}, {"name": + "finish", "title": "Finish", "type": "FINISH", "description": "", "autoFinishProgram": + false, "navigateTo": []}], "nodes": [{"id": "start", "data": {"label": "Start"}, + "type": "graphNode", "position": {"x": 20, "y": 20}}, {"id": "finish", "data": + {"type": "FINISH", "label": "Finish"}, "type": "graphNode", "position": {"x": + 300, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_713b0fea-09cb-4c09-98da-bcb71c6cc9e5-finishHandleTargetLeft_d0fe8672-eafd-4b25-98b8-8845e89953a8", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}, {"name": "prog-non-target-patient", "title": + "Non-Target Patient", "description": "All other non-target patients that do + not meet the criteria for other care plans.", "phases": [{"name": "start", + "title": "Start", "type": "START", "description": "", "autoFinishProgram": + false, "navigateTo": [{"name": "finish"}]}, {"name": "finish", "title": "Finish", + "type": "FINISH", "description": "", "autoFinishProgram": false, "navigateTo": + []}], "nodes": [{"id": "start", "data": {"label": "Start"}, "type": "graphNode", + "position": {"x": 20, "y": 20}}, {"id": "finish", "data": {"label": "Finish"}, + "type": "graphNode", "position": {"x": 1520, "y": 20}}, {"id": "reactflow__edge-startHandleSrcRight_34f0e25d-bb67-4d65-9dd2-b7bca6e1bd73-finishHandleTargetLeft_4c1007b4-98fa-45fc-b64b-678f7fbc880a", + "type": "smoothstep", "source": "start", "target": "finish", "animated": true, + "sourceHandle": "HandleSrcRight_start", "targetHandle": "HandleTargetLeft_finish", + "arrowHeadType": "arrowclosed"}]}]' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:11:02 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '12829' + status: + code: 200 + message: OK +- request: + body: '{"phaseName": "finish"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_9a3dfce4-1178-4f45-8e58-f683604bd00f + Connection: + - keep-alive + Content-Length: + - '23' + Content-Type: + - application/json + User-Agent: + - python-welkin/0.1.1 + method: PATCH + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/prog-target-patient + response: + body: + string: '{"id": "77d60b23-6d23-4292-b007-836a0b14be8f", "createdByName": "createdByName_REDACTED_46a14ef7-aa16-4286-9a44-d1a4e91a5cfe", + "createdAt": "2023-10-31T02:10:16.204Z", "updatedByName": "updatedByName_REDACTED_0ed30a91-f19c-4882-9aa9-2d333d4e0acd", + "updatedAt": "2023-10-31T02:11:02.904Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:11:02.903Z", + "createdBy": "createdBy_REDACTED_0f85b917-5b1d-4baf-be56-c39501eebc5d", "createdByName": + "createdByName_REDACTED_157ef5b7-2ab8-48c8-8b02-582334267edf", "name": "finish", + "title": "Finish", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:10:16.209Z", "createdBy": "createdBy_REDACTED_cfea345f-fa4a-4a4e-a6c4-2b920196b401", + "createdByName": "createdByName_REDACTED_a2abcbc0-89b2-4593-8d30-2d865fc40141", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}, {"timestamp": "2023-10-31T02:11:02.903Z", "createdBy": + "createdBy_REDACTED_cd508893-1e9b-42d1-9496-255dea703f21", "createdByName": + "createdByName_REDACTED_a585ae59-ef98-40d8-8b41-2040869dcd65", "name": "finish", + "title": "Finish", "description": "", "currentVersion": "92", "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:11:02 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '1187' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/TestPrograms.test_read.yaml b/test/cassettes/TestPrograms.test_read.yaml new file mode 100644 index 0000000..6872130 --- /dev/null +++ b/test/cassettes/TestPrograms.test_read.yaml @@ -0,0 +1,75 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_cdbf8879-481a-4cdd-af08-c5a0fc54f3b1 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs?page=0 + response: + body: + string: '{"data": [{"id": null, "createdByName": "createdByName_REDACTED_81a5b561-afc0-4fb3-804b-9baee07b6a8c", + "createdAt": null, "updatedByName": "updatedByName_REDACTED_02620078-7370-4899-852b-61b8f855a48d", + "updatedAt": null, "programName": "prog-target-2-patient", "programTitle": + "Target 2 Patient", "programDescription": "Delayers - en route to top of treatment.", + "assigned": false, "patientId": null, "currentPhase": null, "status": null, + "compatibleWithCurrentVersion": false, "pathHistory": []}, {"id": null, "createdByName": + "createdByName_REDACTED_6be765b8-0e18-425e-ae4e-88092280c9fe", "createdAt": + null, "updatedByName": "updatedByName_REDACTED_85563121-fbcc-4f10-912e-cfc75bc595e1", + "updatedAt": null, "programName": "prog-non-target-patient", "programTitle": + "Non-Target Patient", "programDescription": "All other non-target patients + that do not meet the criteria for other care plans.", "assigned": false, "patientId": + null, "currentPhase": null, "status": null, "compatibleWithCurrentVersion": + false, "pathHistory": []}, {"id": null, "createdByName": "createdByName_REDACTED_6ed5abd3-74fd-4071-b732-c204b1243731", + "createdAt": null, "updatedByName": "updatedByName_REDACTED_932a65a7-1273-4d8b-9cbe-4068dddc95ed", + "updatedAt": null, "programName": "prog-target-patient", "programTitle": "Target + Patient", "programDescription": "Moderate to severe patients, either on biologics + or oral treatment.", "assigned": false, "patientId": null, "currentPhase": + null, "status": null, "compatibleWithCurrentVersion": false, "pathHistory": + []}], "metaInfo": {"page": 0, "pageSize": 20, "totalElements": 3, "numberOfElements": + 3, "lastPage": true, "firstPage": true, "totalPages": 1}}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:15 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '1239' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/patient__TestProgram.test_delete.yaml b/test/cassettes/fixtures/patient__TestProgram.test_delete.yaml new file mode 100644 index 0000000..5e4a3f0 --- /dev/null +++ b/test/cassettes/fixtures/patient__TestProgram.test_delete.yaml @@ -0,0 +1,84 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_cdbf8879-481a-4cdd-af08-c5a0fc54f3b1 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/12345678-1234-1234-1234-1234567890ab?type=EGUID + response: + body: + string: '{"createdByName": "createdByName_REDACTED_3787d4d8-394d-44dc-b136-9b860521a0af", + "lastName": "Patient", "country": null, "secondaryEmail": null, "gender": + "UNKNOWN", "city": null, "timezone": null, "careTeamMembers": [], "secondaryPhoneCapabilities": + [], "createdAt": "2023-10-27T23:19:20.506Z", "accessCode": null, "addressLine1": + null, "addressLine2": null, "id": "de5e1a93-70b0-4ed4-868f-3854becc383c", + "state": null, "secondaryLanguage": null, "email": "test.patient@example.com", + "careTeam": [], "updatedAt": "2023-10-27T23:19:20.506Z", "primaryPhoneCapabilities": + [], "pointOfContact": null, "zip": null, "updatedBy": "updatedBy_REDACTED_397d6410-0119-4452-a443-ce14d8b19119", + "preferableInstancePhoneId": null, "updatedByName": "updatedByName_REDACTED_0f50023d-76aa-4747-81a8-0e880cf9053d", + "mrn": null, "externalId": null, "externalGuid": "12345678-1234-1234-1234-1234567890ab", + "patientPrograms": [{"id": "53e7f5de-67d7-475f-9443-6b4dedf14848", "createdByName": + "createdByName_REDACTED_8fe5924d-f27c-473a-a0d8-04ae4b480ffe", "createdAt": + "2023-10-31T02:05:28.717Z", "updatedByName": "updatedByName_REDACTED_86a500dd-5193-4882-8186-cf5ab9ea2115", + "updatedAt": "2023-10-31T02:05:28.721Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:05:28.720Z", + "createdBy": "createdBy_REDACTED_83e4e86f-cbf2-46d0-b244-337c905318f0", "createdByName": + "createdByName_REDACTED_ea549410-716b-487e-9267-7f2ab471a7e8", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:05:28.720Z", "createdBy": "createdBy_REDACTED_153f6c5f-36a1-4220-b28c-0ff52e023be7", + "createdByName": "createdByName_REDACTED_37ffb982-e10f-4f22-b86c-bfa58fd5af47", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}], "nric": null, "birthDate": null, "cadence": [], "firstName": + "Test", "patientRegionTitle": null, "createdBy": "createdBy_REDACTED_57038b8c-441a-43f6-8530-2342b4b511ce", + "phone": null, "middleName": null, "patientTerritories": [], "patientRegion": + null, "maritalStatus": "UKN", "primaryLanguage": "ENGLISH", "secondaryPhone": + null, "patientTerritory": null}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:14 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '2034' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/patient__TestProgram.test_read[id].yaml b/test/cassettes/fixtures/patient__TestProgram.test_read[id].yaml new file mode 100644 index 0000000..8699f8b --- /dev/null +++ b/test/cassettes/fixtures/patient__TestProgram.test_read[id].yaml @@ -0,0 +1,84 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/12345678-1234-1234-1234-1234567890ab?type=EGUID + response: + body: + string: '{"createdByName": "createdByName_REDACTED_7110ecfd-7888-4132-8dcc-c892e7fb442d", + "lastName": "Patient", "country": null, "secondaryEmail": null, "gender": + "UNKNOWN", "city": null, "timezone": null, "careTeamMembers": [], "secondaryPhoneCapabilities": + [], "createdAt": "2023-10-27T23:19:20.506Z", "accessCode": null, "addressLine1": + null, "addressLine2": null, "id": "de5e1a93-70b0-4ed4-868f-3854becc383c", + "state": null, "secondaryLanguage": null, "email": "test.patient@example.com", + "careTeam": [], "updatedAt": "2023-10-27T23:19:20.506Z", "primaryPhoneCapabilities": + [], "pointOfContact": null, "zip": null, "updatedBy": "updatedBy_REDACTED_61dfe2a9-0a67-4b44-bc4d-179a22559577", + "preferableInstancePhoneId": null, "updatedByName": "updatedByName_REDACTED_9734b0ff-3bdc-46da-baca-da61007e167c", + "mrn": null, "externalId": null, "externalGuid": "12345678-1234-1234-1234-1234567890ab", + "patientPrograms": [{"id": "53e7f5de-67d7-475f-9443-6b4dedf14848", "createdByName": + "createdByName_REDACTED_2e1d77c5-375d-46f3-ab99-3155452e72f5", "createdAt": + "2023-10-31T02:05:28.717Z", "updatedByName": "updatedByName_REDACTED_40a5a934-3e45-4737-afb1-9dc965b64471", + "updatedAt": "2023-10-31T02:05:28.721Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:05:28.720Z", + "createdBy": "createdBy_REDACTED_1aa62f75-0953-4b2b-a0ae-583c14b39bc4", "createdByName": + "createdByName_REDACTED_f49902c1-aee3-4586-9157-381b63a2ae76", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:05:28.720Z", "createdBy": "createdBy_REDACTED_ee8c682a-10ce-4116-8e2c-80f84cdb75e8", + "createdByName": "createdByName_REDACTED_ee114448-3e04-4152-9a1a-f742f6276a6a", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}], "nric": null, "birthDate": null, "cadence": [], "firstName": + "Test", "patientRegionTitle": null, "createdBy": "createdBy_REDACTED_3a280eb7-5af1-47dc-8e5e-c5f49bc375fd", + "phone": null, "middleName": null, "patientTerritories": [], "patientRegion": + null, "maritalStatus": "UKN", "primaryLanguage": "ENGLISH", "secondaryPhone": + null, "patientTerritory": null}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:14 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '2034' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/patient__test_program_read.yaml b/test/cassettes/fixtures/patient__TestProgram.test_read[programName].yaml similarity index 87% rename from test/cassettes/fixtures/patient__test_program_read.yaml rename to test/cassettes/fixtures/patient__TestProgram.test_read[programName].yaml index b92f301..0e6a5f8 100644 --- a/test/cassettes/fixtures/patient__test_program_read.yaml +++ b/test/cassettes/fixtures/patient__TestProgram.test_read[programName].yaml @@ -7,7 +7,7 @@ interactions: Accept-Encoding: - gzip, deflate Authorization: - - API_TOKEN_35e1fe22-32fa-4b05-abbf-bc5d1fb46440 + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 Connection: - keep-alive User-Agent: @@ -16,18 +16,18 @@ interactions: uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/12345678-1234-1234-1234-1234567890ab?type=EGUID response: body: - string: '{"createdByName": "createdByName_REDACTED_1843844d-59a3-4e88-ba9a-7935ee896082", + string: '{"createdByName": "createdByName_REDACTED_0c1a375e-fb29-465b-a0a3-f54e46c8d049", "lastName": "Patient", "country": null, "secondaryEmail": null, "gender": "UNKNOWN", "city": null, "timezone": null, "careTeamMembers": [], "secondaryPhoneCapabilities": [], "createdAt": "2023-10-27T23:19:20.506Z", "accessCode": null, "addressLine1": null, "addressLine2": null, "id": "de5e1a93-70b0-4ed4-868f-3854becc383c", "state": null, "secondaryLanguage": null, "email": "test.patient@example.com", "careTeam": [], "updatedAt": "2023-10-27T23:19:20.506Z", "primaryPhoneCapabilities": - [], "pointOfContact": null, "zip": null, "updatedBy": "updatedBy_REDACTED_c9f6370a-e068-441c-91c4-9ce5421a9887", - "preferableInstancePhoneId": null, "updatedByName": "updatedByName_REDACTED_87c90d81-8a1a-4a09-855c-710cc5fe5ca5", + [], "pointOfContact": null, "zip": null, "updatedBy": "updatedBy_REDACTED_524b5efd-76a4-4971-ba5e-6b4b7fe61ff5", + "preferableInstancePhoneId": null, "updatedByName": "updatedByName_REDACTED_2ba2f3e2-f75a-495d-87db-3bd55a298174", "mrn": null, "externalId": null, "externalGuid": "12345678-1234-1234-1234-1234567890ab", "patientPrograms": [], "nric": null, "birthDate": null, "cadence": [], "firstName": - "Test", "patientRegionTitle": null, "createdBy": "createdBy_REDACTED_7ffa726b-0d5e-4c2c-8f68-4a1af1b6e38b", + "Test", "patientRegionTitle": null, "createdBy": "createdBy_REDACTED_590dd304-97a1-471b-8abc-6a046d5542e9", "phone": null, "middleName": null, "patientTerritories": [], "patientRegion": null, "maritalStatus": "UKN", "primaryLanguage": "ENGLISH", "secondaryPhone": null, "patientTerritory": null}' @@ -49,7 +49,7 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Oct 2023 23:34:52 GMT + - Tue, 31 Oct 2023 02:10:15 GMT Expires: - '0' Pragma: diff --git a/test/cassettes/fixtures/patient__TestProgram.test_update.yaml b/test/cassettes/fixtures/patient__TestProgram.test_update.yaml new file mode 100644 index 0000000..9eba57c --- /dev/null +++ b/test/cassettes/fixtures/patient__TestProgram.test_update.yaml @@ -0,0 +1,84 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_7a764bd7-4131-4ef6-a102-6efd9c869a1c + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/12345678-1234-1234-1234-1234567890ab?type=EGUID + response: + body: + string: '{"createdByName": "createdByName_REDACTED_1db820cc-08a1-4598-aaa7-0bfa05012815", + "lastName": "Patient", "country": null, "secondaryEmail": null, "gender": + "UNKNOWN", "city": null, "timezone": null, "careTeamMembers": [], "secondaryPhoneCapabilities": + [], "createdAt": "2023-10-27T23:19:20.506Z", "accessCode": null, "addressLine1": + null, "addressLine2": null, "id": "de5e1a93-70b0-4ed4-868f-3854becc383c", + "state": null, "secondaryLanguage": null, "email": "test.patient@example.com", + "careTeam": [], "updatedAt": "2023-10-27T23:19:20.506Z", "primaryPhoneCapabilities": + [], "pointOfContact": null, "zip": null, "updatedBy": "updatedBy_REDACTED_22721fb2-a223-4c09-9563-e55254785a20", + "preferableInstancePhoneId": null, "updatedByName": "updatedByName_REDACTED_ebc09ed9-3d69-4e31-9486-db8f946a796a", + "mrn": null, "externalId": null, "externalGuid": "12345678-1234-1234-1234-1234567890ab", + "patientPrograms": [{"id": "53e7f5de-67d7-475f-9443-6b4dedf14848", "createdByName": + "createdByName_REDACTED_3e8a4c70-1021-4181-8314-c1cd5d24d2dd", "createdAt": + "2023-10-31T02:05:28.717Z", "updatedByName": "updatedByName_REDACTED_7675da11-62df-4823-b6dc-c4947ce9f238", + "updatedAt": "2023-10-31T02:05:28.721Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:05:28.720Z", + "createdBy": "createdBy_REDACTED_883b3c82-d17a-4384-85b6-e8d386667f46", "createdByName": + "createdByName_REDACTED_01addf2b-7b5e-47c2-821a-3e82ae4fd4a6", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:05:28.720Z", "createdBy": "createdBy_REDACTED_5914e5a6-0720-4195-8616-1eea59d66b39", + "createdByName": "createdByName_REDACTED_bfcca769-ca87-40f4-b8af-ed65555e9f93", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}], "nric": null, "birthDate": null, "cadence": [], "firstName": + "Test", "patientRegionTitle": null, "createdBy": "createdBy_REDACTED_d10ef850-31ef-4505-a7c8-05b5a48447b0", + "phone": null, "middleName": null, "patientTerritories": [], "patientRegion": + null, "maritalStatus": "UKN", "primaryLanguage": "ENGLISH", "secondaryPhone": + null, "patientTerritory": null}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:14 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '2034' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/patient__TestPrograms.test_read.yaml b/test/cassettes/fixtures/patient__TestPrograms.test_read.yaml new file mode 100644 index 0000000..125f7f7 --- /dev/null +++ b/test/cassettes/fixtures/patient__TestPrograms.test_read.yaml @@ -0,0 +1,70 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_cdbf8879-481a-4cdd-af08-c5a0fc54f3b1 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/12345678-1234-1234-1234-1234567890ab?type=EGUID + response: + body: + string: '{"createdByName": "createdByName_REDACTED_5a78395f-9a3c-49de-ab7b-23c2f37491a4", + "lastName": "Patient", "country": null, "secondaryEmail": null, "gender": + "UNKNOWN", "city": null, "timezone": null, "careTeamMembers": [], "secondaryPhoneCapabilities": + [], "createdAt": "2023-10-27T23:19:20.506Z", "accessCode": null, "addressLine1": + null, "addressLine2": null, "id": "de5e1a93-70b0-4ed4-868f-3854becc383c", + "state": null, "secondaryLanguage": null, "email": "test.patient@example.com", + "careTeam": [], "updatedAt": "2023-10-27T23:19:20.506Z", "primaryPhoneCapabilities": + [], "pointOfContact": null, "zip": null, "updatedBy": "updatedBy_REDACTED_b5975051-e9d1-4105-91c2-bcc61ed5ff90", + "preferableInstancePhoneId": null, "updatedByName": "updatedByName_REDACTED_dd32de08-52c1-4de8-b740-4dcf3562234c", + "mrn": null, "externalId": null, "externalGuid": "12345678-1234-1234-1234-1234567890ab", + "patientPrograms": [], "nric": null, "birthDate": null, "cadence": [], "firstName": + "Test", "patientRegionTitle": null, "createdBy": "createdBy_REDACTED_15d6858b-ec41-4bf4-b806-66412df4b677", + "phone": null, "middleName": null, "patientTerritories": [], "patientRegion": + null, "maritalStatus": "UKN", "primaryLanguage": "ENGLISH", "secondaryPhone": + null, "patientTerritory": null}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:15 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '1071' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/program__TestProgram.test_delete.yaml b/test/cassettes/fixtures/program__TestProgram.test_delete.yaml new file mode 100644 index 0000000..7e8cb75 --- /dev/null +++ b/test/cassettes/fixtures/program__TestProgram.test_delete.yaml @@ -0,0 +1,69 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_cdbf8879-481a-4cdd-af08-c5a0fc54f3b1 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + response: + body: + string: '{"id": "53e7f5de-67d7-475f-9443-6b4dedf14848", "createdByName": "createdByName_REDACTED_796f836c-892e-4b41-a6b6-046320abab2c", + "createdAt": "2023-10-31T02:05:28.717Z", "updatedByName": "updatedByName_REDACTED_af9c9fd6-5c9a-46df-b4c3-8f8941232c58", + "updatedAt": "2023-10-31T02:05:28.721Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:05:28.720Z", + "createdBy": "createdBy_REDACTED_901bd39a-a3b4-4e5c-98d6-89f796435e72", "createdByName": + "createdByName_REDACTED_88cee94f-bfec-45e9-a092-a9c4e20a6603", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:05:28.720Z", "createdBy": "createdBy_REDACTED_307a66b5-ff48-4612-80d7-43fdf1a8f702", + "createdByName": "createdByName_REDACTED_2ac3d8f7-e07c-4df8-b6fd-f7ad43003fdd", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:14 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/program__TestProgram.test_read[id].yaml b/test/cassettes/fixtures/program__TestProgram.test_read[id].yaml new file mode 100644 index 0000000..97bbebd --- /dev/null +++ b/test/cassettes/fixtures/program__TestProgram.test_read[id].yaml @@ -0,0 +1,69 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + response: + body: + string: '{"id": "53e7f5de-67d7-475f-9443-6b4dedf14848", "createdByName": "createdByName_REDACTED_bffddcd1-8dec-4f14-9a37-51a0ef394804", + "createdAt": "2023-10-31T02:05:28.717Z", "updatedByName": "updatedByName_REDACTED_974eb2ed-a7e6-4eb0-975b-b5060ad6b9bc", + "updatedAt": "2023-10-31T02:05:28.721Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:05:28.720Z", + "createdBy": "createdBy_REDACTED_f150d790-2185-45b9-935e-e5a3cd0bd0c2", "createdByName": + "createdByName_REDACTED_89468126-6416-4ec1-8eff-29a556d576b4", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:05:28.720Z", "createdBy": "createdBy_REDACTED_0a32843f-09ed-4257-8dd0-90d102c83afe", + "createdByName": "createdByName_REDACTED_760e9fd1-7526-4ca0-9efe-695e2130aec3", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:14 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/program__TestProgram.test_read[programName].yaml b/test/cassettes/fixtures/program__TestProgram.test_read[programName].yaml new file mode 100644 index 0000000..12cc81a --- /dev/null +++ b/test/cassettes/fixtures/program__TestProgram.test_read[programName].yaml @@ -0,0 +1,130 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + response: + body: + string: '[{"errorCode": "PATIENT_PROGRAM_NOT_FOUND", "componentType": "PATIENT_PROGRAM", + "message": "Patient related to program doesn''t exist", "details": {"programName": + "prog-target-patient", "patientId": "de5e1a93-70b0-4ed4-868f-3854becc383c", + "notStatus": "FINISHED"}, "date": "2023-10-31T02:10:16.035Z"}]' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:16 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '286' + status: + code: 404 + message: Not Found +- request: + body: '{"assigned": true, "phaseName": "start"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_81ee7581-0f2d-4ad6-a3a2-d81fcd1dd971 + Connection: + - keep-alive + Content-Length: + - '40' + Content-Type: + - application/json + User-Agent: + - python-welkin/0.1.1 + method: PATCH + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/prog-target-patient + response: + body: + string: '{"id": "77d60b23-6d23-4292-b007-836a0b14be8f", "createdByName": "createdByName_REDACTED_f2965ed7-e6d4-4911-9b8c-105be1f3bdc1", + "createdAt": "2023-10-31T02:10:16.204Z", "updatedByName": "updatedByName_REDACTED_cfe65b70-81c8-4c33-b79c-12674b135592", + "updatedAt": "2023-10-31T02:10:16.210Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:10:16.209Z", + "createdBy": "createdBy_REDACTED_c6e05235-517f-4c81-8f6f-25235fcb3ad8", "createdByName": + "createdByName_REDACTED_9b2881ee-0d32-420d-a6a9-99c591018ed2", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:10:16.209Z", "createdBy": "createdBy_REDACTED_3c4c585f-e200-4f42-8141-23716e911021", + "createdByName": "createdByName_REDACTED_a5e49667-4d24-4718-a656-98e96da012c5", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:10:16 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +version: 1 diff --git a/test/cassettes/fixtures/program__TestProgram.test_update.yaml b/test/cassettes/fixtures/program__TestProgram.test_update.yaml new file mode 100644 index 0000000..3bd3810 --- /dev/null +++ b/test/cassettes/fixtures/program__TestProgram.test_update.yaml @@ -0,0 +1,69 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - API_TOKEN_9a3dfce4-1178-4f45-8e58-f683604bd00f + Connection: + - keep-alive + User-Agent: + - python-welkin/0.1.1 + method: GET + uri: https://api.live.welkincloud.io/tenant_REDACTED/instance_REDACTED/patients/de5e1a93-70b0-4ed4-868f-3854becc383c/programs/current/prog-target-patient + response: + body: + string: '{"id": "77d60b23-6d23-4292-b007-836a0b14be8f", "createdByName": "createdByName_REDACTED_c39f6ee2-2030-4109-9e94-7469bdd4e8ae", + "createdAt": "2023-10-31T02:10:16.204Z", "updatedByName": "updatedByName_REDACTED_0477b685-93eb-4bae-b2a6-cd50bd8379ed", + "updatedAt": "2023-10-31T02:10:16.210Z", "programName": "prog-target-patient", + "programTitle": "Target Patient", "programDescription": "Moderate to severe + patients, either on biologics or oral treatment.", "assigned": true, "patientId": + "de5e1a93-70b0-4ed4-868f-3854becc383c", "currentPhase": {"timestamp": "2023-10-31T02:10:16.209Z", + "createdBy": "createdBy_REDACTED_9a567b17-258b-4e31-b497-c94fc64d3113", "createdByName": + "createdByName_REDACTED_3f03e301-06af-47b9-8659-4e759277ea87", "name": "start", + "title": "Start", "description": "", "currentVersion": "92", "deleted": false}, + "status": "IN_PROGRESS", "compatibleWithCurrentVersion": true, "pathHistory": + [{"timestamp": "2023-10-31T02:10:16.209Z", "createdBy": "createdBy_REDACTED_90df99b1-b748-490c-b7f5-42d6faa3d93e", + "createdByName": "createdByName_REDACTED_5aab39e6-d160-4fe8-afc9-951ec6919339", + "name": "start", "title": "Start", "description": "", "currentVersion": "92", + "deleted": false}]}' + headers: + Access-Control-Allow-Headers: + - authorization, content-type, xsrf-token, security-role + Access-Control-Allow-Methods: + - GET, POST, PUT, DELETE, PATCH, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - xsrf-token + Access-Control-Max-Age: + - '3600' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 31 Oct 2023 02:11:02 GMT + Expires: + - '0' + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + content-length: + - '963' + status: + code: 200 + message: OK +version: 1 diff --git a/test/conftest.py b/test/conftest.py index c87601d..654ddf2 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,3 +1,4 @@ +import inspect import json import os import uuid @@ -111,17 +112,27 @@ def hook(dct): @pytest.fixture -def patient(client, vcr, vcr_cassette_dir, vcr_cassette_name): +def fixture_cassette(vcr, vcr_cassette_dir, vcr_cassette_name): + def _cassette(): + caller_function_name = inspect.stack()[1].function + cassette_name = f"{caller_function_name}__{vcr_cassette_name}" + fixture_path = str(Path(vcr_cassette_dir, "fixtures")) + + return vcr.use_cassette(cassette_name, cassette_library_dir=fixture_path) + + return _cassette + + +@pytest.fixture +def patient(client, fixture_cassette): patient = client.Patient( firstName="Test", lastName="Patient", email="test.patient@example.com", externalGuid=uuid.UUID("12345678-1234-1234-1234-1234567890ab"), ) - cassette_name = f"patient__{vcr_cassette_name}" - fixture_path = str(Path(vcr_cassette_dir, "fixtures")) - with vcr.use_cassette(cassette_name, cassette_library_dir=fixture_path): + with fixture_cassette(): try: return patient.get() except WelkinHTTPError as exc: diff --git a/test/test_program.py b/test/test_program.py index 5abeddc..bd723b0 100644 --- a/test/test_program.py +++ b/test/test_program.py @@ -8,68 +8,82 @@ from welkin.models.formation import Program as FormationProgram -@pytest.fixture -def formation(client: Client) -> FormationProgram: - return client.Formation().Programs().get()[0] - - -@pytest.fixture -def first_phase(formation) -> str: - return formation.phases[0]["name"] - - -@pytest.fixture -def second_phase(formation) -> str: - return formation.phases[1]["name"] - - -@pytest.fixture -def model(patient: Patient, formation: FormationProgram, first_phase: str) -> Program: - model = patient.Program(programName=formation.name) - try: - model = model.get() - except WelkinHTTPError as exc: - if exc.response.status_code != HTTPStatus.NOT_FOUND: - raise - - return model.update(assigned=True, phaseName=first_phase) - - if len(model.pathHistory) > 1: - model.delete() - model = model.update(assigned=True, phaseName=first_phase) - - return model - - @pytest.mark.vcr class TestProgram: - @pytest.mark.parametrize("identifier", ["id", "programName"]) - def test_read(self, patient: Patient, model: Program, identifier: str): - program = patient.Program(**{identifier: getattr(model, identifier)}).get() - - assert isinstance(program, Program) - assert isinstance(program.currentPhase, ProgramPhase) - assert isinstance(program.pathHistory, ProgramPhases) - - assert program.id == model.id - - def test_update(self, patient: Patient, model: Program, second_phase: str): - assert model.currentPhase.name != second_phase - assert len(model.pathHistory) == 1 - - program = patient.Program(programName=model.programName).update( + @pytest.fixture + def formation(self, client: Client) -> FormationProgram: + return client.Formation().Programs().get()[0] + + @pytest.fixture + def first_phase(self, formation) -> str: + return formation.phases[0]["name"] + + @pytest.fixture + def second_phase(self, formation) -> str: + return formation.phases[1]["name"] + + @pytest.fixture + def program( + self, + patient: Patient, + formation: FormationProgram, + first_phase: str, + fixture_cassette, + ) -> Program: + program = patient.Program(programName=formation.name) + + with fixture_cassette(): + try: + program = program.get() + except WelkinHTTPError as exc: + if exc.response.status_code != HTTPStatus.NOT_FOUND: + raise + + return program.update(assigned=True, phaseName=first_phase) + + if len(program.pathHistory) > 1: + program.delete() + program = program.update(assigned=True, phaseName=first_phase) + + return program + + @pytest.mark.parametrize( + "identifier", + [ + "id", + "programName", + ], + ) + def test_read(self, patient: Patient, program: Program, identifier: str): + prog = patient.Program(**{identifier: getattr(program, identifier)}).get() + + assert isinstance(prog, Program) + assert isinstance(prog.currentPhase, ProgramPhase) + assert isinstance(prog.pathHistory, ProgramPhases) + + assert prog.id == program.id + + def test_read_no_id(self, client): + with pytest.raises(ValueError): + client.Patient(id="notarealid").Program().get() + + def test_update(self, patient: Patient, program: Program, second_phase: str): + assert program.currentPhase.name != second_phase + assert len(program.pathHistory) == 1 + + prog = patient.Program(programName=program.programName).update( phaseName=second_phase ) - assert program.currentPhase.name == second_phase - assert program.currentPhase.name != model.currentPhase.name - assert len(program.pathHistory) == 2 + assert prog.currentPhase.name == second_phase + assert prog.currentPhase.name != program.currentPhase.name + assert len(prog.pathHistory) == 2 - def test_delete(self, patient: Patient, model: Program): - program = patient.Program(id=model.id) - program.delete() + def test_delete(self, patient: Patient, program: Program): + prog = patient.Program(id=program.id) + prog.delete() with pytest.raises(WelkinHTTPError) as excinfo: - program.get() + prog.get() assert excinfo.value.response.status_code == 404 From e56ec4a6fc695ad81f113b6952ce94109cee8159 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Mon, 30 Oct 2023 19:17:20 -0700 Subject: [PATCH 23/48] Remove .envrc --- .envrc | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .envrc diff --git a/.envrc b/.envrc deleted file mode 100644 index fe7c01a..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -dotenv From bc41a26ca37e0b839aa968f16f79868011a06f16 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Mon, 30 Oct 2023 19:19:57 -0700 Subject: [PATCH 24/48] Revert import change --- welkin/client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/welkin/client.py b/welkin/client.py index 22e58d6..e95e1ed 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -11,10 +11,10 @@ from requests.compat import urljoin from requests.packages.urllib3.util.retry import Retry # type: ignore -from . import __version__, models -from .authentication import WelkinAuth -from .exceptions import WelkinHTTPError -from .util import _build_resources, clean_request_params, clean_request_payload +from welkin import __version__, models +from welkin.authentication import WelkinAuth +from welkin.exceptions import WelkinHTTPError +from welkin.util import _build_resources, clean_request_params, clean_request_payload logger = logging.getLogger(__name__) From dd8b754a562b8391cd5cf52448e1e394d7e2e486 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 10:25:26 -0700 Subject: [PATCH 25/48] Remove old shelve dbm on error --- test/test_authentication.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/test_authentication.py b/test/test_authentication.py index b410c47..9d731ac 100644 --- a/test/test_authentication.py +++ b/test/test_authentication.py @@ -1,4 +1,5 @@ import dbm +from pathlib import Path from requests import Request @@ -11,6 +12,12 @@ def auth_class(client): auth.tenant = "test_tenant" auth.token_method = lambda: {"token": "API_TOKEN"} + try: + auth.token + except dbm.error: + Path(DB_PATH).unlink() + return auth_class(client) + return auth From e658124ae12ccc601e33ecf0b468984c6303ebb5 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 10:31:41 -0700 Subject: [PATCH 26/48] Add `pre-commit` --- .github/workflows/pre-commit-autoupdate.yaml | 26 +++ .github/workflows/pre-commit.yaml | 14 ++ .github/workflows/test.yaml | 7 +- .pre-commit-config.yaml | 28 +++ poetry.lock | 171 ++++++++++++------- pyproject.toml | 3 +- test/test_document.py | 1 - welkin/models/assessment.py | 1 - welkin/models/calendar.py | 1 - welkin/models/cdt.py | 1 - welkin/models/email.py | 1 - welkin/models/sms.py | 1 - 12 files changed, 181 insertions(+), 74 deletions(-) create mode 100644 .github/workflows/pre-commit-autoupdate.yaml create mode 100644 .github/workflows/pre-commit.yaml create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/pre-commit-autoupdate.yaml b/.github/workflows/pre-commit-autoupdate.yaml new file mode 100644 index 0000000..4d1e42f --- /dev/null +++ b/.github/workflows/pre-commit-autoupdate.yaml @@ -0,0 +1,26 @@ +name: Pre-commit auto-update + +on: + # every day at midnight + schedule: + - cron: "0 0 * * *" + # on demand + workflow_dispatch: + +jobs: + auto-update: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + + - uses: browniebroke/pre-commit-autoupdate-action@main + + - uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: update/pre-commit-hooks + title: Update pre-commit hooks + commit-message: "chore: update pre-commit hooks" + body: Update versions of pre-commit hooks to latest version. diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000..ec4d9b3 --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,14 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e8fb4f1..7d955ba 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -52,5 +52,8 @@ jobs: - name: Run tests run: poetry run pytest --cov - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 + - name: Pytest coverage comment + uses: MishaKav/pytest-coverage-comment@main + with: + pytest-coverage-path: ./pytest-coverage.txt + junitxml-path: ./pytest.xml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..65bfc05 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,28 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-yaml + args: [--unsafe] + - id: debug-statements + - id: mixed-line-ending + + - repo: https://github.com/pycqa/doc8 + rev: v1.1.1 + hooks: + - id: doc8 + entry: ./scripts/run_hook.py apps/rind python -m doc8 + exclude: ^(?!(apps/rind)).*$ + + ## Python + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + types: [python] + + - repo: https://github.com/psf/black + rev: 23.9.1 + hooks: + - id: black + types: [python] diff --git a/poetry.lock b/poetry.lock index fe390e8..17f0062 100644 --- a/poetry.lock +++ b/poetry.lock @@ -36,7 +36,6 @@ files = [ [package.dependencies] lazy-object-proxy = ">=1.4.0" setuptools = ">=20.0" -typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} wrapt = ">=1.11,<2" @@ -81,7 +80,6 @@ mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] @@ -101,6 +99,17 @@ files = [ {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + [[package]] name = "charset-normalizer" version = "3.2.0" @@ -198,7 +207,6 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "colorama" @@ -286,6 +294,17 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] +[[package]] +name = "distlib" +version = "0.3.7" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, + {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, +] + [[package]] name = "docutils" version = "0.18.1" @@ -325,6 +344,36 @@ files = [ [package.extras] testing = ["hatch", "pre-commit", "pytest", "tox"] +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "identify" +version = "2.5.31" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.31-py2.py3-none-any.whl", hash = "sha256:90199cb9e7bd3c5407a9b7e81b4abec4bb9d249991c79439ec8af740afc6293d"}, + {file = "identify-2.5.31.tar.gz", hash = "sha256:7736b3c7a28233637e3c36550646fc6389bedd74ae84cb788200cc8e2dd60b75"}, +] + +[package.extras] +license = ["ukkonen"] + [[package]] name = "idna" version = "3.4" @@ -359,7 +408,6 @@ files = [ ] [package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] @@ -470,7 +518,6 @@ files = [ [package.dependencies] mdurl = ">=0.1,<1.0" -typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [package.extras] benchmarking = ["psutil", "pytest", "pytest-benchmark"] @@ -691,6 +738,20 @@ linkify = ["linkify-it-py (>=1.0,<2.0)"] rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"] +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + [[package]] name = "packaging" version = "23.1" @@ -724,9 +785,6 @@ files = [ {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.7.1", markers = "python_version < \"3.8\""} - [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] @@ -742,9 +800,6 @@ files = [ {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, ] -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] @@ -768,6 +823,24 @@ docs = ["sphinx (>=1.7.1)"] redis = ["redis"] tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)"] +[[package]] +name = "pre-commit" +version = "3.5.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, + {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + [[package]] name = "pygments" version = "2.16.1" @@ -796,7 +869,6 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" @@ -1220,56 +1292,6 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[[package]] -name = "typed-ast" -version = "1.5.5" -description = "a fork of Python 2 and 3 ast modules with type comment support" -optional = false -python-versions = ">=3.6" -files = [ - {file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"}, - {file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"}, - {file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"}, - {file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"}, - {file = "typed_ast-1.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5"}, - {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c"}, - {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa"}, - {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f"}, - {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d"}, - {file = "typed_ast-1.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5"}, - {file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"}, - {file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"}, - {file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"}, - {file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"}, - {file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"}, -] - [[package]] name = "typing-extensions" version = "4.7.1" @@ -1315,6 +1337,26 @@ urllib3 = {version = "<2", markers = "python_version < \"3.10\""} wrapt = "*" yarl = "*" +[[package]] +name = "virtualenv" +version = "20.24.6" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"}, + {file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<4" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [[package]] name = "wrapt" version = "1.15.0" @@ -1485,7 +1527,6 @@ files = [ [package.dependencies] idna = ">=2.0" multidict = ">=4.0" -typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [[package]] name = "zipp" @@ -1504,5 +1545,5 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" -python-versions = "^3.7" -content-hash = "bc16e9c8d9b067e6cee6870a30473e74a8c641305f5da551b9157f96c1546bee" +python-versions = "^3.8" +content-hash = "caf97d4d5754573e65ca424d70cb7b88ce87539f9da5bf36549c641cf454afb7" diff --git a/pyproject.toml b/pyproject.toml index 3bef3ca..f2f41a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ classifiers = [ "Bug Tracker" = "https://github.com/lightmatter/welkin-health/issues" [tool.poetry.dependencies] -python = "^3.7" +python = "^3.8" requests = "^2.28.1" portalocker = "^2.7.0" @@ -27,6 +27,7 @@ optional = true [tool.poetry.group.dev.dependencies] black = "^22.10.0" isort = "^5.10.1" +pre-commit = "^3.5.0" [tool.poetry.group.test] optional = true diff --git a/test/test_document.py b/test/test_document.py index 1e8b7d7..b52253b 100644 --- a/test/test_document.py +++ b/test/test_document.py @@ -82,7 +82,6 @@ def test_document_summary_create(client, vcr_cassette): reason="the bytes upload hits this issue in vcr: https://github.com/kevin1024/vcrpy/issues/660 but this test shows the correct implementation" ) def test_document_summary_files_create(client, vcr_cassette): - with open("test/walrus_uJGKbRm.jpeg", "rb") as f: files = client.DocumentSummaryFiles().create( patient_id="283f50d3-0840-426f-b07b-bd8e4ab76401", diff --git a/welkin/models/assessment.py b/welkin/models/assessment.py index 5efa5af..92d832d 100644 --- a/welkin/models/assessment.py +++ b/welkin/models/assessment.py @@ -49,7 +49,6 @@ class Assessments(Collection): iterator = PageableIterator def get(self, patient_id: str = None, encounter_id: str = None, *args, **kwargs): - root = f"{self._client.instance}/patients/" if self._parent: encounter_id = self._parent.id diff --git a/welkin/models/calendar.py b/welkin/models/calendar.py index 66ba660..90b1cff 100644 --- a/welkin/models/calendar.py +++ b/welkin/models/calendar.py @@ -131,7 +131,6 @@ def get( *args, **kwargs, ): - params = { "from": from_date, "to": to_date, diff --git a/welkin/models/cdt.py b/welkin/models/cdt.py index 98cf848..bb6353a 100644 --- a/welkin/models/cdt.py +++ b/welkin/models/cdt.py @@ -43,7 +43,6 @@ def get( *args, **kwargs, ): - root = "" if patient_id: root = f"patients/{patient_id}" diff --git a/welkin/models/email.py b/welkin/models/email.py index f900361..e26d2e2 100644 --- a/welkin/models/email.py +++ b/welkin/models/email.py @@ -19,7 +19,6 @@ class Emails(Collection): @patient_id def get(self, patient_id: str = None, sort: str = None, *args, **kwargs): - params = { "sort": sort, } diff --git a/welkin/models/sms.py b/welkin/models/sms.py index 6bcfcb0..3d96bd3 100644 --- a/welkin/models/sms.py +++ b/welkin/models/sms.py @@ -19,7 +19,6 @@ class SMSes(Collection): @patient_id def get(self, patient_id: str = None, sort: str = None, *args, **kwargs): - params = { "sort": sort, } From e08a09da5b809eaae42b8fa513c1524be5223212 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 10:33:43 -0700 Subject: [PATCH 27/48] Bump test matrix version --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7d955ba..b0dedee 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -15,7 +15,7 @@ jobs: - uses: snok/latest-python-versions@v1 id: get-python-versions-action with: - min-version: 3.7 + min-version: 3.8 test: needs: [get-python-versions] From c37ab881972af7c4165c9a71d9d365019e8cb82a Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 10:48:44 -0700 Subject: [PATCH 28/48] Fix coverage comment --- .github/workflows/test.yaml | 7 ++++++- .gitignore | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b0dedee..7859de4 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -50,10 +50,15 @@ jobs: run: poetry install --with test --no-interaction - name: Run tests - run: poetry run pytest --cov + run: | + poetry run pytest \ + --junitxml=pytest.xml \ + --cov-report=term-missing:skip-covered \ + --cov=app tests/ | tee pytest-coverage.txt - name: Pytest coverage comment uses: MishaKav/pytest-coverage-comment@main with: pytest-coverage-path: ./pytest-coverage.txt junitxml-path: ./pytest.xml + unique-id-for-comment: ${{ matrix.python-version }} diff --git a/.gitignore b/.gitignore index e61a850..5a4ec39 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,8 @@ coverage.xml *.py,cover .hypothesis/ .pytest_cache/ +pytest-coverage.txt +pytest.xml # Translations *.mo From 41ed3d74047991daf556bc6d60d414cfe5cabb27 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 10:51:14 -0700 Subject: [PATCH 29/48] Fix permissions --- .github/workflows/test.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7859de4..4fa5c82 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,6 +18,7 @@ jobs: min-version: 3.8 test: + permissions: write-all needs: [get-python-versions] runs-on: ubuntu-latest strategy: From b0ac9596f75194873f4eed77984046f32108fe85 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 10:54:30 -0700 Subject: [PATCH 30/48] Use lesser permissions --- .github/workflows/test.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4fa5c82..c3debd1 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,7 +18,8 @@ jobs: min-version: 3.8 test: - permissions: write-all + permissions: + pull-requests: write needs: [get-python-versions] runs-on: ubuntu-latest strategy: From f19c70cae212f7b644234ee6f446b278dc8e6283 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 11:03:54 -0700 Subject: [PATCH 31/48] Fix coverage report txt --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c3debd1..84dd492 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -56,7 +56,7 @@ jobs: poetry run pytest \ --junitxml=pytest.xml \ --cov-report=term-missing:skip-covered \ - --cov=app tests/ | tee pytest-coverage.txt + --cov=welkin test/ | tee pytest-coverage.txt - name: Pytest coverage comment uses: MishaKav/pytest-coverage-comment@main From 985bc4187386497525da10c6c0fb3400b8c7f727 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 11:12:18 -0700 Subject: [PATCH 32/48] Remove doc8 from precommit --- .pre-commit-config.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 65bfc05..db8f572 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,13 +7,6 @@ repos: - id: debug-statements - id: mixed-line-ending - - repo: https://github.com/pycqa/doc8 - rev: v1.1.1 - hooks: - - id: doc8 - entry: ./scripts/run_hook.py apps/rind python -m doc8 - exclude: ^(?!(apps/rind)).*$ - ## Python - repo: https://github.com/pycqa/isort rev: 5.12.0 From d8ef8b6366b8079ae608be4ba1ff85e89224343f Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 11:32:59 -0700 Subject: [PATCH 33/48] Rename models to avoid naming conflict --- ...ent_program__TestProgram.test_delete.yaml} | 0 ...t_program__TestProgram.test_read[id].yaml} | 0 ...__TestProgram.test_read[programName].yaml} | 0 ...ent_program__TestProgram.test_update.yaml} | 0 test/test_program.py | 58 +++++++++++-------- welkin/client.py | 4 +- welkin/models/__init__.py | 11 +++- welkin/models/patient.py | 6 +- welkin/models/program.py | 6 +- 9 files changed, 51 insertions(+), 34 deletions(-) rename test/cassettes/fixtures/{program__TestProgram.test_delete.yaml => patient_program__TestProgram.test_delete.yaml} (100%) rename test/cassettes/fixtures/{program__TestProgram.test_read[id].yaml => patient_program__TestProgram.test_read[id].yaml} (100%) rename test/cassettes/fixtures/{program__TestProgram.test_read[programName].yaml => patient_program__TestProgram.test_read[programName].yaml} (100%) rename test/cassettes/fixtures/{program__TestProgram.test_update.yaml => patient_program__TestProgram.test_update.yaml} (100%) diff --git a/test/cassettes/fixtures/program__TestProgram.test_delete.yaml b/test/cassettes/fixtures/patient_program__TestProgram.test_delete.yaml similarity index 100% rename from test/cassettes/fixtures/program__TestProgram.test_delete.yaml rename to test/cassettes/fixtures/patient_program__TestProgram.test_delete.yaml diff --git a/test/cassettes/fixtures/program__TestProgram.test_read[id].yaml b/test/cassettes/fixtures/patient_program__TestProgram.test_read[id].yaml similarity index 100% rename from test/cassettes/fixtures/program__TestProgram.test_read[id].yaml rename to test/cassettes/fixtures/patient_program__TestProgram.test_read[id].yaml diff --git a/test/cassettes/fixtures/program__TestProgram.test_read[programName].yaml b/test/cassettes/fixtures/patient_program__TestProgram.test_read[programName].yaml similarity index 100% rename from test/cassettes/fixtures/program__TestProgram.test_read[programName].yaml rename to test/cassettes/fixtures/patient_program__TestProgram.test_read[programName].yaml diff --git a/test/cassettes/fixtures/program__TestProgram.test_update.yaml b/test/cassettes/fixtures/patient_program__TestProgram.test_update.yaml similarity index 100% rename from test/cassettes/fixtures/program__TestProgram.test_update.yaml rename to test/cassettes/fixtures/patient_program__TestProgram.test_update.yaml diff --git a/test/test_program.py b/test/test_program.py index bd723b0..55a7c8f 100644 --- a/test/test_program.py +++ b/test/test_program.py @@ -4,14 +4,20 @@ from welkin import Client from welkin.exceptions import WelkinHTTPError -from welkin.models import Patient, Program, ProgramPhase, ProgramPhases, Programs -from welkin.models.formation import Program as FormationProgram +from welkin.models import ( + Patient, + PatientProgram, + PatientPrograms, + ProgramPhase, + ProgramPhases, +) +from welkin.models.formation import Program @pytest.mark.vcr class TestProgram: @pytest.fixture - def formation(self, client: Client) -> FormationProgram: + def formation(self, client: Client) -> Program: return client.Formation().Programs().get()[0] @pytest.fixture @@ -23,14 +29,14 @@ def second_phase(self, formation) -> str: return formation.phases[1]["name"] @pytest.fixture - def program( + def patient_program( self, patient: Patient, - formation: FormationProgram, + formation: Program, first_phase: str, fixture_cassette, - ) -> Program: - program = patient.Program(programName=formation.name) + ) -> PatientProgram: + program = patient.PatientProgram(programName=formation.name) with fixture_cassette(): try: @@ -54,32 +60,38 @@ def program( "programName", ], ) - def test_read(self, patient: Patient, program: Program, identifier: str): - prog = patient.Program(**{identifier: getattr(program, identifier)}).get() - - assert isinstance(prog, Program) + def test_read( + self, patient: Patient, patient_program: PatientProgram, identifier: str + ): + prog = patient.PatientProgram( + **{identifier: getattr(patient_program, identifier)} + ).get() + + assert isinstance(prog, PatientProgram) assert isinstance(prog.currentPhase, ProgramPhase) assert isinstance(prog.pathHistory, ProgramPhases) - assert prog.id == program.id + assert prog.id == patient_program.id def test_read_no_id(self, client): with pytest.raises(ValueError): - client.Patient(id="notarealid").Program().get() + client.Patient(id="notarealid").PatientProgram().get() - def test_update(self, patient: Patient, program: Program, second_phase: str): - assert program.currentPhase.name != second_phase - assert len(program.pathHistory) == 1 + def test_update( + self, patient: Patient, patient_program: PatientProgram, second_phase: str + ): + assert patient_program.currentPhase.name != second_phase + assert len(patient_program.pathHistory) == 1 - prog = patient.Program(programName=program.programName).update( + prog = patient.PatientProgram(programName=patient_program.programName).update( phaseName=second_phase ) assert prog.currentPhase.name == second_phase - assert prog.currentPhase.name != program.currentPhase.name + assert prog.currentPhase.name != patient_program.currentPhase.name assert len(prog.pathHistory) == 2 - def test_delete(self, patient: Patient, program: Program): - prog = patient.Program(id=program.id) + def test_delete(self, patient: Patient, patient_program: PatientProgram): + prog = patient.PatientProgram(id=patient_program.id) prog.delete() with pytest.raises(WelkinHTTPError) as excinfo: @@ -91,7 +103,7 @@ def test_delete(self, patient: Patient, program: Program): @pytest.mark.vcr class TestPrograms: def test_read(self, patient): - programs = patient.Programs().get() + programs = patient.PatientPrograms().get() - assert isinstance(programs, Programs) - assert isinstance(programs[0], Program) + assert isinstance(programs, PatientPrograms) + assert isinstance(programs[0], PatientProgram) diff --git a/welkin/client.py b/welkin/client.py index e95e1ed..79b56ef 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -94,10 +94,10 @@ class Client(Session): Formation = models.Formation Patient = models.Patient Patients = models.Patients - Program = models.Program + PatientProgram = models.PatientProgram ProgramPhase = models.ProgramPhase ProgramPhases = models.ProgramPhases - Programs = models.Programs + PatientPrograms = models.PatientPrograms Schedules = models.Schedules SearchChats = models.SearchChats SMS = models.SMS diff --git a/welkin/models/__init__.py b/welkin/models/__init__.py index 52e97ed..aec8dc3 100644 --- a/welkin/models/__init__.py +++ b/welkin/models/__init__.py @@ -19,7 +19,12 @@ from welkin.models.encounter import Encounter, EncounterDisposition, Encounters from welkin.models.formation import Formation from welkin.models.patient import Patient, Patients -from welkin.models.program import Program, ProgramPhase, ProgramPhases, Programs +from welkin.models.program import ( + PatientProgram, + PatientPrograms, + ProgramPhase, + ProgramPhases, +) from welkin.models.sms import SMS, SMSes from welkin.models.user import User, Users @@ -49,10 +54,10 @@ "Formation", "Patient", "Patients", - "Program", + "PatientProgram", "ProgramPhase", "ProgramPhases", - "Programs", + "PatientPrograms", "Schedules", "SearchChats", "SMS", diff --git a/welkin/models/patient.py b/welkin/models/patient.py index 1a1b79c..a565e91 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -10,7 +10,7 @@ ) from welkin.models.email import Email, Emails from welkin.models.encounter import Encounter, Encounters -from welkin.models.program import Program, Programs +from welkin.models.program import PatientProgram, PatientPrograms from welkin.models.sms import SMS, SMSes from welkin.pagination import PageableIterator @@ -31,8 +31,8 @@ class Patient(Resource): Emails, Encounter, Encounters, - Program, - Programs, + PatientProgram, + PatientPrograms, SearchChats, SMS, SMSes, diff --git a/welkin/models/program.py b/welkin/models/program.py index 36f7f09..6e23a95 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -11,7 +11,7 @@ class ProgramPhases(Collection): resource = ProgramPhase -class Program(Resource): +class PatientProgram(Resource): subresources = [ProgramPhase] nested_objects = { "phases": "ProgramPhase", @@ -64,8 +64,8 @@ def delete(self, patient_id: str = None): ) -class Programs(Collection): - resource = Program +class PatientPrograms(Collection): + resource = PatientProgram iterator = MetaInfoIterator def get( From f15eef71bfe91407c16697b0d883a3e043833fcb Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 3 Nov 2023 11:47:07 -0700 Subject: [PATCH 34/48] Revert "Use lesser permissions" This reverts commit b0ac9596f75194873f4eed77984046f32108fe85. --- .github/workflows/test.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 84dd492..0115449 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,8 +18,7 @@ jobs: min-version: 3.8 test: - permissions: - pull-requests: write + permissions: write-all needs: [get-python-versions] runs-on: ubuntu-latest strategy: From d764dd0bb8ed9284727b738da9a340fc2ccfa87a Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 08:49:19 -0800 Subject: [PATCH 35/48] Fix `PatientProgram` parent accessors --- welkin/models/program.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/welkin/models/program.py b/welkin/models/program.py index 6e23a95..d451d56 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -1,6 +1,6 @@ from welkin.models.base import Collection, Resource -from welkin.models.util import find_patient_id_in_parents from welkin.pagination import MetaInfoIterator +from welkin.util import model_id class ProgramPhase(Resource): @@ -19,16 +19,15 @@ class PatientProgram(Resource): "pathHistory": "ProgramPhases", } + @model_id("Patient") def get( self, - patient_id: str = None, + patient_id: str, assigned_programs: bool = None, sort: str = None, *args, **kwargs, ): - patient_id = patient_id or find_patient_id_in_parents(self) - path = f"{self._client.instance}/patients/{patient_id}/programs" if hasattr(self, "id"): path += f"/history/{self.id}" @@ -47,18 +46,16 @@ def get( **kwargs, ) - def update(self, patient_id: str = None, **kwargs): - patient_id = patient_id or find_patient_id_in_parents(self) - + @model_id("Patient") + def update(self, patient_id: str, **kwargs): return super().patch( f"{self._client.instance}/patients/{patient_id}/programs/" f"{self.programName}", kwargs, ) - def delete(self, patient_id: str = None): - patient_id = patient_id or find_patient_id_in_parents(self) - + @model_id("Patient") + def delete(self, patient_id: str): return super().delete( f"{self._client.instance}/patients/{patient_id}/programs/{self.id}" ) @@ -68,16 +65,15 @@ class PatientPrograms(Collection): resource = PatientProgram iterator = MetaInfoIterator + @model_id("Patient") def get( self, - patient_id: str = None, + patient_id: str, assigned_programs: bool = None, sort: str = None, *args, **kwargs, ): - patient_id = patient_id or find_patient_id_in_parents(self) - return super().get( f"{self._client.instance}/patients/{patient_id}/programs", params={ From ebfee7b648d9b4ab5afb2a61f85fb2b4cbfdb8be Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 09:39:48 -0800 Subject: [PATCH 36/48] Run all matrix jobs even if one fails --- .github/workflows/test.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 0115449..76a22be 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,6 +22,7 @@ jobs: needs: [get-python-versions] runs-on: ubuntu-latest strategy: + fail-fast: false matrix: python-version: ${{ fromJson(needs.get-python-versions.outputs.python-matrix) }} @@ -59,6 +60,7 @@ jobs: - name: Pytest coverage comment uses: MishaKav/pytest-coverage-comment@main + continue-on-error: true with: pytest-coverage-path: ./pytest-coverage.txt junitxml-path: ./pytest.xml From 8d2eb93d439a72b75d4c022e8c177af5e42b4095 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 10:07:43 -0800 Subject: [PATCH 37/48] Add concurrency limiter --- .github/workflows/test.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 76a22be..e87cb82 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -6,6 +6,10 @@ on: - main - develop +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: get-python-versions: runs-on: ubuntu-latest From c062822746eb92030f5e6f298e07910a786dbe7a Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 11:11:47 -0800 Subject: [PATCH 38/48] Revamp test/publish actions --- .github/workflows/cd.yaml | 78 ++++++++++++++++++++++++++++++++++ .github/workflows/ci.yaml | 78 ++++++++++++++++++++++++++++++++++ .github/workflows/publish.yaml | 18 -------- .github/workflows/test.yaml | 71 ------------------------------- 4 files changed, 156 insertions(+), 89 deletions(-) create mode 100644 .github/workflows/cd.yaml create mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/publish.yaml delete mode 100644 .github/workflows/test.yaml diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml new file mode 100644 index 0000000..5b2cbf4 --- /dev/null +++ b/.github/workflows/cd.yaml @@ -0,0 +1,78 @@ +name: Publish Python 🐍 package 📦 to PyPI + +on: + push: + branches: + - master + workflow_dispatch: + +jobs: + get-package-version: + name: Get ${{ github.ref_name }} package version + runs-on: ubuntu-latest + outputs: + package-version: ${{ steps.package-version.outputs.package-version }} + version-compairson: ${{ steps.semver.outputs.comparison-result}} + steps: + - name: Checkout ${{ github.repository }} + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + + - name: Install Poetry + uses: snok/install-poetry@v1 + with: + virtualenvs-create: true + virtualenvs-in-project: true + installer-parallel: true + + - name: Get package version + id: package-version + run: echo "package-version=v$(poetry version --short)" >> $GITHUB_OUTPUT + + - name: Get release version + id: release-version + uses: pozetroninc/github-action-get-latest-release@master + with: + repository: ${{ github.repository }} + + - name: Analyze semver + id: semver + uses: madhead/semver-utils@latest + with: + lenient: false + version: ${{ steps.package-version.outputs.package-version }} + compare-to: ${{ steps.release-version.outputs.release }} + + - name: Check pre-release + if: ${{ steps.semver.outputs.prerelease != '' }} + run: | + echo "Checking if version is a pre-release" + echo "::error::Skipping pre-release version: ${{ steps.package-version.outputs.package-version}}" + exit 1 + + deploy: + name: Deploy Python 🐍 distributions 📦 to PyPI + needs: [get-package-version] + runs-on: ubuntu-latest + if: ${{ needs.get-package-version.outputs.version-compairson != '=' }} + + steps: + - name: Checkout ${{ github.repository }} + uses: actions/checkout@v3 + + - name: Build and publish to PyPI + uses: JRubics/poetry-publish@v1.13 + with: + pypi_token: ${{ secrets.PYPI_API_TOKEN }} + + - name: Create release ${{ needs.get-package-version.outputs.package-version }} + uses: ncipollo/release-action@v1 + with: + commit: ${{ github.ref_name }} + tag: ${{ needs.get-package-version.outputs.package-version }} + generateReleaseNotes: true + artifacts: | + dist/*.whl + dist/*.tar.gz diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..b355873 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,78 @@ +name: CI + +on: [pull_request, workflow_dispatch] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + get-python-versions: + name: Get Python versions + runs-on: ubuntu-latest + outputs: + python-matrix: ${{ steps.get-python-versions-action.outputs.latest-python-versions }} + steps: + - name: Get Python version matrix + uses: snok/latest-python-versions@v1 + id: get-python-versions-action + with: + min-version: 3.8 + + ci: + name: CI + needs: [get-python-versions] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ${{ fromJson(needs.get-python-versions.outputs.python-matrix) }} + + steps: + - name: Checkout ${{ github.repository }} + uses: actions/checkout@v4 + + - name: Setup Python ${{ matrix.python-version }} + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + uses: snok/install-poetry@v1 + with: + virtualenvs-create: true + virtualenvs-in-project: true + installer-parallel: true + + - name: Load cached environment + uses: actions/cache@v3 + with: + path: .venv + key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }} + + - name: Install dependencies + id: poetry-install + run: | + poetry install --with test --no-interaction --no-root + + - name: Run pre-commit + run: poetry run pre-commit run --all-files + + - name: Run Tests + run: | + poetry run pytest \ + --junitxml=pytest.xml \ + --cov-report=term-missing:skip-covered \ + --cov=welkin | tee pytest-coverage.txt + + - name: Add coverage comment + uses: MishaKav/pytest-coverage-comment@main + continue-on-error: true + with: + pytest-coverage-path: ./pytest-coverage.txt + junitxml-path: ./pytest.xml + report-only-changed-files: true + title: Coverage Report + unique-id-for-comment: ${{ matrix.python-version }} + remove-link-from-badge: true diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml deleted file mode 100644 index 5dc7655..0000000 --- a/.github/workflows/publish.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Publish Python 🐍 distributions 📦 to PyPI - -on: - release: - types: [created] - -jobs: - deploy: - name: Deploy Python 🐍 distributions 📦 to PyPI - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Build and publish to pypi - uses: JRubics/poetry-publish@v1.13 - with: - pypi_token: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index e87cb82..0000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,71 +0,0 @@ -name: Python 🐍 package 📦 test - -on: - pull_request: - branches: - - main - - develop - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - get-python-versions: - runs-on: ubuntu-latest - outputs: - python-matrix: ${{ steps.get-python-versions-action.outputs.latest-python-versions }} - steps: - - uses: snok/latest-python-versions@v1 - id: get-python-versions-action - with: - min-version: 3.8 - - test: - permissions: write-all - needs: [get-python-versions] - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ${{ fromJson(needs.get-python-versions.outputs.python-matrix) }} - - steps: - - name: Check out repository - uses: actions/checkout@v3 - - - name: Load cached Poetry installation - uses: actions/cache@v3 - with: - path: ~/.local # the path depends on the OS - key: poetry-0 # increment to reset cache - - - name: Install Poetry - uses: snok/install-poetry@v1 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: poetry - - - name: Specify Poetry Python version - run: poetry env use ${{ matrix.python-version }} - - - name: Install dependencies - run: poetry install --with test --no-interaction - - - name: Run tests - run: | - poetry run pytest \ - --junitxml=pytest.xml \ - --cov-report=term-missing:skip-covered \ - --cov=welkin test/ | tee pytest-coverage.txt - - - name: Pytest coverage comment - uses: MishaKav/pytest-coverage-comment@main - continue-on-error: true - with: - pytest-coverage-path: ./pytest-coverage.txt - junitxml-path: ./pytest.xml - unique-id-for-comment: ${{ matrix.python-version }} From ff714c912eaf8d6c1878cd7c41dca2d598a7ac5a Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 11:21:44 -0800 Subject: [PATCH 39/48] Bump semver --- .github/workflows/ci.yaml | 3 +-- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b355873..9925242 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -53,8 +53,7 @@ jobs: - name: Install dependencies id: poetry-install - run: | - poetry install --with test --no-interaction --no-root + run: poetry install --with test --no-interaction --no-root - name: Run pre-commit run: poetry run pre-commit run --all-files diff --git a/pyproject.toml b/pyproject.toml index 40f173b..1054069 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "welkin" -version = "0.1.1" +version = "0.1.2" description = "Python Welkin Health API Wrapper." authors = ["Sam Morgan "] license = "GPL-3.0-or-later" From ce802ecc60b55940650f8b60392d5aeae97f230e Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 11:25:53 -0800 Subject: [PATCH 40/48] Fix package groups --- .github/workflows/ci.yaml | 2 +- .github/workflows/pre-commit.yaml | 14 -------------- poetry.lock | 2 +- pyproject.toml | 9 --------- 4 files changed, 2 insertions(+), 25 deletions(-) delete mode 100644 .github/workflows/pre-commit.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9925242..da40b10 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -53,7 +53,7 @@ jobs: - name: Install dependencies id: poetry-install - run: poetry install --with test --no-interaction --no-root + run: poetry install --no-interaction --no-root - name: Run pre-commit run: poetry run pre-commit run --all-files diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml deleted file mode 100644 index ec4d9b3..0000000 --- a/.github/workflows/pre-commit.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: pre-commit - -on: - pull_request: - push: - branches: [main] - -jobs: - pre-commit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - uses: pre-commit/action@v3.0.0 diff --git a/poetry.lock b/poetry.lock index e96793c..9079475 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1557,4 +1557,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "c28aa3ec9916edecdc6d57e58cd1b6e3539d952a9c2f038cefa264bf1b6139b9" +content-hash = "415816e09ebda751949d0e1e14906f58c650e3e59b1b9146efaf1f4b8ebe5342" diff --git a/pyproject.toml b/pyproject.toml index 1054069..bba2efb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,17 +22,11 @@ requests = "^2.28.1" portalocker = "^2.7.0" inflection = "^0.5.1" -[tool.poetry.group.dev] -optional = true - [tool.poetry.group.dev.dependencies] black = "^22.10.0" isort = "^5.10.1" pre-commit = "^3.5.0" -[tool.poetry.group.test] -optional = true - [tool.poetry.group.test.dependencies] pytest = "^7.1.3" pytest-cov = "^4.0.0" @@ -41,9 +35,6 @@ pytest-vcr = "^1.0.2" pytest-xdist = "^3.2.1" tomli = "^2.0.1" -[tool.poetry.group.docs] -optional = true - [tool.poetry.group.docs.dependencies] Sphinx = "^5.2.3" sphinx-autoapi = "^2.0.0" From 65c25b5e9080958268badcda37c15a99d41b5156 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 11:29:26 -0800 Subject: [PATCH 41/48] Update RTD command --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index cdef690..7464f83 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,7 +11,7 @@ build: post_install: - pip install poetry - poetry config virtualenvs.create false - - poetry install --with docs + - poetry install sphinx: configuration: docs/conf.py From f7315dbdcc18bb5069f4df09ca694e24d557a744 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 11:32:44 -0800 Subject: [PATCH 42/48] Add Python version to coverage comment --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index da40b10..656887a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -72,6 +72,6 @@ jobs: pytest-coverage-path: ./pytest-coverage.txt junitxml-path: ./pytest.xml report-only-changed-files: true - title: Coverage Report + title: Coverage Report (Python ${{ matrix.python-version }}) unique-id-for-comment: ${{ matrix.python-version }} remove-link-from-badge: true From 368671e7d31255ac2b003af52807988a32ce1aff Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 12:00:28 -0800 Subject: [PATCH 43/48] Add dynamic package metadata --- poetry.lock | 1194 +++++++++++++++++++++-------------------- welkin/__version__.py | 23 +- 2 files changed, 612 insertions(+), 605 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9079475..15ed92c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -24,35 +24,35 @@ files = [ [[package]] name = "astroid" -version = "2.11.7" +version = "3.1.0" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.8.0" files = [ - {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, - {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, + {file = "astroid-3.1.0-py3-none-any.whl", hash = "sha256:951798f922990137ac090c53af473db7ab4e70c770e6d7fae0cec59f74411819"}, + {file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"}, ] [package.dependencies] -lazy-object-proxy = ">=1.4.0" -setuptools = ">=20.0" -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} -wrapt = ">=1.11,<2" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "babel" -version = "2.12.1" +version = "2.14.0" description = "Internationalization utilities" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, - {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, ] [package.dependencies] pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + [[package]] name = "black" version = "22.12.0" @@ -90,13 +90,13 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -112,86 +112,101 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.2.0" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, - {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] @@ -221,71 +236,63 @@ files = [ [[package]] name = "coverage" -version = "7.2.7" +version = "7.4.3" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, - {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, - {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, - {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, - {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, - {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, - {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, - {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, - {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, - {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, - {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, - {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, - {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, - {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, - {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, - {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, - {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, - {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"}, + {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"}, + {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"}, + {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"}, + {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"}, + {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"}, + {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"}, + {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"}, + {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"}, + {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"}, + {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"}, + {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"}, + {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"}, ] [package.dependencies] @@ -296,13 +303,13 @@ toml = ["tomli"] [[package]] name = "distlib" -version = "0.3.7" +version = "0.3.8" description = "Distribution utilities" optional = false python-versions = "*" files = [ - {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, - {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] [[package]] @@ -318,13 +325,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] @@ -362,13 +369,13 @@ typing = ["typing-extensions (>=4.8)"] [[package]] name = "identify" -version = "2.5.31" +version = "2.5.35" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.31-py2.py3-none-any.whl", hash = "sha256:90199cb9e7bd3c5407a9b7e81b4abec4bb9d249991c79439ec8af740afc6293d"}, - {file = "identify-2.5.31.tar.gz", hash = "sha256:7736b3c7a28233637e3c36550646fc6389bedd74ae84cb788200cc8e2dd60b75"}, + {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"}, + {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"}, ] [package.extras] @@ -376,13 +383,13 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] @@ -398,22 +405,22 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.7.0" +version = "7.0.1" description = "Read metadata from Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"}, - {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"}, + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "inflection" @@ -439,30 +446,27 @@ files = [ [[package]] name = "isort" -version = "5.11.5" +version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "isort-5.11.5-py3-none-any.whl", hash = "sha256:ba1d72fb2595a01c7895a5128f9585a5cc4b6d395f1c8d514989b9a7eb2a8746"}, - {file = "isort-5.11.5.tar.gz", hash = "sha256:6be1f76a507cb2ecf16c7cf14a37e41609ca082330be4e3436a18ef74add55db"}, + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] +colors = ["colorama (>=0.4.6)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.3" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [package.dependencies] @@ -471,51 +475,6 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "lazy-object-proxy" -version = "1.9.0" -description = "A fast and thorough lazy object proxy." -optional = false -python-versions = ">=3.7" -files = [ - {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, -] - [[package]] name = "markdown-it-py" version = "2.2.0" @@ -542,61 +501,71 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.3" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] @@ -631,85 +600,101 @@ files = [ [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] @@ -765,50 +750,50 @@ setuptools = "*" [[package]] name = "packaging" -version = "23.1" +version = "23.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] [[package]] name = "pathspec" -version = "0.11.2" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "platformdirs" -version = "3.10.0" +version = "4.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, - {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, ] [package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] [[package]] name = "pluggy" -version = "1.2.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, - {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -817,13 +802,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "portalocker" -version = "2.7.0" +version = "2.8.2" description = "Wraps the portalocker recipe for easy usage" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "portalocker-2.7.0-py2.py3-none-any.whl", hash = "sha256:a07c5b4f3985c3cf4798369631fb7011adb498e2a46d8440efc75a8f29a0f983"}, - {file = "portalocker-2.7.0.tar.gz", hash = "sha256:032e81d534a88ec1736d03f780ba073f047a06c478b06e2937486f334e955c51"}, + {file = "portalocker-2.8.2-py3-none-any.whl", hash = "sha256:cfb86acc09b9aa7c3b43594e19be1345b9d16af3feb08bf92f23d4dce513a28e"}, + {file = "portalocker-2.8.2.tar.gz", hash = "sha256:2b035aa7828e46c58e9b31390ee1f169b98e1066ab10b9a6a861fe7e25ee4f33"}, ] [package.dependencies] @@ -832,7 +817,7 @@ pywin32 = {version = ">=226", markers = "platform_system == \"Windows\""} [package.extras] docs = ["sphinx (>=1.7.1)"] redis = ["redis"] -tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)"] +tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)", "types-redis"] [[package]] name = "pre-commit" @@ -854,27 +839,28 @@ virtualenv = ">=20.10.0" [[package]] name = "pygments" -version = "2.16.1" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] [package.extras] plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "7.4.2" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, - {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -938,13 +924,13 @@ vcrpy = "*" [[package]] name = "pytest-xdist" -version = "3.3.1" +version = "3.5.0" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-xdist-3.3.1.tar.gz", hash = "sha256:d5ee0520eb1b7bcca50a60a518ab7a7707992812c578198f8b44fdfac78e8c93"}, - {file = "pytest_xdist-3.3.1-py3-none-any.whl", hash = "sha256:ff9daa7793569e6a68544850fd3927cd257cc03a7ef76c95e86915355e82b5f2"}, + {file = "pytest-xdist-3.5.0.tar.gz", hash = "sha256:cbb36f3d67e0c478baa57fa4edc8843887e0f6cfc42d677530a36d7472b32d8a"}, + {file = "pytest_xdist-3.5.0-py3-none-any.whl", hash = "sha256:d075629c7e00b611df89f490a5063944bee7a4362a5ff11c7cc7824a03dfce24"}, ] [package.dependencies] @@ -958,13 +944,13 @@ testing = ["filelock"] [[package]] name = "python-dotenv" -version = "0.21.1" +version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"}, - {file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"}, + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, ] [package.extras] @@ -972,13 +958,13 @@ cli = ["click (>=5.0)"] [[package]] name = "pytz" -version = "2023.3.post1" +version = "2024.1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] [[package]] @@ -1076,30 +1062,19 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" -version = "68.0.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"}, - {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "snowballstemmer" @@ -1191,13 +1166,13 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.2" -description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +version = "1.0.4" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, - {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, ] [package.extras] @@ -1221,13 +1196,13 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.0" +version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, - {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, ] [package.extras] @@ -1305,64 +1280,82 @@ files = [ [[package]] name = "typing-extensions" -version = "4.7.1" -description = "Backported and Experimental Type Hints for Python 3.7+" +version = "4.10.0" +description = "Backported and Experimental Type Hints for Python 3.8+" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, - {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] name = "urllib3" -version = "1.26.16" +version = "1.26.18" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, - {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, + {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, + {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "vcrpy" -version = "4.4.0" +version = "6.0.1" description = "Automatically mock your HTTP interactions to simplify and speed up testing" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "vcrpy-4.4.0-py2.py3-none-any.whl", hash = "sha256:560c9d0d8436ced29223ceefb513c3ac3f2e2a60d51a9830f236a1e63167905a"}, - {file = "vcrpy-4.4.0.tar.gz", hash = "sha256:d1109ae93dbc2e7fcbc485849a7600d5dea510d3bef070eec4419c9a72ca2639"}, + {file = "vcrpy-6.0.1.tar.gz", hash = "sha256:9e023fee7f892baa0bbda2f7da7c8ac51165c1c6e38ff8688683a12a4bde9278"}, ] [package.dependencies] PyYAML = "*" -six = ">=1.5" -urllib3 = {version = "<2", markers = "python_version < \"3.10\""} +urllib3 = {version = "<2", markers = "platform_python_implementation == \"PyPy\" or python_version < \"3.10\""} wrapt = "*" yarl = "*" +[package.extras] +tests = ["Werkzeug (==2.0.3)", "aiohttp", "boto3", "httplib2", "httpx", "pytest", "pytest-aiohttp", "pytest-asyncio", "pytest-cov", "pytest-httpbin", "requests (>=2.22.0)", "tornado", "urllib3"] + [[package]] name = "virtualenv" -version = "20.24.6" +version = "20.25.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"}, - {file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"}, + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<4" +platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] @@ -1370,169 +1363,180 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "wrapt" -version = "1.15.0" +version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] [[package]] name = "yarl" -version = "1.9.2" +version = "1.9.4" description = "Yet another URL library" optional = false python-versions = ">=3.7" files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, ] [package.dependencies] @@ -1541,18 +1545,18 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.15.0" +version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [metadata] lock-version = "2.0" diff --git a/welkin/__version__.py b/welkin/__version__.py index a4c7b32..48905ff 100644 --- a/welkin/__version__.py +++ b/welkin/__version__.py @@ -1,11 +1,14 @@ -"""Package version information. -""" +"""Package version information.""" +from datetime import date +from importlib.metadata import distribution -__title__ = "welkin" -__description__ = "Python Welkin Health API Wrapper." -__url__ = "https://github.com/Lightmatter/welkin-health" -__version__ = "0.1.1" -__author__ = "Sam Morgan" -__author_email__ = "sama4mail@gmail.com" -__license__ = "GNU GPL 3.0" -__copyright__ = "2022 Lightmatter" +_dist_metadata: dict = distribution("welkin").metadata.json + +__title__ = _dist_metadata["name"] +__description__ = _dist_metadata["summary"] +__url__ = _dist_metadata["home_page"] +__version__ = _dist_metadata["version"] +__author__ = _dist_metadata["author"] +__author_email__ = _dist_metadata["author_email"] +__license__ = _dist_metadata["license"] +__copyright__ = f"{date.today().year} Lightmatter" From 06ec9590ba328495dee3a3873e3b6a2a5464d1bf Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 12:17:29 -0800 Subject: [PATCH 44/48] Get rid of Tomli --- docs/conf.py | 34 ++++++++++------------------------ poetry.lock | 2 +- pyproject.toml | 2 -- test/test_version.py | 13 ------------- 4 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 test/test_version.py diff --git a/docs/conf.py b/docs/conf.py index d53e8b8..ce8ad3d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,39 +1,25 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# 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. +"""Configuration file for the Sphinx documentation builder. +This file only contains a selection of the most common options. For a full +list see the documentation: +https://www.sphinx-doc.org/en/master/usage/configuration.html +""" import sys -from datetime import date from pathlib import Path -import tomli +import welkin root = Path(__file__).parent.parent sys.path.insert(0, str(root)) # -- Project information ----------------------------------------------------- -def _get_project_meta(): - with (root / "pyproject.toml").open(mode="rb") as f: - return tomli.load(f)["tool"]["poetry"] - - -project_meta = _get_project_meta() - -project = project_meta["name"] -author = project_meta["authors"][0].rsplit(maxsplit=1)[0] -copyright = f"{date.today().year} Lightmatter Team" +project = welkin.__title__ +author = welkin.__author__ +copyright = welkin.__copyright__ # The full version, including alpha/beta/rc tags -release = project_meta["version"] +release = welkin.__version__ # -- General configuration --------------------------------------------------- diff --git a/poetry.lock b/poetry.lock index 15ed92c..9361415 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1561,4 +1561,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "415816e09ebda751949d0e1e14906f58c650e3e59b1b9146efaf1f4b8ebe5342" +content-hash = "53ce3c553714535ed0855e4219d83940f1059ef8c02b77f5c8aa5c978cf807a9" diff --git a/pyproject.toml b/pyproject.toml index bba2efb..33b1ead 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,14 +33,12 @@ pytest-cov = "^4.0.0" pytest-dotenv = "^0.5.2" pytest-vcr = "^1.0.2" pytest-xdist = "^3.2.1" -tomli = "^2.0.1" [tool.poetry.group.docs.dependencies] Sphinx = "^5.2.3" sphinx-autoapi = "^2.0.0" sphinx-rtd-theme = "^1.0.0" myst-parser = "^0.18.1" -tomli = "^2.0.1" [build-system] requires = ["poetry-core"] diff --git a/test/test_version.py b/test/test_version.py deleted file mode 100644 index 4e40620..0000000 --- a/test/test_version.py +++ /dev/null @@ -1,13 +0,0 @@ -from pathlib import Path - -import tomli - -from welkin.__version__ import __version__ - -pyproject_path = Path(__file__).parent.parent / "pyproject.toml" - - -def test_version_match(): - with open(pyproject_path, "rb") as f: - pyproject_toml = tomli.load(f) - assert pyproject_toml["tool"]["poetry"]["version"] == __version__ From 668688292333a14637b5e5688baf62d9f60dc587 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 12:20:18 -0800 Subject: [PATCH 45/48] Move welkin import --- docs/conf.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ce8ad3d..ec34c93 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,11 +7,10 @@ import sys from pathlib import Path -import welkin - root = Path(__file__).parent.parent sys.path.insert(0, str(root)) +import welkin # -- Project information ----------------------------------------------------- project = welkin.__title__ From 916aa9c639bf594241b0e2277b6de8444d69c9d0 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 14:01:17 -0800 Subject: [PATCH 46/48] Update sphinx deps --- docs/conf.py | 56 +++++------------------ poetry.lock | 117 +++++++++++++++++++++++++------------------------ pyproject.toml | 18 ++++---- 3 files changed, 80 insertions(+), 111 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ec34c93..bad8568 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,31 +1,19 @@ -"""Configuration file for the Sphinx documentation builder. - -This file only contains a selection of the most common options. For a full -list see the documentation: -https://www.sphinx-doc.org/en/master/usage/configuration.html -""" -import sys -from pathlib import Path - -root = Path(__file__).parent.parent -sys.path.insert(0, str(root)) - -import welkin +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Project information ----------------------------------------------------- -project = welkin.__title__ -author = welkin.__author__ -copyright = welkin.__copyright__ - -# The full version, including alpha/beta/rc tags -release = welkin.__version__ +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +project = "foobar" +copyright = "2024, Sam Morgan" +author = "Sam Morgan" +release = "1" # -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = [ "autoapi.extension", "sphinx.ext.autodoc", @@ -45,32 +33,12 @@ ] autoapi_type = "python" -# Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [ - "_build", - "Thumbs.db", - ".DS_Store", -] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# html_theme = "sphinx_rtd_theme" - -# 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"] - -source_suffix = { - ".rst": "restructuredtext", - ".md": "markdown", -} diff --git a/poetry.lock b/poetry.lock index 9361415..1af56b1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -314,13 +314,13 @@ files = [ [[package]] name = "docutils" -version = "0.18.1" +version = "0.20.1" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, - {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, ] [[package]] @@ -477,13 +477,13 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "markdown-it-py" -version = "2.2.0" +version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, - {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, ] [package.dependencies] @@ -496,7 +496,7 @@ compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0 linkify = ["linkify-it-py (>=1,<3)"] plugins = ["mdit-py-plugins"] profiling = ["gprof2dot"] -rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] @@ -570,21 +570,21 @@ files = [ [[package]] name = "mdit-py-plugins" -version = "0.3.5" +version = "0.4.0" description = "Collection of plugins for markdown-it-py" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mdit-py-plugins-0.3.5.tar.gz", hash = "sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a"}, - {file = "mdit_py_plugins-0.3.5-py3-none-any.whl", hash = "sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e"}, + {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, + {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, ] [package.dependencies] -markdown-it-py = ">=1.0.0,<3.0.0" +markdown-it-py = ">=1.0.0,<4.0.0" [package.extras] code-style = ["pre-commit"] -rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] +rtd = ["myst-parser", "sphinx-book-theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] @@ -710,29 +710,29 @@ files = [ [[package]] name = "myst-parser" -version = "0.18.1" -description = "An extended commonmark compliant parser, with bridges to docutils & sphinx." +version = "2.0.0" +description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "myst-parser-0.18.1.tar.gz", hash = "sha256:79317f4bb2c13053dd6e64f9da1ba1da6cd9c40c8a430c447a7b146a594c246d"}, - {file = "myst_parser-0.18.1-py3-none-any.whl", hash = "sha256:61b275b85d9f58aa327f370913ae1bec26ebad372cc99f3ab85c8ec3ee8d9fb8"}, + {file = "myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14"}, + {file = "myst_parser-2.0.0.tar.gz", hash = "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"}, ] [package.dependencies] -docutils = ">=0.15,<0.20" +docutils = ">=0.16,<0.21" jinja2 = "*" -markdown-it-py = ">=1.0.0,<3.0.0" -mdit-py-plugins = ">=0.3.1,<0.4.0" +markdown-it-py = ">=3.0,<4.0" +mdit-py-plugins = ">=0.4,<1.0" pyyaml = "*" -sphinx = ">=4,<6" -typing-extensions = "*" +sphinx = ">=6,<8" [package.extras] -code-style = ["pre-commit (>=2.12,<3.0)"] -linkify = ["linkify-it-py (>=1.0,<2.0)"] -rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] -testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"] +code-style = ["pre-commit (>=3.0,<4.0)"] +linkify = ["linkify-it-py (>=2.0,<3.0)"] +rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.8.2,<0.9.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] +testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] [[package]] name = "nodeenv" @@ -854,13 +854,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "7.4.4" +version = "8.0.2" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.0.2-py3-none-any.whl", hash = "sha256:edfaaef32ce5172d5466b5127b42e0d6d35ebbe4453f0e3505d96afd93f6b096"}, + {file = "pytest-8.0.2.tar.gz", hash = "sha256:d4051d623a2e0b7e51960ba963193b09ce6daeb9759a451844a21e4ddedfc1bd"}, ] [package.dependencies] @@ -868,7 +868,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" +pluggy = ">=1.3.0,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] @@ -1089,26 +1089,26 @@ files = [ [[package]] name = "sphinx" -version = "5.3.0" +version = "7.1.2" description = "Python documentation generator" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"}, - {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"}, + {file = "sphinx-7.1.2-py3-none-any.whl", hash = "sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe"}, + {file = "sphinx-7.1.2.tar.gz", hash = "sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f"}, ] [package.dependencies] alabaster = ">=0.7,<0.8" babel = ">=2.9" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.14,<0.20" +docutils = ">=0.18.1,<0.21" imagesize = ">=1.3" importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} Jinja2 = ">=3.0" packaging = ">=21.0" -Pygments = ">=2.12" -requests = ">=2.5.0" +Pygments = ">=2.13" +requests = ">=2.25.0" snowballstemmer = ">=2.0" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" @@ -1119,46 +1119,47 @@ sphinxcontrib-serializinghtml = ">=1.1.5" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"] -test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] [[package]] name = "sphinx-autoapi" -version = "2.1.1" +version = "3.0.0" description = "Sphinx API documentation generator" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "sphinx-autoapi-2.1.1.tar.gz", hash = "sha256:fbadb96e79020d6b0ec45d888517bf816d6b587a2d340fbe1ec31135e300a6c8"}, - {file = "sphinx_autoapi-2.1.1-py2.py3-none-any.whl", hash = "sha256:d8da890477bd18e3327cafdead9d5a44a7d798476c6fa32492100e288250a5a3"}, + {file = "sphinx-autoapi-3.0.0.tar.gz", hash = "sha256:09ebd674a32b44467222b0fb8a917b97c89523f20dbf05b52cb8a3f0e15714de"}, + {file = "sphinx_autoapi-3.0.0-py2.py3-none-any.whl", hash = "sha256:ea207793cba1feff7b2ded0e29364f2995a4d157303a98603cee0ce94cea2688"}, ] [package.dependencies] anyascii = "*" -astroid = ">=2.7" +astroid = [ + {version = ">=2.7", markers = "python_version < \"3.12\""}, + {version = ">=3.0.0a1", markers = "python_version >= \"3.12\""}, +] Jinja2 = "*" PyYAML = "*" -sphinx = ">=5.2.0" +sphinx = ">=6.1.0" [package.extras] docs = ["furo", "sphinx", "sphinx-design"] -dotnet = ["sphinxcontrib-dotnetdomain"] -go = ["sphinxcontrib-golangdomain"] [[package]] name = "sphinx-rtd-theme" -version = "1.3.0" +version = "2.0.0" description = "Read the Docs theme for Sphinx" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.6" files = [ - {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"}, - {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"}, + {file = "sphinx_rtd_theme-2.0.0-py2.py3-none-any.whl", hash = "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586"}, + {file = "sphinx_rtd_theme-2.0.0.tar.gz", hash = "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b"}, ] [package.dependencies] -docutils = "<0.19" -sphinx = ">=1.6,<8" +docutils = "<0.21" +sphinx = ">=5,<8" sphinxcontrib-jquery = ">=4,<5" [package.extras] @@ -1561,4 +1562,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "53ce3c553714535ed0855e4219d83940f1059ef8c02b77f5c8aa5c978cf807a9" +content-hash = "59d873929c1d5c720280d77471b88aedf160fe781363769ded86bb86783f08a7" diff --git a/pyproject.toml b/pyproject.toml index 33b1ead..ada4ed8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,8 +18,8 @@ classifiers = [ [tool.poetry.dependencies] python = "^3.8" -requests = "^2.28.1" -portalocker = "^2.7.0" +requests = "^2.31.0" +portalocker = "^2.8.2" inflection = "^0.5.1" [tool.poetry.group.dev.dependencies] @@ -28,17 +28,17 @@ isort = "^5.10.1" pre-commit = "^3.5.0" [tool.poetry.group.test.dependencies] -pytest = "^7.1.3" -pytest-cov = "^4.0.0" +pytest = "^8.0.2" +pytest-cov = "^4.1.0" pytest-dotenv = "^0.5.2" pytest-vcr = "^1.0.2" -pytest-xdist = "^3.2.1" +pytest-xdist = "^3.5.0" [tool.poetry.group.docs.dependencies] -Sphinx = "^5.2.3" -sphinx-autoapi = "^2.0.0" -sphinx-rtd-theme = "^1.0.0" -myst-parser = "^0.18.1" +Sphinx = "7.1.2" +sphinx-autoapi = "^3.0.0" +sphinx-rtd-theme = "^2.0.0" +myst-parser = "^2.0.0" [build-system] requires = ["poetry-core"] From 0e249eae11ca28ea941c7c21439d9ddff429a517 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 14:08:54 -0800 Subject: [PATCH 47/48] Update RTD config --- .readthedocs.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 7464f83..42a57c6 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,14 +4,14 @@ version: 2 build: - os: ubuntu-20.04 + os: ubuntu-22.04 tools: - python: "3" + python: "3.8" jobs: - post_install: + post_create_environment: - pip install poetry - - poetry config virtualenvs.create false - - poetry install + post_install: + - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install sphinx: configuration: docs/conf.py From 0c0eb5b4679b30755a662a2df8cb7e54d86265d4 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Wed, 28 Feb 2024 14:17:43 -0800 Subject: [PATCH 48/48] Suggested fixes --- test/test_base.py | 2 +- welkin/models/assessment.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_base.py b/test/test_base.py index d62b1b6..9531f54 100644 --- a/test/test_base.py +++ b/test/test_base.py @@ -40,6 +40,6 @@ def test_method_args(client, class_name: str): if cls in Patient.subresources: try: - assert args.args.index("patient_id") == 1, f"patient_id must be first" + assert args.args.index("patient_id") == 1, "patient_id must be first" except ValueError: pytest.fail(f"{method} must accept patient_id") diff --git a/welkin/models/assessment.py b/welkin/models/assessment.py index 9f58276..457c490 100644 --- a/welkin/models/assessment.py +++ b/welkin/models/assessment.py @@ -42,7 +42,7 @@ class Assessments(Collection): def get(self, patient_id: str, encounter_id: str, *args, **kwargs): return super().get( f"{self._client.instance}/patients/{patient_id}/encounters/{encounter_id}/" - f"assessments", + "assessments", *args, **kwargs, )