From 1ab09cd23af06d7ab6bea4043d5f25a8a767f1d3 Mon Sep 17 00:00:00 2001 From: samamorgan <356814+samamorgan@users.noreply.github.com> Date: Thu, 29 Feb 2024 01:19:02 +0000 Subject: [PATCH 01/18] update pre-commit hooks --- .pre-commit-config.yaml | 6 +++--- welkin/__init__.py | 1 + welkin/__version__.py | 1 + welkin/client.py | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index db8f572..b8a64fe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-yaml args: [--unsafe] @@ -9,13 +9,13 @@ repos: ## Python - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort types: [python] - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 24.2.0 hooks: - id: black types: [python] diff --git a/welkin/__init__.py b/welkin/__init__.py index 976679b..1f9ce36 100644 --- a/welkin/__init__.py +++ b/welkin/__init__.py @@ -45,6 +45,7 @@ For this example we will assume Client Name is VBOPNRYRWJIP and Secret Key is +}B{KGTG6#zG%P;tQm0C """ + from welkin.__version__ import ( __author__, __author_email__, diff --git a/welkin/__version__.py b/welkin/__version__.py index 48905ff..94828b8 100644 --- a/welkin/__version__.py +++ b/welkin/__version__.py @@ -1,4 +1,5 @@ """Package version information.""" + from datetime import date from importlib.metadata import distribution diff --git a/welkin/client.py b/welkin/client.py index 79b56ef..94751c0 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -2,6 +2,7 @@ This module provides a Client object to interface with the Welkin Health API. """ + import logging from http import HTTPStatus from json import JSONDecodeError From aa24f53a67a4947987092040d0f41e46c356c344 Mon Sep 17 00:00:00 2001 From: samamorgan <356814+samamorgan@users.noreply.github.com> Date: Sat, 16 Mar 2024 00:10:27 +0000 Subject: [PATCH 02/18] update pre-commit hooks --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b8a64fe..e82779e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: types: [python] - repo: https://github.com/psf/black - rev: 24.2.0 + rev: 24.3.0 hooks: - id: black types: [python] From 66d3a8f9527612cbf9bb1346dcc92ed3eda72daa Mon Sep 17 00:00:00 2001 From: samamorgan <356814+samamorgan@users.noreply.github.com> Date: Sun, 7 Apr 2024 00:13:01 +0000 Subject: [PATCH 03/18] update pre-commit hooks --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e82779e..7350b76 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-yaml args: [--unsafe] From 817fc9d506e31a19105216f44b13d627ab9bba16 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 11:42:19 -0700 Subject: [PATCH 04/18] Add `ruff` --- poetry.lock | 125 +++++++++++-------------------------------------- pyproject.toml | 55 ++++++++++++++++++++-- 2 files changed, 79 insertions(+), 101 deletions(-) diff --git a/poetry.lock b/poetry.lock index fcc400a..2be048b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -53,41 +53,6 @@ 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" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.7" -files = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "certifi" version = "2024.2.2" @@ -209,20 +174,6 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" @@ -444,20 +395,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {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.6)"] - [[package]] name = "jinja2" version = "3.1.3" @@ -697,17 +634,6 @@ files = [ {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - [[package]] name = "myst-parser" version = "2.0.0" @@ -759,17 +685,6 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {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 = "4.2.0" @@ -1002,7 +917,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1010,15 +924,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1035,7 +942,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1043,7 +949,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -1070,6 +975,32 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "ruff" +version = "0.3.6" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.3.6-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:732ef99984275534f9466fbc01121523caf72aa8c2bdeb36fd2edf2bc294a992"}, + {file = "ruff-0.3.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:93699d61116807edc5ca1cdf9d2d22cf8d93335d59e3ff0ca7aee62c1818a736"}, + {file = "ruff-0.3.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc4006cbc6c11fefc25f122d2eb4731d7a3d815dc74d67c54991cc3f99c90177"}, + {file = "ruff-0.3.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:878ef1a55ce931f3ca23b690b159cd0659f495a4c231a847b00ca55e4c688baf"}, + {file = "ruff-0.3.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecb87788284af96725643eae9ab3ac746d8cc09aad140268523b019f7ac3cd98"}, + {file = "ruff-0.3.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b2e79f8e1b6bd5411d7ddad3f2abff3f9d371beda29daef86400d416dedb7e02"}, + {file = "ruff-0.3.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf48ec2c4bfae7837dc325c431a2932dc23a1485e71c59591c1df471ba234e0e"}, + {file = "ruff-0.3.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c466a52c522e6a08df0af018f550902f154f5649ad09e7f0d43da766e7399ebc"}, + {file = "ruff-0.3.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28ccf3fb6d1162a73cd286c63a5e4d885f46a1f99f0b392924bc95ccbd18ea8f"}, + {file = "ruff-0.3.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b11e09439d9df6cc12d9f622065834654417c40216d271f639512d80e80e3e53"}, + {file = "ruff-0.3.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:647f1fb5128a3e24ce68878b8050bb55044c45bb3f3ae4710d4da9ca96ede5cb"}, + {file = "ruff-0.3.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2b0c4c70578ef1871a9ac5c85ed7a8c33470e976c73ba9211a111d2771b5f787"}, + {file = "ruff-0.3.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e3da499ded004d0b956ab04248b2ae17e54a67ffc81353514ac583af5959a255"}, + {file = "ruff-0.3.6-py3-none-win32.whl", hash = "sha256:4056480f5cf38ad278667c31b0ef334c29acdfcea617cb89c4ccbc7d96f1637f"}, + {file = "ruff-0.3.6-py3-none-win_amd64.whl", hash = "sha256:f1aa621beed533f46e9c7d6fe00e7f6e4570155b61d8f020387b72ace2b42e04"}, + {file = "ruff-0.3.6-py3-none-win_arm64.whl", hash = "sha256:7c8a2a0e0cab077a07465259ffe3b3c090e747ca8097c5dc4c36ca0fdaaac90d"}, + {file = "ruff-0.3.6.tar.gz", hash = "sha256:26071fb530038602b984e3bbe1443ef82a38450c4dcb1344a9caf67234ff9756"}, +] + [[package]] name = "setuptools" version = "69.1.1" @@ -1572,4 +1503,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "59d873929c1d5c720280d77471b88aedf160fe781363769ded86bb86783f08a7" +content-hash = "4733215c87b487b90c900694fbd2b99ad031934515d9e0cda40ac0eaef2768f1" diff --git a/pyproject.toml b/pyproject.toml index ada4ed8..6ec143c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,9 +23,8 @@ portalocker = "^2.8.2" inflection = "^0.5.1" [tool.poetry.group.dev.dependencies] -black = "^22.10.0" -isort = "^5.10.1" pre-commit = "^3.5.0" +ruff = "^0.3.6" [tool.poetry.group.test.dependencies] pytest = "^8.0.2" @@ -44,8 +43,56 @@ myst-parser = "^2.0.0" requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" -[tool.isort] -profile = "black" +[tool.ruff] +cache-dir = "~/.cache/ruff" +extend-exclude = ["*migrations/*"] +line-length = 92 +target-version = "py38" +show-fixes = true + +[tool.ruff.lint] +ignore = [ + "D205", # 1 blank line required between summary line and description (does not allow wrapping of summary lines) + "D407", # Dashed underline after doc section (not compatible with google style) +] +select = [ # https://docs.astral.sh/ruff/rules + "F", # pyflakes + "E", # pycodestyle + "W", # pycodestyle + "C90", # mccabe + "I", # isort + "N", # pep8-naming + "D", # pydocstyle + "UP", # pyupgrade + "B", # flake8-bugbear + "S", # flake8-bandit + "A", # flake8-builtins + "C4", # flake8-comprehensions + "DTZ", # flake8-datetimez + "ISC", # flake8-implicit-str-concat + "EXE", # flake8-executable + "PT", # flake8-pytest-style + "Q", # flake8-quotes + "RET", # flake8-return + "TCH", # flake8-type-checking + "SIM", # flake8-simplify + "T20", # flake8-print + "TID", # flake8-tidy-imports + "ERA", # eradicate + "PL", # pylint + "RUF", # ruff +] +unfixable = ["D407"] + +[tool.ruff.lint.flake8-pytest-style] +fixture-parentheses = false +mark-parentheses = false + +[tool.ruff.lint.isort] +combine-as-imports = true + +[tool.ruff.lint.pydocstyle] +convention = "google" [tool.coverage.run] omit = ["test/*"] From 52e64d146461dcdfc0a859278b50deae4bdd3ffa Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 15:16:26 -0700 Subject: [PATCH 05/18] Fix lint violations --- docs/conf.py | 2 +- pyproject.toml | 7 ++++++ test/conftest.py | 20 ++++++++--------- test/test_assessments.py | 25 +++++++-------------- test/test_authentication.py | 2 +- test/test_base.py | 3 ++- test/test_calendar.py | 1 - test/test_cdts.py | 3 +-- test/test_document.py | 19 ++++++++-------- test/test_encounters.py | 6 ++--- test/test_formation.py | 4 +--- test/test_patients.py | 4 +++- test/test_program.py | 6 ++--- test/test_util.py | 33 ++++++++++----------------- welkin/__init__.py | 4 +++- welkin/__version__.py | 2 +- welkin/authentication.py | 16 ++++++------- welkin/client.py | 32 ++++++++++++++++---------- welkin/exceptions.py | 5 ++--- welkin/models/assessment.py | 2 +- welkin/models/base.py | 13 ++++++----- welkin/models/calendar.py | 36 ++++++++++++++--------------- welkin/models/care_plan.py | 2 +- welkin/models/cdt.py | 16 ++++++------- welkin/models/chat.py | 8 +++---- welkin/models/document.py | 6 ++--- welkin/models/email.py | 4 ++-- welkin/models/encounter.py | 33 ++++++++++++++------------- welkin/models/formation.py | 8 ++----- welkin/models/patient.py | 20 ++++++++--------- welkin/models/program.py | 28 +++++++++++++---------- welkin/models/sms.py | 4 ++-- welkin/models/user.py | 22 ++++++++---------- welkin/pagination.py | 45 ++++++++++++++++--------------------- welkin/util.py | 16 +++++++------ 35 files changed, 219 insertions(+), 238 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 07e9558..ef54d87 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,7 +8,7 @@ import welkin project = welkin.__name__ -copyright = welkin.__copyright__ +copyright = welkin.__copyright__ # noqa: A001 author = welkin.__author__ release = welkin.__version__ diff --git a/pyproject.toml b/pyproject.toml index 6ec143c..bb5c52c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ show-fixes = true [tool.ruff.lint] ignore = [ + "D1", # Missing docstrings "D205", # 1 blank line required between summary line and description (does not allow wrapping of summary lines) "D407", # Dashed underline after doc section (not compatible with google style) ] @@ -91,6 +92,12 @@ mark-parentheses = false [tool.ruff.lint.isort] combine-as-imports = true +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["E402"] +"**/{tests,docs}/*" = ["S", "PLR2004", "PLR0913"] +"**/conftest.py" = ["S", "PLR2004", "PLR0913"] +"**/test*.py" = ["S", "PLR2004", "PLR0913"] + [tool.ruff.lint.pydocstyle] convention = "google" diff --git a/test/conftest.py b/test/conftest.py index 654ddf2..612d831 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -5,7 +5,6 @@ from datetime import date, datetime, time, timedelta, timezone from http import HTTPStatus from pathlib import Path -from uuid import uuid4 import pytest @@ -15,7 +14,7 @@ def pytest_collection_modifyitems(items): # Ensure auth tests execute first, otherwise all other tests will fail. - items.sort(key=lambda x: True if "authentication" not in x.nodeid else False) + items.sort(key=lambda x: "authentication" not in x.nodeid) def redact(field_name, extra=""): @@ -34,12 +33,12 @@ def redact(field_name, extra=""): "updatedBy", "updatedByName", ] -CLIENT_INIT = dict( - tenant=os.environ["WELKIN_TENANT"], - instance=os.environ["WELKIN_INSTANCE"], - api_client=os.environ["WELKIN_API_CLIENT"], - secret_key=os.environ["WELKIN_SECRET"], -) +CLIENT_INIT = { + "tenant": os.environ["WELKIN_TENANT"], + "instance": os.environ["WELKIN_INSTANCE"], + "api_client": os.environ["WELKIN_API_CLIENT"], + "secret_key": os.environ["WELKIN_SECRET"], +} @pytest.fixture(scope="module") @@ -61,7 +60,6 @@ def vcr(vcr): def scrub_request(blacklist, replacement="REDACTED"): def before_record_request(request): - # request.body = filter_body(request.body, blacklist, replacement) if "api_clients" in request.path: return None uri_comps = request.uri.split("/") @@ -188,5 +186,5 @@ def est_datetime_str(): @pytest.fixture -def _uuid(): - return uuid4() +def uuid4(): + return uuid.uuid4() diff --git a/test/test_assessments.py b/test/test_assessments.py index 034b8f0..b817c79 100644 --- a/test/test_assessments.py +++ b/test/test_assessments.py @@ -8,14 +8,10 @@ def test_assessment_record_answers_update(client, vcr_cassette): patient = client.Patient(id="371dd15c-cedc-4425-a394-d666c8d3fc01") - assmt_record = patient.AssessmentRecord( - id="c8764b19-ffa3-406a-b446-c971036a7a1d" - ).get() + assmt_record = patient.AssessmentRecord(id="c8764b19-ffa3-406a-b446-c971036a7a1d").get() hi_answer = assmt_record.answers["cdt-hello__cdtf-hi"] assmt_record.AssessmentRecordAnswers(**{"cdt-hello__cdtf-hi": "abc123def"}).update() - assmt_record = patient.AssessmentRecord( - id="c8764b19-ffa3-406a-b446-c971036a7a1d" - ).get() + assmt_record = patient.AssessmentRecord(id="c8764b19-ffa3-406a-b446-c971036a7a1d").get() assert assmt_record.answers["cdt-hello__cdtf-hi"] == "abc123def" assert hi_answer != assmt_record.answers["cdt-hello__cdtf-hi"] @@ -26,9 +22,7 @@ def test_assessment_record_answers_update(client, vcr_cassette): def test_assessment_record_get(client, vcr_cassette): patient = client.Patient(id="371dd15c-cedc-4425-a394-d666c8d3fc01") - assmt_record = patient.AssessmentRecord( - id="c8764b19-ffa3-406a-b446-c971036a7a1d" - ).get() + assmt_record = patient.AssessmentRecord(id="c8764b19-ffa3-406a-b446-c971036a7a1d").get() assert isinstance(assmt_record, AssessmentRecord) assert assmt_record.id == "c8764b19-ffa3-406a-b446-c971036a7a1d" @@ -37,9 +31,9 @@ def test_assessment_record_get(client, vcr_cassette): @pytest.mark.vcr def test_assessment_record_get_w_patient_id(client, vcr_cassette): - assmt_record = client.AssessmentRecord( - id="c8764b19-ffa3-406a-b446-c971036a7a1d" - ).get(patient_id="371dd15c-cedc-4425-a394-d666c8d3fc01") + assmt_record = client.AssessmentRecord(id="c8764b19-ffa3-406a-b446-c971036a7a1d").get( + patient_id="371dd15c-cedc-4425-a394-d666c8d3fc01" + ) assert isinstance(assmt_record, AssessmentRecord) assert assmt_record.id == "c8764b19-ffa3-406a-b446-c971036a7a1d" @@ -50,9 +44,7 @@ def test_assessment_record_get_w_patient_id(client, vcr_cassette): def test_assessment_record_update(client, vcr_cassette): patient = client.Patient(id="371dd15c-cedc-4425-a394-d666c8d3fc01") - assmt_record = patient.AssessmentRecord( - id="e18a2759-5089-44e7-9d31-cf942476ffab" - ).get() + assmt_record = patient.AssessmentRecord(id="e18a2759-5089-44e7-9d31-cf942476ffab").get() status = assmt_record.status assmt_record.status = "COMPLETED" @@ -84,8 +76,7 @@ def test_assessment_record_delete(client, vcr_cassette): with pytest.raises(WelkinHTTPError) as excinfo: assmt_record.get() - assert excinfo.value.response.status_code == 404 - + assert excinfo.value.response.status_code == 404 assert len(vcr_cassette) == 2 diff --git a/test/test_authentication.py b/test/test_authentication.py index 9d731ac..785c1b3 100644 --- a/test/test_authentication.py +++ b/test/test_authentication.py @@ -13,7 +13,7 @@ def auth_class(client): auth.token_method = lambda: {"token": "API_TOKEN"} try: - auth.token + auth.token # noqa: B018 except dbm.error: Path(DB_PATH).unlink() return auth_class(client) diff --git a/test/test_base.py b/test/test_base.py index 9531f54..b3c22ed 100644 --- a/test/test_base.py +++ b/test/test_base.py @@ -31,7 +31,8 @@ def test_method_args(client, class_name: str): continue # skip dunder methods if hasattr(method, "__wrapped__"): - method = method.__wrapped__ # unwrap decorated functions + # unwrap decorated functions + method = method.__wrapped__ # noqa: PLW2901 if method.__qualname__ != f"{class_name}.{method_name}": continue # skip methods from parent classes diff --git a/test/test_calendar.py b/test/test_calendar.py index 6af58f9..65692ce 100644 --- a/test/test_calendar.py +++ b/test/test_calendar.py @@ -8,7 +8,6 @@ CalendarEvents, Schedule, Schedules, - WorkHours, ) UTC = timezone.utc diff --git a/test/test_cdts.py b/test/test_cdts.py index 1d07893..807ad7d 100644 --- a/test/test_cdts.py +++ b/test/test_cdts.py @@ -100,6 +100,5 @@ def test_cdt_delete(client, vcr_cassette): with pytest.raises(WelkinHTTPError) as excinfo: cdt.get() - assert excinfo.value.response.status_code == 404 - + assert excinfo.value.response.status_code == 404 assert len(vcr_cassette) == 3 diff --git a/test/test_document.py b/test/test_document.py index b52253b..3b0d9fb 100644 --- a/test/test_document.py +++ b/test/test_document.py @@ -25,9 +25,7 @@ def test_document_summaries_get_patient_id(client, vcr_cassette): @pytest.mark.vcr def test_document_summaries_subresource(client, vcr_cassette): documents = ( - client.Patient(id="283f50d3-0840-426f-b07b-bd8e4ab76401") - .DocumentSummaries() - .get() + client.Patient(id="283f50d3-0840-426f-b07b-bd8e4ab76401").DocumentSummaries().get() ) assert isinstance(documents, DocumentSummaries) @@ -50,17 +48,16 @@ def test_document_summary_get(client, vcr_cassette): @pytest.mark.vcr def test_document_summary_delete(client, vcr_cassette): - document = client.Patient( - id="283f50d3-0840-426f-b07b-bd8e4ab76401" - ).DocumentSummary(id="5106ec9d-da83-4ce6-89d0-6a9b7fde0138") + document = client.Patient(id="283f50d3-0840-426f-b07b-bd8e4ab76401").DocumentSummary( + id="5106ec9d-da83-4ce6-89d0-6a9b7fde0138" + ) document.delete() with pytest.raises(WelkinHTTPError) as excinfo: document.get() - assert excinfo.value.response.status_code == 404 - + assert excinfo.value.response.status_code == 404 assert len(vcr_cassette) == 2 @@ -79,7 +76,11 @@ def test_document_summary_create(client, vcr_cassette): @pytest.mark.vcr @pytest.mark.skip( - reason="the bytes upload hits this issue in vcr: https://github.com/kevin1024/vcrpy/issues/660 but this test shows the correct implementation" + 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: diff --git a/test/test_encounters.py b/test/test_encounters.py index 1e5d159..bff37fd 100644 --- a/test/test_encounters.py +++ b/test/test_encounters.py @@ -121,8 +121,7 @@ def test_encounter_delete(client, vcr_cassette): with pytest.raises(WelkinHTTPError) as excinfo: encounter.get() - assert excinfo.value.response.status_code == 404 - + assert excinfo.value.response.status_code == 404 assert len(vcr_cassette) == 3 @@ -242,8 +241,7 @@ def test_encounter_assessment_delete(client, vcr_cassette): with pytest.raises(WelkinHTTPError) as excinfo: assessment.get() - assert excinfo.value.response.status_code == 404 - + assert excinfo.value.response.status_code == 404 assert len(vcr_cassette) == 2 diff --git a/test/test_formation.py b/test/test_formation.py index 953c443..dc255e4 100644 --- a/test/test_formation.py +++ b/test/test_formation.py @@ -88,9 +88,7 @@ def test_encounters_read(self, formation, vcr_cassette): @pytest.mark.vcr def test_encounter_read(self, formation, vcr_cassette): - encounter_template = formation.Encounter( - name="etmp-coaching-introduction" - ).get() + encounter_template = formation.Encounter(name="etmp-coaching-introduction").get() assert isinstance(encounter_template, Encounter) assert encounter_template.name == "etmp-coaching-introduction" diff --git a/test/test_patients.py b/test/test_patients.py index c768851..7f40c70 100644 --- a/test/test_patients.py +++ b/test/test_patients.py @@ -18,7 +18,9 @@ def test_patient_create(client, vcr_cassette): @pytest.mark.vcr def test_patient_create_birthdate(client, vcr_cassette): patient = client.Patient( - firstName="happy", lastName="borf", birthDate=date.today() + firstName="happy", + lastName="borf", + birthDate=date.today(), # noqa: DTZ011 ).create() assert isinstance(patient, Patient) diff --git a/test/test_program.py b/test/test_program.py index 55a7c8f..26c2cc6 100644 --- a/test/test_program.py +++ b/test/test_program.py @@ -60,9 +60,7 @@ def patient_program( "programName", ], ) - def test_read( - self, patient: Patient, patient_program: PatientProgram, identifier: str - ): + def test_read(self, patient: Patient, patient_program: PatientProgram, identifier: str): prog = patient.PatientProgram( **{identifier: getattr(patient_program, identifier)} ).get() @@ -74,7 +72,7 @@ def test_read( assert prog.id == patient_program.id def test_read_no_id(self, client): - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="Program must have"): client.Patient(id="notarealid").PatientProgram().get() def test_update( diff --git a/test/test_util.py b/test/test_util.py index 4f58f19..a5fc060 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -17,7 +17,7 @@ class TestCleanRequestPayload: @pytest.fixture - def payload(self, _uuid, base_date, utc_datetime, pst_datetime): + def payload(self, uuid4, base_date, utc_datetime, pst_datetime): return { "datetime": pst_datetime, "date": base_date, @@ -30,12 +30,12 @@ def payload(self, _uuid, base_date, utc_datetime, pst_datetime): "int": [-sys.maxsize, 0, sys.maxsize], "float": [sys.float_info.min, 1, sys.float_info.max], "bool": [True, False], - "_uuid4": _uuid, + "uuid4": uuid4, "none": None, } def test_clean_request_payload( - self, payload, _uuid, pst_datetime_str, base_date_str, utc_datetime_str + self, payload, uuid4, pst_datetime_str, base_date_str, utc_datetime_str ): payload_copy = copy.deepcopy(payload) cleaned = clean_request_payload(payload) @@ -45,7 +45,7 @@ def test_clean_request_payload( 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) + assert cleaned["uuid4"] == str(uuid4) class TestCleanJsonList: @@ -98,20 +98,11 @@ def test_clean_date(base_date, base_date_str): @pytest.mark.parametrize( - "dt,expected", + ("dt", "expected"), [ - ( - "utc_datetime", - "utc_datetime_str", - ), - ( - "pst_datetime", - "pst_datetime_str", - ), - ( - "est_datetime", - "est_datetime_str", - ), + ("utc_datetime", "utc_datetime_str"), + ("pst_datetime", "pst_datetime_str"), + ("est_datetime", "est_datetime_str"), ], ) def test_clean_datetime(dt, expected, request): @@ -120,7 +111,7 @@ def test_clean_datetime(dt, expected, request): @pytest.mark.parametrize( - "input", + "string", [ "foo_bar", "fooBar", @@ -130,9 +121,9 @@ def test_clean_datetime(dt, expected, request): "FOOBar", ], ) -def test_case_converters(input): - assert to_camel_case(input) == "fooBar" - assert to_snake_case(input) == "foo_bar" +def test_case_converters(string): + assert to_camel_case(string) == "fooBar" + assert to_snake_case(string) == "foo_bar" def test_find_model_id(client): diff --git a/welkin/__init__.py b/welkin/__init__.py index 1f9ce36..c57cc8d 100644 --- a/welkin/__init__.py +++ b/welkin/__init__.py @@ -1,4 +1,4 @@ -"""Welkin Health API wrapper +"""Welkin Health API wrapper. https://developers.welkinhealth.com/ @@ -46,6 +46,8 @@ +}B{KGTG6#zG%P;tQm0C """ +# ruff: noqa: F401 + from welkin.__version__ import ( __author__, __author_email__, diff --git a/welkin/__version__.py b/welkin/__version__.py index 94828b8..4834d71 100644 --- a/welkin/__version__.py +++ b/welkin/__version__.py @@ -12,4 +12,4 @@ __author__ = _dist_metadata["author"] __author_email__ = _dist_metadata["author_email"] __license__ = _dist_metadata["license"] -__copyright__ = f"{date.today().year} Lightmatter" +__copyright__ = f"{date.today().year} Lightmatter" # noqa: DTZ011 diff --git a/welkin/authentication.py b/welkin/authentication.py index f722538..bcf1cec 100644 --- a/welkin/authentication.py +++ b/welkin/authentication.py @@ -50,12 +50,11 @@ def __call__(self, r: PreparedRequest) -> PreparedRequest: @property def token(self) -> str: - with Lock(DB_LOCK): - with shelve.open(DB_PATH) as db: - try: - return db[self.tenant]["token"] - except KeyError: - pass + with Lock(DB_LOCK), shelve.open(DB_PATH) as db: # noqa: S301 + try: + return db[self.tenant]["token"] + except KeyError: + pass self.refresh_token() @@ -63,9 +62,8 @@ def token(self) -> str: @token.setter def token(self, value: dict) -> None: - with Lock(DB_LOCK): - with shelve.open(DB_PATH) as db: - db[self.tenant] = value + with Lock(DB_LOCK), shelve.open(DB_PATH) as db: # noqa: S301 + db[self.tenant] = value def refresh_token(self) -> None: self.token = self.token_method() diff --git a/welkin/client.py b/welkin/client.py index 94751c0..7012472 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -1,4 +1,4 @@ -"""Client +"""Client. This module provides a Client object to interface with the Welkin Health API. """ @@ -63,7 +63,7 @@ class Client(Session): user = welkin.User(id="301b2895-cbf0-4cac-b4cf-1d082faee95c").get() # Read users = welkin.Users().get() # Read all/list uasers = welkin.Users().get( - search="lightmatter", region="east-coast", seat_assigned=True, user_state="ACTIVE" + search="foo", region="east-coast", seat_assigned=True, user_state="ACTIVE" ) # Filtered read all/list user.update(firstName="Baz") # Update @@ -107,7 +107,7 @@ class Client(Session): Users = models.Users WorkHours = models.WorkHours - def __init__( + def __init__( # noqa: PLR0913 self, tenant, instance, @@ -172,12 +172,12 @@ def prepare_request(self, request): return super().prepare_request(request) - def request( + def request( # noqa: C901, PLR0912 self, method: str, path: str, - meta_key: str = None, - meta_dict: dict = {}, + meta_key: str | None = None, + meta_dict: dict | None = None, *args, **kwargs, ): @@ -186,17 +186,23 @@ def request( Args: method (str): Method for the new Request object. path (str): Path from host for the new Request object. + meta_key (str | None, optional): Key for metadata in the response JSON. + Defaults to None. + meta_dict (dict | None, optional): Metadata dictionary for the response JSON. + Defaults to None. + *args: Arguments to pass to `Session.request`. + **kwargs: Keyword arguments to pass to `Session.request`. Returns: dict: Response JSON """ if not isinstance(path, str): - path = "/".join((str(s) for s in path if s)) + path = "/".join(str(s) for s in path if s) path = path.rstrip("/") for _ in range(2): response = super().request( - method=method, url=urljoin(self.host, path), *args, **kwargs + *args, method=method, url=urljoin(self.host, path), **kwargs ) try: @@ -269,10 +275,10 @@ def request( return resource or json def get_token(self) -> dict: - data = {"secret": self.auth.secret_key} - response = self.post(f"admin/api_clients/{self.auth.api_client}", json=data) - - return response + return self.post( + f"admin/api_clients/{self.auth.api_client}", + json={"secret": self.auth.secret_key}, + ) class TimeoutHTTPAdapter(HTTPAdapter): @@ -282,6 +288,8 @@ def __init__(self, timeout, *args, **kwargs): Args: timeout (int): How many seconds to wait for the server to send data before giving up. + *args: Arguments to pass to `HTTPAdapter`. + **kwargs: Keyword arguments to pass to `HTTPAdapter`. """ self.timeout = timeout super().__init__(*args, **kwargs) diff --git a/welkin/exceptions.py b/welkin/exceptions.py index 39392cd..058def8 100644 --- a/welkin/exceptions.py +++ b/welkin/exceptions.py @@ -1,3 +1,4 @@ +import contextlib import json from requests import HTTPError @@ -22,9 +23,7 @@ def __init__(self, exc): response = exc.response msg = exc.args[0] - try: + with contextlib.suppress(json.JSONDecodeError): msg = f"{msg}\n{json.dumps(response.json(), indent=2)}" - except json.JSONDecodeError: - pass super(HTTPError, self).__init__(msg, request=request, response=response) diff --git a/welkin/models/assessment.py b/welkin/models/assessment.py index 457c490..58770d6 100644 --- a/welkin/models/assessment.py +++ b/welkin/models/assessment.py @@ -58,7 +58,7 @@ def update(self, patient_id: str, assessment_record_id: str): class AssessmentRecord(Resource): - subresources = [AssessmentRecordAnswers] + subresources = (AssessmentRecordAnswers,) @model_id("Patient") def create(self, patient_id: str): diff --git a/welkin/models/base.py b/welkin/models/base.py index a438c8c..8ac48c1 100644 --- a/welkin/models/base.py +++ b/welkin/models/base.py @@ -1,4 +1,5 @@ import sys +from types import MappingProxyType from welkin.pagination import PageIterator @@ -6,7 +7,7 @@ class SchemaBase: _client = None _parent = None - subresources = [] + subresources = () def __getattr__(self, name): try: @@ -25,7 +26,7 @@ def __getattr__(self, name): class Resource(dict, SchemaBase): - nested_objects = {} + nested_objects = MappingProxyType({}) def __getattr__(self, name): try: @@ -49,7 +50,7 @@ def __delattr__(self, name): super().__delitem__(name) def __str__(self): - id = getattr(self, "id", "") + id = getattr(self, "id", "") # noqa: A001 return f"{self.__class__.__name__} #{id}" if id else self.__class__.__name__ @@ -65,8 +66,8 @@ def get(self, resource, subresource=None, *args, **kwargs): def patch(self, resource, data, *args, **kwargs): response = self._client.patch( resource, - json=data, *args, + json=data, **kwargs, ) @@ -77,8 +78,8 @@ def patch(self, resource, data, *args, **kwargs): def post(self, resource, *args, **kwargs): response = self._client.post( resource, - json=self, *args, + json=self, **kwargs, ) super().update(response) @@ -88,8 +89,8 @@ def post(self, resource, *args, **kwargs): def put(self, resource, *args, **kwargs): response = self._client.put( resource, - json=self, *args, + json=self, **kwargs, ) diff --git a/welkin/models/calendar.py b/welkin/models/calendar.py index 90b1cff..9333a9f 100644 --- a/welkin/models/calendar.py +++ b/welkin/models/calendar.py @@ -1,4 +1,4 @@ -from datetime import datetime, timezone +from datetime import datetime from enum import Enum from welkin.models.base import Collection, Resource @@ -34,9 +34,7 @@ def get(self): return super().get(f"{self._client.instance}/calendar/events/{self.id}") def update(self, **kwargs): - return super().patch( - f"{self._client.instance}/calendar/events/{self.id}", kwargs - ) + return super().patch(f"{self._client.instance}/calendar/events/{self.id}", kwargs) def delete(self): return super().delete(f"{self._client.instance}/calendar/events/{self.id}") @@ -46,17 +44,17 @@ class CalendarEvents(Collection): resource = CalendarEvent iterator = PageableIterator - def get( + def get( # noqa: PLR0913 self, from_date: datetime, to_date: datetime, - participant_ids: list = None, - event_type: str = None, - sort: str = None, - include_cancelled: bool = None, - include_encounter_info: bool = None, - exclude_assigned_to_encounter_events: bool = None, - viewer_timezone: str = None, + participant_ids: list | None = None, + event_type: str | None = None, + sort: str | None = None, + include_cancelled: bool | None = None, + include_encounter_info: bool | None = None, + exclude_assigned_to_encounter_events: bool | None = None, + viewer_timezone: str | None = None, *args, **kwargs, ): @@ -78,7 +76,7 @@ def get( } return super().get( - f"{self._client.instance}/calendar/events", params=params, *args, **kwargs + f"{self._client.instance}/calendar/events", *args, params=params, **kwargs ) @@ -90,12 +88,12 @@ class Schedules(Collection): resource = Schedule iterator = PageableIterator - def get( + def get( # noqa: PLR0913 self, ids: list, from_date: datetime, to_date: datetime, - include_cancelled: bool = None, + include_cancelled: bool | None = None, available: bool = False, full: bool = False, *args, @@ -115,7 +113,7 @@ def get( } return super().get( - f"{self._client.instance}/calendar/{route}", params=params, *args, **kwargs + f"{self._client.instance}/calendar/{route}", *args, params=params, **kwargs ) @@ -126,8 +124,8 @@ def get( self, from_date: datetime, to_date: datetime, - psm_ids: list = None, - timezone: str = None, + psm_ids: list | None = None, + timezone: str | None = None, *args, **kwargs, ): @@ -146,7 +144,7 @@ def get( ) # When no work hours are found Welkin returns an {None: []} dictionary - if isinstance(response, dict) and None in response.keys(): + if isinstance(response, dict) and None in response: return WorkHours([]) return response diff --git a/welkin/models/care_plan.py b/welkin/models/care_plan.py index 1423b36..e962e3f 100644 --- a/welkin/models/care_plan.py +++ b/welkin/models/care_plan.py @@ -11,7 +11,7 @@ def update(self, patient_id: str): class CarePlan(Resource): - subresources = [CarePlanOverview] + subresources = (CarePlanOverview,) @model_id("Patient") def create(self, patient_id: str): diff --git a/welkin/models/cdt.py b/welkin/models/cdt.py index 7d45588..ba476fa 100644 --- a/welkin/models/cdt.py +++ b/welkin/models/cdt.py @@ -37,15 +37,15 @@ class CDTs(Collection): iterator = PageNumberIterator @model_id("Patient") - def get( + def get( # noqa: PLR0913 self, patient_id: str, cdt_name: str, - fields: list = None, - filters: dict = None, - date_start: datetime = None, - date_end: datetime = None, - sort: str = None, + fields: list | None = None, + filters: dict | None = None, + date_start: datetime | None = None, + date_end: datetime | None = None, + sort: str | None = None, *args, **kwargs, ): @@ -59,13 +59,13 @@ def get( return super().get( f"{self._client.instance}/patients/{patient_id}/cdts/{cdt_name}", - params=params, *args, + params=params, **kwargs, ) @model_id("Patient") - def update(self, patient_id: str, cdt_name: str, body: dict = None, **kwargs): + def update(self, patient_id: str, cdt_name: str, body: dict | None = None, **kwargs): return super().patch( f"{self._client.instance}/patients/{patient_id}/cdts/{cdt_name}", json=body, diff --git a/welkin/models/chat.py b/welkin/models/chat.py index 64d8c3e..ba4fafd 100644 --- a/welkin/models/chat.py +++ b/welkin/models/chat.py @@ -6,9 +6,7 @@ class Chat(Resource): @model_id("Patient") def create(self, patient_id: str): - return super().post( - f"{self._client.instance}/patients/{patient_id}/chat/inbound" - ) + return super().post(f"{self._client.instance}/patients/{patient_id}/chat/inbound") def __str__(self): return f"{self.sender['clientType']} {self.message}" @@ -26,8 +24,8 @@ def get(self, patient_id: str, include_archived: bool = False, *args, **kwargs): return super().get( f"{self._client.instance}/patients/{patient_id}/chat", - params=params, *args, + params=params, **kwargs, ) @@ -58,7 +56,7 @@ def get( return super().get( f"{self._client.instance}/patients/{patient_id}/chat/search", - params=params, *args, + params=params, **kwargs, ) diff --git a/welkin/models/document.py b/welkin/models/document.py index 5286338..6611244 100644 --- a/welkin/models/document.py +++ b/welkin/models/document.py @@ -25,21 +25,21 @@ def create( self, patient_id: str, document_summary_id: str, - files: list = None, + files: list | None = None, *args, **kwargs, ): return super().post( f"{self._client.instance}/patients/{patient_id}/document-summary/" f"{document_summary_id}/files", - files=files, *args, + files=files, **kwargs, ) class DocumentSummary(Resource): - subresources = [DocumentSummaryFile, DocumentSummaryFiles] + subresources = (DocumentSummaryFile, DocumentSummaryFiles) @model_id("Patient") def get(self, patient_id: str): diff --git a/welkin/models/email.py b/welkin/models/email.py index 4890adc..5c6943d 100644 --- a/welkin/models/email.py +++ b/welkin/models/email.py @@ -18,14 +18,14 @@ class Emails(Collection): iterator = PageableIterator @model_id("Patient") - def get(self, patient_id: str, sort: str = None, *args, **kwargs): + def get(self, patient_id: str, sort: str | None = None, *args, **kwargs): params = { "sort": sort, } return super().get( f"{self._client.instance}/patients/{patient_id}/emails", - params=params, *args, + params=params, **kwargs, ) diff --git a/welkin/models/encounter.py b/welkin/models/encounter.py index 49255e9..7d6edb0 100644 --- a/welkin/models/encounter.py +++ b/welkin/models/encounter.py @@ -1,4 +1,5 @@ from enum import Enum +from types import MappingProxyType from welkin.models.assessment import Assessment, Assessments from welkin.models.base import Collection, Resource @@ -29,12 +30,14 @@ class EncounterStatus(Enum): class Encounter(Resource): - subresources = [Assessment, Assessments, EncounterDisposition] - nested_objects = { - "assessmentLinks": "Assessments", - "userRelatedToCalendarEvent": "User", - "disposition": "EncounterDisposition", - } + subresources = (Assessment, Assessments, EncounterDisposition) + nested_objects = MappingProxyType( + { + "assessmentLinks": "Assessments", + "userRelatedToCalendarEvent": "User", + "disposition": "EncounterDisposition", + } + ) @model_id("Patient") def create(self, patient_id: str): @@ -68,15 +71,15 @@ class Encounters(Collection): resource = Encounter iterator = MetaInfoIterator - def get( + def get( # noqa: PLR0913 self, - patient_id: str = None, - user_id: str = None, - related_data: bool = None, - with_care_team: bool = None, - only_with_calendar_event: bool = None, - statuses: list = None, - sort: str = None, + patient_id: str | None = None, + user_id: str | None = None, + related_data: bool | None = None, + with_care_team: bool | None = None, + only_with_calendar_event: bool | None = None, + statuses: list | None = None, + sort: str | None = None, *args, **kwargs, ): @@ -99,4 +102,4 @@ def get( "onlyWithCalendarEvent": only_with_calendar_event, } - return super().get(path, params=params, *args, **kwargs) + return super().get(path, *args, params=params, **kwargs) diff --git a/welkin/models/formation.py b/welkin/models/formation.py index 699dc49..47dcc71 100644 --- a/welkin/models/formation.py +++ b/welkin/models/formation.py @@ -1,5 +1,3 @@ -from typing import Union - from welkin.models.base import Collection, Resource from welkin.pagination import FormationIterator from welkin.util import Target, _build_resources @@ -10,9 +8,7 @@ class FormationBase: def __new__(cls, *args, **kwargs): if not cls.endpoint: - raise AttributeError( - f"The `endpoint` attribute must be set on {cls.__name__}" - ) + raise AttributeError(f"The `endpoint` attribute must be set on {cls.__name__}") return super().__new__(cls) @@ -116,7 +112,7 @@ class Formation(Target): Program = Program Programs = Programs - def __init__(self, version: Union[int, str] = "current"): + def __init__(self, version: int | str = "current"): super().__init__() self._base_path = f"{self._client.instance}/formations/{version}" diff --git a/welkin/models/patient.py b/welkin/models/patient.py index a565e91..996edcb 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -16,7 +16,7 @@ class Patient(Resource): - subresources = [ + subresources = ( AssessmentRecord, AssessmentRecords, CarePlan, @@ -36,30 +36,30 @@ class Patient(Resource): SearchChats, SMS, SMSes, - ] + ) def create(self): return super().post(f"{self._client.instance}/patients") - def get(self, expand: bool = None): + def get(self, expand: bool | None = None): _id = None if hasattr(self, "id"): - type = None + _type = None _id = self.id elif hasattr(self, "externalId"): - type = "EID" + _type = "EID" _id = self.externalId elif hasattr(self, "externalGuid"): - type = "EGUID" + _type = "EGUID" _id = self.externalGuid elif hasattr(self, "mrn"): - type = "MRN" + _type = "MRN" _id = self.mrn return super().get( f"{self._client.instance}/patients/{_id}", params={ - "type": type, + "type": _type, expand: expand, }, ) @@ -78,8 +78,8 @@ class Patients(Collection): resource = Patient iterator = PageableIterator - def get(self, filter={}, *args, **kwargs): + def get(self, filter: dict | None = None, *args, **kwargs): # noqa: A002 # TODO: Add sort and query arguments. return super().post( - f"{self._client.instance}/by-filter/patients", json=filter, *args, **kwargs + f"{self._client.instance}/by-filter/patients", *args, json=filter, **kwargs ) diff --git a/welkin/models/program.py b/welkin/models/program.py index d451d56..6fe2c6f 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -1,3 +1,5 @@ +from types import MappingProxyType + from welkin.models.base import Collection, Resource from welkin.pagination import MetaInfoIterator from welkin.util import model_id @@ -12,19 +14,21 @@ class ProgramPhases(Collection): class PatientProgram(Resource): - subresources = [ProgramPhase] - nested_objects = { - "phases": "ProgramPhase", - "currentPhase": "ProgramPhase", - "pathHistory": "ProgramPhases", - } + subresources = (ProgramPhase,) + nested_objects = MappingProxyType( + { + "phases": "ProgramPhase", + "currentPhase": "ProgramPhase", + "pathHistory": "ProgramPhases", + } + ) @model_id("Patient") def get( self, patient_id: str, - assigned_programs: bool = None, - sort: str = None, + assigned_programs: bool | None = None, + sort: str | None = None, *args, **kwargs, ): @@ -38,11 +42,11 @@ def get( return super().get( path, + *args, params={ "assignedPrograms": assigned_programs, "sort": sort, }, - *args, **kwargs, ) @@ -69,17 +73,17 @@ class PatientPrograms(Collection): def get( self, patient_id: str, - assigned_programs: bool = None, - sort: str = None, + assigned_programs: bool | None = None, + sort: str | None = None, *args, **kwargs, ): return super().get( f"{self._client.instance}/patients/{patient_id}/programs", + *args, params={ "assignedPrograms": assigned_programs, "sort": sort, }, - *args, **kwargs, ) diff --git a/welkin/models/sms.py b/welkin/models/sms.py index 6a23546..0ee81d5 100644 --- a/welkin/models/sms.py +++ b/welkin/models/sms.py @@ -18,14 +18,14 @@ class SMSes(Collection): iterator = PageableIterator @model_id("Patient") - def get(self, patient_id: str, sort: str = None, *args, **kwargs): + def get(self, patient_id: str, sort: str | None = None, *args, **kwargs): params = { "sort": sort, } return super().get( f"{self._client.instance}/patients/{patient_id}/sms", - params=params, *args, + params=params, **kwargs, ) diff --git a/welkin/models/user.py b/welkin/models/user.py index 11a7190..f4d1d24 100644 --- a/welkin/models/user.py +++ b/welkin/models/user.py @@ -6,7 +6,7 @@ class User(Resource): - subresources = [Encounters] + subresources = (Encounters,) def __str__(self): try: @@ -18,13 +18,13 @@ def create(self): return super().post("admin/users") def get(self): - return super().get(f"admin/users/{self.id}", params=dict(type="ID")) + return super().get(f"admin/users/{self.id}", params={"type": "ID"}) def update(self, **kwargs): return super().patch(f"admin/users/{self.username}", kwargs) def delete(self): - return super().delete(f"admin/users/{self.id}", params=dict(type="ID")) + return super().delete(f"admin/users/{self.id}", params={"type": "ID"}) class UserState(Enum): @@ -39,19 +39,15 @@ class Users(Collection): def get( self, - search: str = None, - region: str = None, - seat_assigned: bool = None, - user_state: str = None, + search: str | None = None, + region: str | None = None, + seat_assigned: bool | None = None, + user_state: str | None = None, *args, **kwargs, ): # TODO: Figure out sort arguments - params = dict( - search=search, - seatAssigned=seat_assigned, - userState=user_state, - ) + params = {"search": search, "seatAssigned": seat_assigned, "userState": user_state} # User state validation if user_state: @@ -62,4 +58,4 @@ def get( path = f"{self._client.instance}/users" params["region"] = region - return super().get(path, params=params, *args, **kwargs) + return super().get(path, *args, params=params, **kwargs) diff --git a/welkin/pagination.py b/welkin/pagination.py index 23a7e4e..6475c08 100644 --- a/welkin/pagination.py +++ b/welkin/pagination.py @@ -1,5 +1,10 @@ +DEFAULT_PAGE_SIZE = 20 + + class PageIterator: - def __init__(self, collection, resource, method, size=20, *args, **kwargs): + def __init__( + self, collection, resource, method, size=DEFAULT_PAGE_SIZE, *args, **kwargs + ): self.collection = collection self.resource = resource self.method = method @@ -7,7 +12,7 @@ def __init__(self, collection, resource, method, size=20, *args, **kwargs): self.meta_key = None self.meta_dict = {"totalPages": 1, "number": 0, "last": True} - if size != 20: + if size != DEFAULT_PAGE_SIZE: kwargs.setdefault("params", {}).update(size=size) self.args = args @@ -28,9 +33,9 @@ def __next__(self): self.resources, meta = self.method( self.resource, + *self.args, meta_key=self.meta_key, meta_dict=self.meta_dict, - *self.args, **self.kwargs, ) @@ -41,15 +46,11 @@ def __next__(self): raise StopIteration def _pre_request(self): - """ - Function to execute before making the next request, e.g. update paging params - """ + """Function to execute before making the next request, e.g. update paging params.""" self.kwargs.setdefault("params", {}) def _post_request(self, meta): - """ - Function to execute after making the next request, e.g. updating page tracking - """ + """Function to execute after making the next request, e.g. update page tracking.""" self.last = True @property @@ -63,9 +64,7 @@ def resources(self, value): class PageableIterator(PageIterator): - """ - Most common paging class - """ + """Most common paging class.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -84,10 +83,10 @@ def _post_request(self, meta): class FormationIterator(PageIterator): - """ - Specifically for paginating formations responses - Similar to PageableIterator but includes special behavior for - single item formations, e.g. encounter disposition + """Specifically for paginating formations responses. + + Similar to PageableIterator but includes special behavior for single item formations, + e.g. encounter disposition """ def __init__(self, *args, **kwargs): @@ -107,9 +106,9 @@ def __next__(self): data = self.method( self.resource, + *self.args, meta_key=self.meta_key, meta_dict=self.meta_dict, - *self.args, **self.kwargs, ) if isinstance(data, dict): @@ -132,9 +131,7 @@ def _post_request(self, meta): class PageNumberIterator(PageableIterator): - """ - PageableIterator with a different key used for the page count - """ + """PageableIterator with a different key used for the page count.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -147,9 +144,7 @@ def _post_request(self, meta): class MetaInfoIterator(PageIterator): - """ - Functionally identical to PageableIterator with various renamed keys - """ + """Functionally identical to PageableIterator with various renamed keys.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -170,9 +165,7 @@ def _post_request(self, meta): class MetaIterator(PageIterator): - """ - Paging class for token based paging - """ + """Paging class for token based paging.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/welkin/util.py b/welkin/util.py index 05ae8b7..58193d1 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -20,7 +20,9 @@ def __init__(self): _build_resources(self, "_client", self._client) -def _build_resources(instance: type, attribute_name: str, value: type = None) -> None: +def _build_resources( + instance: type, attribute_name: str, value: type | None = None +) -> None: """Add an attribute pointing to an instance for each resource. Args: @@ -54,13 +56,13 @@ def clean_data(value: Any) -> Any: """ if isinstance(value, datetime): return clean_datetime(value) - elif isinstance(value, date): + if isinstance(value, date): return clean_date(value) - elif isinstance(value, dict): + if isinstance(value, dict): return clean_request_payload(value) - elif isinstance(value, list): + if isinstance(value, list): return clean_json_list(value) - elif isinstance(value, UUID): + if isinstance(value, UUID): return str(value) # No cleaning needed @@ -129,9 +131,9 @@ def find_model_id(instance: Union[Collection, Resource], model_name: str) -> str if instance.__class__.__name__ == model_name: return instance.id - elif hasattr(instance, body_id_key): + if hasattr(instance, body_id_key): return getattr(instance, body_id_key) - elif instance._parent is not None: + if instance._parent is not None: return find_model_id(instance._parent, model_name) raise AttributeError( From a158fbc16f87a62110fc7e9d07c22df30aed464a Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 15:18:06 -0700 Subject: [PATCH 06/18] Add `ruff` pre-commit hook --- .pre-commit-config.yaml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7350b76..2ecabae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,14 +8,9 @@ repos: - id: mixed-line-ending ## Python - - repo: https://github.com/pycqa/isort - rev: 5.13.2 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.6 hooks: - - id: isort - types: [python] - - - repo: https://github.com/psf/black - rev: 24.3.0 - hooks: - - id: black - types: [python] + - id: ruff + args: [--fix] + - id: ruff-format From b5db4533c9a63bac647edd018cb9324134786599 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 15:37:21 -0700 Subject: [PATCH 07/18] Fix silent CI failure --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index da12ed2..0556b3c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -59,6 +59,7 @@ jobs: run: poetry run pre-commit run --all-files - name: Run Tests + shell: bash run: | poetry run pytest \ --junitxml=pytest.xml \ From a7ec347b6b3e069bfbb00ea283a1d640951140b8 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 15:39:17 -0700 Subject: [PATCH 08/18] Fix CI --- .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 0556b3c..63a0378 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 --no-interaction --no-root + run: poetry install --no-interaction - name: Run pre-commit run: poetry run pre-commit run --all-files From 44be359190c2295ff86a2983f4e6ae5b171df1e9 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 16:06:00 -0700 Subject: [PATCH 09/18] Fix package metadata --- welkin/__version__.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/welkin/__version__.py b/welkin/__version__.py index 4834d71..3a46c21 100644 --- a/welkin/__version__.py +++ b/welkin/__version__.py @@ -1,15 +1,21 @@ """Package version information.""" -from datetime import date +from __future__ import annotations + +from datetime import datetime, timezone from importlib.metadata import distribution +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from importlib.metadata._adapters import Message -_dist_metadata: dict = distribution("welkin").metadata.json +_metadata: Message = distribution("welkin").metadata -__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" # noqa: DTZ011 +__title__ = _metadata.get("Name") +__description__ = _metadata.get("Summary") +__url__ = _metadata.get("Home-page") +__version__ = _metadata.get("Version") +__author__ = _metadata.get("Author") +__author_email__ = _metadata.get("Author-email") +__license__ = _metadata.get("License") +__copyright__ = f"{datetime.now(tz=timezone.utc):%Y} Lightmatter" From d7872ba010996d606f941c79f699052ff4a580b2 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 16:14:48 -0700 Subject: [PATCH 10/18] Remove `get-python-versions` job --- .github/workflows/ci.yaml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 63a0378..c567983 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -7,26 +7,13 @@ concurrency: 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) }} + python-version: [3.8, 3.9, 3.10, 3.11, 3.12] steps: - name: Checkout ${{ github.repository }} From b8d48f88eafd6e4378d06beaecc572f635617ce4 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 16:15:45 -0700 Subject: [PATCH 11/18] Fix version specifiers --- .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 c567983..e7ab056 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8, 3.9, 3.10, 3.11, 3.12] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - name: Checkout ${{ github.repository }} From e64391f6962410f53efd951aaff34db389c7d35e Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 16:26:33 -0700 Subject: [PATCH 12/18] Add `__future__.annotations` to all modules --- test/conftest.py | 2 ++ test/test_assessments.py | 2 ++ test/test_authentication.py | 2 ++ test/test_base.py | 2 ++ test/test_calendar.py | 2 ++ test/test_care_plan.py | 2 ++ test/test_cdts.py | 2 ++ test/test_chat.py | 2 ++ test/test_client.py | 2 ++ test/test_document.py | 2 ++ test/test_email.py | 2 ++ test/test_encounters.py | 2 ++ test/test_exception.py | 2 ++ test/test_formation.py | 2 ++ test/test_patients.py | 2 ++ test/test_program.py | 9 +++++++-- test/test_sms.py | 2 ++ test/test_users.py | 2 ++ test/test_util.py | 2 ++ welkin/authentication.py | 9 +++++++-- welkin/client.py | 2 ++ welkin/exceptions.py | 2 ++ welkin/models/assessment.py | 2 ++ welkin/models/base.py | 2 ++ welkin/models/calendar.py | 7 ++++++- welkin/models/care_plan.py | 2 ++ welkin/models/cdt.py | 7 ++++++- welkin/models/chat.py | 2 ++ welkin/models/document.py | 2 ++ welkin/models/email.py | 2 ++ welkin/models/encounter.py | 2 ++ welkin/models/formation.py | 2 ++ welkin/models/patient.py | 2 ++ welkin/models/program.py | 2 ++ welkin/models/sms.py | 2 ++ welkin/models/user.py | 2 ++ welkin/pagination.py | 2 ++ welkin/util.py | 10 ++++++---- 38 files changed, 98 insertions(+), 10 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 612d831..cacb3e8 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import inspect import json import os diff --git a/test/test_assessments.py b/test/test_assessments.py index b817c79..8924e29 100644 --- a/test/test_assessments.py +++ b/test/test_assessments.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.exceptions import WelkinHTTPError diff --git a/test/test_authentication.py b/test/test_authentication.py index 785c1b3..4113bce 100644 --- a/test/test_authentication.py +++ b/test/test_authentication.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import dbm from pathlib import Path diff --git a/test/test_base.py b/test/test_base.py index b3c22ed..127eb0d 100644 --- a/test/test_base.py +++ b/test/test_base.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import inspect import pytest diff --git a/test/test_calendar.py b/test/test_calendar.py index 65692ce..4532765 100644 --- a/test/test_calendar.py +++ b/test/test_calendar.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from datetime import datetime, timedelta, timezone import pytest diff --git a/test/test_care_plan.py b/test/test_care_plan.py index 8e7e088..3adb51a 100644 --- a/test/test_care_plan.py +++ b/test/test_care_plan.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.models import CarePlan diff --git a/test/test_cdts.py b/test/test_cdts.py index 807ad7d..e3cee98 100644 --- a/test/test_cdts.py +++ b/test/test_cdts.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.exceptions import WelkinHTTPError diff --git a/test/test_chat.py b/test/test_chat.py index a9cdda4..74532e9 100644 --- a/test/test_chat.py +++ b/test/test_chat.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.models.chat import Chat, Chats, ChatSearchResult, SearchChats diff --git a/test/test_client.py b/test/test_client.py index c022cb8..b303542 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import inspect import pytest diff --git a/test/test_document.py b/test/test_document.py index 3b0d9fb..5405ee9 100644 --- a/test/test_document.py +++ b/test/test_document.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from io import BytesIO import pytest diff --git a/test/test_email.py b/test/test_email.py index e8a42bd..ab340b0 100644 --- a/test/test_email.py +++ b/test/test_email.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.exceptions import WelkinHTTPError diff --git a/test/test_encounters.py b/test/test_encounters.py index bff37fd..a6ff19c 100644 --- a/test/test_encounters.py +++ b/test/test_encounters.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from datetime import datetime, timedelta, timezone import pytest diff --git a/test/test_exception.py b/test/test_exception.py index 833d56a..d0cb8ab 100644 --- a/test/test_exception.py +++ b/test/test_exception.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import pytest diff --git a/test/test_formation.py b/test/test_formation.py index dc255e4..8b88ad1 100644 --- a/test/test_formation.py +++ b/test/test_formation.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.models.formation import ( diff --git a/test/test_patients.py b/test/test_patients.py index 7f40c70..716365c 100644 --- a/test/test_patients.py +++ b/test/test_patients.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from datetime import date import pytest diff --git a/test/test_program.py b/test/test_program.py index 26c2cc6..c6895ab 100644 --- a/test/test_program.py +++ b/test/test_program.py @@ -1,8 +1,10 @@ +from __future__ import annotations + from http import HTTPStatus +from typing import TYPE_CHECKING import pytest -from welkin import Client from welkin.exceptions import WelkinHTTPError from welkin.models import ( Patient, @@ -11,7 +13,10 @@ ProgramPhase, ProgramPhases, ) -from welkin.models.formation import Program + +if TYPE_CHECKING: + from welkin import Client + from welkin.models.formation import Program @pytest.mark.vcr diff --git a/test/test_sms.py b/test/test_sms.py index c596232..62679f8 100644 --- a/test/test_sms.py +++ b/test/test_sms.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.exceptions import WelkinHTTPError diff --git a/test/test_users.py b/test/test_users.py index 54044a7..27d4c4f 100644 --- a/test/test_users.py +++ b/test/test_users.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from welkin.exceptions import WelkinHTTPError diff --git a/test/test_util.py b/test/test_util.py index a5fc060..adebb3c 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import copy import sys diff --git a/welkin/authentication.py b/welkin/authentication.py index bcf1cec..e62d573 100644 --- a/welkin/authentication.py +++ b/welkin/authentication.py @@ -1,13 +1,18 @@ +from __future__ import annotations + import logging import shelve import tempfile from pathlib import Path -from typing import Callable +from typing import TYPE_CHECKING, Callable from portalocker import Lock -from requests import PreparedRequest from requests.auth import AuthBase +if TYPE_CHECKING: + from requests import PreparedRequest + + logger = logging.getLogger(__name__) diff --git a/welkin/client.py b/welkin/client.py index 7012472..1be0936 100644 --- a/welkin/client.py +++ b/welkin/client.py @@ -3,6 +3,8 @@ This module provides a Client object to interface with the Welkin Health API. """ +from __future__ import annotations + import logging from http import HTTPStatus from json import JSONDecodeError diff --git a/welkin/exceptions.py b/welkin/exceptions.py index 058def8..af34fff 100644 --- a/welkin/exceptions.py +++ b/welkin/exceptions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import contextlib import json diff --git a/welkin/models/assessment.py b/welkin/models/assessment.py index 58770d6..dda1f08 100644 --- a/welkin/models/assessment.py +++ b/welkin/models/assessment.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from welkin.models.base import Collection, Resource from welkin.pagination import PageableIterator from welkin.util import model_id diff --git a/welkin/models/base.py b/welkin/models/base.py index 8ac48c1..489842f 100644 --- a/welkin/models/base.py +++ b/welkin/models/base.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys from types import MappingProxyType diff --git a/welkin/models/calendar.py b/welkin/models/calendar.py index 9333a9f..dfb49b1 100644 --- a/welkin/models/calendar.py +++ b/welkin/models/calendar.py @@ -1,9 +1,14 @@ -from datetime import datetime +from __future__ import annotations + from enum import Enum +from typing import TYPE_CHECKING from welkin.models.base import Collection, Resource from welkin.pagination import PageableIterator +if TYPE_CHECKING: + from datetime import datetime + class EventType(Enum): GROUP_THERAPY = "GROUP_THERAPY" diff --git a/welkin/models/care_plan.py b/welkin/models/care_plan.py index e962e3f..0b81112 100644 --- a/welkin/models/care_plan.py +++ b/welkin/models/care_plan.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from welkin.models.base import Resource from welkin.util import model_id diff --git a/welkin/models/cdt.py b/welkin/models/cdt.py index ba476fa..65e682c 100644 --- a/welkin/models/cdt.py +++ b/welkin/models/cdt.py @@ -1,9 +1,14 @@ -from datetime import datetime +from __future__ import annotations + +from typing import TYPE_CHECKING from welkin.models.base import Collection, Resource from welkin.pagination import PageNumberIterator from welkin.util import model_id +if TYPE_CHECKING: + from datetime import datetime + class CDT(Resource): @model_id("Patient") diff --git a/welkin/models/chat.py b/welkin/models/chat.py index ba4fafd..45c7434 100644 --- a/welkin/models/chat.py +++ b/welkin/models/chat.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from welkin.models.base import Collection, Resource from welkin.pagination import MetaIterator from welkin.util import model_id diff --git a/welkin/models/document.py b/welkin/models/document.py index 6611244..27cbdb3 100644 --- a/welkin/models/document.py +++ b/welkin/models/document.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from io import BytesIO from welkin.models.base import Collection, Resource diff --git a/welkin/models/email.py b/welkin/models/email.py index 5c6943d..4157ab8 100644 --- a/welkin/models/email.py +++ b/welkin/models/email.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from welkin.models.base import Collection, Resource from welkin.pagination import PageableIterator from welkin.util import model_id diff --git a/welkin/models/encounter.py b/welkin/models/encounter.py index 7d6edb0..d9f29cd 100644 --- a/welkin/models/encounter.py +++ b/welkin/models/encounter.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from enum import Enum from types import MappingProxyType diff --git a/welkin/models/formation.py b/welkin/models/formation.py index 47dcc71..f6e1660 100644 --- a/welkin/models/formation.py +++ b/welkin/models/formation.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from welkin.models.base import Collection, Resource from welkin.pagination import FormationIterator from welkin.util import Target, _build_resources diff --git a/welkin/models/patient.py b/welkin/models/patient.py index 996edcb..3eea760 100644 --- a/welkin/models/patient.py +++ b/welkin/models/patient.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from welkin.models.assessment import AssessmentRecord, AssessmentRecords from welkin.models.base import Collection, Resource from welkin.models.care_plan import CarePlan diff --git a/welkin/models/program.py b/welkin/models/program.py index 6fe2c6f..637b7cb 100644 --- a/welkin/models/program.py +++ b/welkin/models/program.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from types import MappingProxyType from welkin.models.base import Collection, Resource diff --git a/welkin/models/sms.py b/welkin/models/sms.py index 0ee81d5..580ec1c 100644 --- a/welkin/models/sms.py +++ b/welkin/models/sms.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from welkin.models.base import Collection, Resource from welkin.pagination import PageableIterator from welkin.util import model_id diff --git a/welkin/models/user.py b/welkin/models/user.py index f4d1d24..4f6b745 100644 --- a/welkin/models/user.py +++ b/welkin/models/user.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from enum import Enum from welkin.models.base import Collection, Resource diff --git a/welkin/pagination.py b/welkin/pagination.py index 6475c08..137d955 100644 --- a/welkin/pagination.py +++ b/welkin/pagination.py @@ -1,3 +1,5 @@ +from __future__ import annotations + DEFAULT_PAGE_SIZE = 20 diff --git a/welkin/util.py b/welkin/util.py index 58193d1..323e11a 100644 --- a/welkin/util.py +++ b/welkin/util.py @@ -1,6 +1,8 @@ +from __future__ import annotations + from datetime import date, datetime, timezone from functools import lru_cache, wraps -from typing import Any, Callable, Tuple, Union +from typing import Any, Callable from uuid import UUID import inflection @@ -114,7 +116,7 @@ def clean_datetime(dt: datetime) -> str: ) -def find_model_id(instance: Union[Collection, Resource], model_name: str) -> str: +def find_model_id(instance: Collection | Resource, model_name: str) -> str: """Recursively traverse the `_parent` chain searching for a model id. Args: @@ -141,11 +143,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 0543aff92cc1ea578bbae9e6772bc3efedc5618d Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Thu, 11 Apr 2024 16:39:07 -0700 Subject: [PATCH 13/18] Add coverage exclusions --- pyproject.toml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bb5c52c..5ecb895 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,17 @@ myst-parser = "^2.0.0" requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" +[tool.coverage.report] +# Regexes for lines to exclude from consideration +exclude_also = ["if TYPE_CHECKING:"] + +[tool.coverage.run] +omit = ["test/*"] + +[tool.pytest.ini_options] +addopts = ["-n=auto"] +env_files = [".env", ".env.example"] + [tool.ruff] cache-dir = "~/.cache/ruff" extend-exclude = ["*migrations/*"] @@ -100,10 +111,3 @@ combine-as-imports = true [tool.ruff.lint.pydocstyle] convention = "google" - -[tool.coverage.run] -omit = ["test/*"] - -[tool.pytest.ini_options] -addopts = ["-n=auto"] -env_files = [".env", ".env.example"] From 3622d4cd7c8c7b558d87c93c9135ca3f884bcd0f Mon Sep 17 00:00:00 2001 From: samamorgan <356814+samamorgan@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:10:17 +0000 Subject: [PATCH 14/18] update pre-commit hooks --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2ecabae..da79337 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: ## Python - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.6 + rev: v0.3.7 hooks: - id: ruff args: [--fix] From 91eff7ba3aa6e67379a07ddd232b82d1e3ca2a42 Mon Sep 17 00:00:00 2001 From: samamorgan <356814+samamorgan@users.noreply.github.com> Date: Sat, 20 Apr 2024 00:10:41 +0000 Subject: [PATCH 15/18] update pre-commit hooks --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index da79337..91eafcd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: ## Python - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.7 + rev: v0.4.1 hooks: - id: ruff args: [--fix] From c6aacfb4c40ee3cb08f50390d07d4a8bc17beb6d Mon Sep 17 00:00:00 2001 From: samamorgan <356814+samamorgan@users.noreply.github.com> Date: Fri, 10 May 2024 00:11:45 +0000 Subject: [PATCH 16/18] update pre-commit hooks --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 91eafcd..e04e6f4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: ## Python - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.1 + rev: v0.4.4 hooks: - id: ruff args: [--fix] From 748e3d51d37cf2416fd6e688efe8cf95efe47f35 Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 10 May 2024 10:45:01 -0700 Subject: [PATCH 17/18] Make CI callable --- .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 e7ab056..0f56faf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,6 +1,6 @@ name: CI -on: [pull_request, workflow_dispatch] +on: [pull_request, workflow_dispatch, workflow_call] concurrency: group: ${{ github.workflow }}-${{ github.ref }} From 2048cf8ad337d8427fda5b5c2e7156b3cbc86d6a Mon Sep 17 00:00:00 2001 From: Sam Morgan Date: Fri, 10 May 2024 12:49:13 -0700 Subject: [PATCH 18/18] Bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5ecb895..968c38b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "welkin" -version = "0.1.2" +version = "0.1.3" description = "Python Welkin Health API Wrapper." authors = ["Sam Morgan "] license = "GPL-3.0-or-later"