add pylint and lint the project
This commit is contained in:
parent
6f1d90cc0c
commit
ac571289d4
197
pdm.lock
197
pdm.lock
|
@ -8,6 +8,17 @@ dependencies = [
|
||||||
"sniffio>=1.1",
|
"sniffio>=1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "astroid"
|
||||||
|
version = "2.12.13"
|
||||||
|
requires_python = ">=3.7.2"
|
||||||
|
summary = "An abstract syntax tree for Python with inference support."
|
||||||
|
dependencies = [
|
||||||
|
"lazy-object-proxy>=1.4.0",
|
||||||
|
"wrapt<2,>=1.11; python_version < \"3.11\"",
|
||||||
|
"wrapt<2,>=1.14; python_version >= \"3.11\"",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.3"
|
version = "8.1.3"
|
||||||
|
@ -23,6 +34,12 @@ version = "0.4.6"
|
||||||
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
summary = "Cross-platform colored terminal text."
|
summary = "Cross-platform colored terminal text."
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dill"
|
||||||
|
version = "0.3.6"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "serialize all of python"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi"
|
name = "fastapi"
|
||||||
version = "0.88.0"
|
version = "0.88.0"
|
||||||
|
@ -51,6 +68,30 @@ version = "3.4"
|
||||||
requires_python = ">=3.5"
|
requires_python = ">=3.5"
|
||||||
summary = "Internationalized Domain Names in Applications (IDNA)"
|
summary = "Internationalized Domain Names in Applications (IDNA)"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "isort"
|
||||||
|
version = "5.11.4"
|
||||||
|
requires_python = ">=3.7.0"
|
||||||
|
summary = "A Python utility / library to sort Python imports."
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy-object-proxy"
|
||||||
|
version = "1.8.0"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "A fast and thorough lazy object proxy."
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mccabe"
|
||||||
|
version = "0.7.0"
|
||||||
|
requires_python = ">=3.6"
|
||||||
|
summary = "McCabe checker, plugin for flake8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "2.6.0"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "1.10.2"
|
version = "1.10.2"
|
||||||
|
@ -60,6 +101,23 @@ dependencies = [
|
||||||
"typing-extensions>=4.1.0",
|
"typing-extensions>=4.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pylint"
|
||||||
|
version = "2.15.9"
|
||||||
|
requires_python = ">=3.7.2"
|
||||||
|
summary = "python code static checker"
|
||||||
|
dependencies = [
|
||||||
|
"astroid<=2.14.0-dev0,>=2.12.13",
|
||||||
|
"colorama>=0.4.5; sys_platform == \"win32\"",
|
||||||
|
"dill>=0.2; python_version < \"3.11\"",
|
||||||
|
"dill>=0.3.6; python_version >= \"3.11\"",
|
||||||
|
"isort<6,>=4.2.5",
|
||||||
|
"mccabe<0.8,>=0.6",
|
||||||
|
"platformdirs>=2.2.0",
|
||||||
|
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||||
|
"tomlkit>=0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-dotenv"
|
name = "python-dotenv"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
|
@ -87,6 +145,18 @@ dependencies = [
|
||||||
"anyio<5,>=3.4.0",
|
"anyio<5,>=3.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tomli"
|
||||||
|
version = "2.0.1"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "A lil' TOML parser"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tomlkit"
|
||||||
|
version = "0.11.6"
|
||||||
|
requires_python = ">=3.6"
|
||||||
|
summary = "Style preserving TOML library"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.4.0"
|
version = "4.4.0"
|
||||||
|
@ -141,15 +211,25 @@ version = "10.4"
|
||||||
requires_python = ">=3.7"
|
requires_python = ">=3.7"
|
||||||
summary = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
|
summary = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wrapt"
|
||||||
|
version = "1.14.1"
|
||||||
|
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||||
|
summary = "Module for decorators, wrappers and monkey patching."
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock_version = "4.1"
|
lock_version = "4.1"
|
||||||
content_hash = "sha256:b322cb00d8d7fb1b82a352ce22f81402bfde370223353b1df64cd11ec9639a92"
|
content_hash = "sha256:9a10f6941e9a68f98e1a2ce7e300b98d1c7cc79f71526d28a1030d59c7e560bb"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
"anyio 3.6.2" = [
|
"anyio 3.6.2" = [
|
||||||
{url = "https://files.pythonhosted.org/packages/77/2b/b4c0b7a3f3d61adb1a1e0b78f90a94e2b6162a043880704b7437ef297cad/anyio-3.6.2-py3-none-any.whl", hash = "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"},
|
{url = "https://files.pythonhosted.org/packages/77/2b/b4c0b7a3f3d61adb1a1e0b78f90a94e2b6162a043880704b7437ef297cad/anyio-3.6.2-py3-none-any.whl", hash = "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"},
|
||||||
{url = "https://files.pythonhosted.org/packages/8b/94/6928d4345f2bc1beecbff03325cad43d320717f51ab74ab5a571324f4f5a/anyio-3.6.2.tar.gz", hash = "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421"},
|
{url = "https://files.pythonhosted.org/packages/8b/94/6928d4345f2bc1beecbff03325cad43d320717f51ab74ab5a571324f4f5a/anyio-3.6.2.tar.gz", hash = "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421"},
|
||||||
]
|
]
|
||||||
|
"astroid 2.12.13" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/61/d0/e7cfca72ec7d6c5e0da725c003db99bb056e9b6c2f4ee6fae1145adf28a6/astroid-2.12.13.tar.gz", hash = "sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/b1/61/42e075b7d29ed4d452d91cbaaca142710d50d04e68eb7161ce5807a00a30/astroid-2.12.13-py3-none-any.whl", hash = "sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907"},
|
||||||
|
]
|
||||||
"click 8.1.3" = [
|
"click 8.1.3" = [
|
||||||
{url = "https://files.pythonhosted.org/packages/59/87/84326af34517fca8c58418d148f2403df25303e02736832403587318e9e8/click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
{url = "https://files.pythonhosted.org/packages/59/87/84326af34517fca8c58418d148f2403df25303e02736832403587318e9e8/click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||||
{url = "https://files.pythonhosted.org/packages/c2/f1/df59e28c642d583f7dacffb1e0965d0e00b218e0186d7858ac5233dce840/click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
{url = "https://files.pythonhosted.org/packages/c2/f1/df59e28c642d583f7dacffb1e0965d0e00b218e0186d7858ac5233dce840/click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||||
|
@ -158,6 +238,10 @@ content_hash = "sha256:b322cb00d8d7fb1b82a352ce22f81402bfde370223353b1df64cd11ec
|
||||||
{url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
{url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
{url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
{url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
]
|
]
|
||||||
|
"dill 0.3.6" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/7c/e7/364a09134e1062d4d5ff69b853a56cf61c223e0afcc6906b6832bcd51ea8/dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/be/e3/a84bf2e561beed15813080d693b4b27573262433fced9c1d1fea59e60553/dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"},
|
||||||
|
]
|
||||||
"fastapi 0.88.0" = [
|
"fastapi 0.88.0" = [
|
||||||
{url = "https://files.pythonhosted.org/packages/d8/09/ce090f6d53ce8b6335954488087210fa1e054c4a65f74d5f76aed254c159/fastapi-0.88.0-py3-none-any.whl", hash = "sha256:263b718bb384422fe3d042ffc9a0c8dece5e034ab6586ff034f6b4b1667c3eee"},
|
{url = "https://files.pythonhosted.org/packages/d8/09/ce090f6d53ce8b6335954488087210fa1e054c4a65f74d5f76aed254c159/fastapi-0.88.0-py3-none-any.whl", hash = "sha256:263b718bb384422fe3d042ffc9a0c8dece5e034ab6586ff034f6b4b1667c3eee"},
|
||||||
{url = "https://files.pythonhosted.org/packages/f0/d1/55559f6b09ac336cbb4640ab4c2da0fd79a955eed31f475f0a5ba2ad102e/fastapi-0.88.0.tar.gz", hash = "sha256:915bf304180a0e7c5605ec81097b7d4cd8826ff87a02bb198e336fb9f3b5ff02"},
|
{url = "https://files.pythonhosted.org/packages/f0/d1/55559f6b09ac336cbb4640ab4c2da0fd79a955eed31f475f0a5ba2ad102e/fastapi-0.88.0.tar.gz", hash = "sha256:915bf304180a0e7c5605ec81097b7d4cd8826ff87a02bb198e336fb9f3b5ff02"},
|
||||||
|
@ -213,6 +297,39 @@ content_hash = "sha256:b322cb00d8d7fb1b82a352ce22f81402bfde370223353b1df64cd11ec
|
||||||
{url = "https://files.pythonhosted.org/packages/8b/e1/43beb3d38dba6cb420cefa297822eac205a277ab43e5ba5d5c46faf96438/idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
{url = "https://files.pythonhosted.org/packages/8b/e1/43beb3d38dba6cb420cefa297822eac205a277ab43e5ba5d5c46faf96438/idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
||||||
{url = "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
|
{url = "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
|
||||||
]
|
]
|
||||||
|
"isort 5.11.4" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/76/46/004e2dd6c312e8bb7cb40a6c01b770956e0ef137857e82d47bd9c829356b/isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/91/3b/a63bafb8141b67c397841b36ad46e7469716af2b2d00cb0be2dfb9667130/isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"},
|
||||||
|
]
|
||||||
|
"lazy-object-proxy 1.8.0" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/0a/68/5839136508651d813c1adce568e2f7417bb66083dc8d604a69d465ee53c0/lazy_object_proxy-1.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/30/c3/81c176ce53d9107947d355b273f9661a4f4cad6d56d1daf1c9d6969902e8/lazy_object_proxy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/34/c5/1ef17ab530068f7a5549ab376726f83fe2221db592dbdfd4f8fd4662e45d/lazy_object_proxy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/46/35/55c3650f29858869596871b7fedf4a6b211b61dcc4dd8e8d5702eb85370e/lazy_object_proxy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/60/c1/bf324cf9a0577b0e3781b1a38696405235ac784c4a6d889f97a36dcedc70/lazy_object_proxy-1.8.0-cp37-cp37m-win32.whl", hash = "sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/64/ed/ad47931e7780a5c39f7439de9124438794137840ffdb5f3ffd2995228071/lazy_object_proxy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/65/08/836c9e4e6edf3a267e5b1d0c03923a70ee1a233baf6eb00bfab88d795c51/lazy_object_proxy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/74/37/591f89e8a09ae4574391bdf8a5eecd34a3dbe545917333e625c9de9a66b0/lazy-object-proxy-1.8.0.tar.gz", hash = "sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/7c/0f/60db0efe9a1d61fc830cfd2806d54c5fb64761e8009b9d163bf0ede5b12d/lazy_object_proxy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/80/aa/71f82fd17211767419d6b1fc3dc00ba4641c11f9c9358f7acc5222e693b9/lazy_object_proxy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/95/97/44ee4e0247754bcb878886baf2e06856ff268b0d67e86f1d750f251e3c87/lazy_object_proxy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/9d/23/7e78292a5b72121a8bdfff128fcfb8d3630af74336855d3e527f73eaa4c0/lazy_object_proxy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/9d/d1/6dd90b049748d02d9120a496c3649220ac4f6803dd74c9ae48f2bb001239/lazy_object_proxy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/b9/a2/e6b92d1ce6da768a1570d436616f4c565420fcf1c4b2b5246cf77624fe36/lazy_object_proxy-1.8.0-pp37-pypy37_pp73-any.whl", hash = "sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/d7/8a/7bf9154dd7e6e9bda733a105e3baca3636abe72091cd1dcbf636979b667f/lazy_object_proxy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e0/d3/0cdabfa685eb152a9f4d179fa95f121b3810171f246e8e51f45d100b345c/lazy_object_proxy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e3/90/4c8d2ce638791874f48894761e305afa2bf6f85f315f1d51946eb1e2b18f/lazy_object_proxy-1.8.0-pp38-pypy38_pp73-any.whl", hash = "sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/f5/dc/11168f6697ed68ec29a4f0887308c0d7836d96148a81eb0abb7b8e77b8e8/lazy_object_proxy-1.8.0-pp39-pypy39_pp73-any.whl", hash = "sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/f6/71/e0dbe4172135aca4b4f657cf15fefd34247b5392ae42cf2ca2583dfa332f/lazy_object_proxy-1.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858"},
|
||||||
|
]
|
||||||
|
"mccabe 0.7.0" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
|
||||||
|
]
|
||||||
|
"platformdirs 2.6.0" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/87/69/cd019a9473bcdfb38983e2d550ccb239264fc4c2fc32c42ac1b1cc2506b6/platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/ec/4c/9af851448e55c57b30a13a72580306e628c3b431d97fdae9e0b8d4fa3685/platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"},
|
||||||
|
]
|
||||||
"pydantic 1.10.2" = [
|
"pydantic 1.10.2" = [
|
||||||
{url = "https://files.pythonhosted.org/packages/13/e3/5b83cba317390c9125e049a5328b8e19475098362d398a65936aaab3f00f/pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"},
|
{url = "https://files.pythonhosted.org/packages/13/e3/5b83cba317390c9125e049a5328b8e19475098362d398a65936aaab3f00f/pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"},
|
||||||
{url = "https://files.pythonhosted.org/packages/22/53/196c9a5752e30d682e493d7c00ea0a02377446578e577ae5e085010dc0bd/pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"},
|
{url = "https://files.pythonhosted.org/packages/22/53/196c9a5752e30d682e493d7c00ea0a02377446578e577ae5e085010dc0bd/pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"},
|
||||||
|
@ -251,6 +368,10 @@ content_hash = "sha256:b322cb00d8d7fb1b82a352ce22f81402bfde370223353b1df64cd11ec
|
||||||
{url = "https://files.pythonhosted.org/packages/fe/5b/6f77e6ebc93e5e3c7fd480e1b171a6547407eba901a56a65d2745df24144/pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"},
|
{url = "https://files.pythonhosted.org/packages/fe/5b/6f77e6ebc93e5e3c7fd480e1b171a6547407eba901a56a65d2745df24144/pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"},
|
||||||
{url = "https://files.pythonhosted.org/packages/fe/fd/8f7f8271d526378c927babd1229501e576760cef9a509909a3415eec3c0d/pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"},
|
{url = "https://files.pythonhosted.org/packages/fe/fd/8f7f8271d526378c927babd1229501e576760cef9a509909a3415eec3c0d/pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"},
|
||||||
]
|
]
|
||||||
|
"pylint 2.15.9" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/68/3a/1e61444eb8276ad962a7f300b6920b7ad391f4fbe551d34443f093a18899/pylint-2.15.9.tar.gz", hash = "sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/7d/df/0e50d5640ed4c6a492cdc6df0c281afee3f85d98209e7ec7b31243838b40/pylint-2.15.9-py3-none-any.whl", hash = "sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb"},
|
||||||
|
]
|
||||||
"python-dotenv 0.21.0" = [
|
"python-dotenv 0.21.0" = [
|
||||||
{url = "https://files.pythonhosted.org/packages/2d/10/ff4f2f5b2a420fd09e1331d63cc87cf4367c5745c0a4ce99cea92b1cbacb/python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"},
|
{url = "https://files.pythonhosted.org/packages/2d/10/ff4f2f5b2a420fd09e1331d63cc87cf4367c5745c0a4ce99cea92b1cbacb/python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"},
|
||||||
{url = "https://files.pythonhosted.org/packages/87/8d/ab7352188f605e3f663f34692b2ed7457da5985857e9e4c2335cd12fb3c9/python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"},
|
{url = "https://files.pythonhosted.org/packages/87/8d/ab7352188f605e3f663f34692b2ed7457da5985857e9e4c2335cd12fb3c9/python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"},
|
||||||
|
@ -305,6 +426,14 @@ content_hash = "sha256:b322cb00d8d7fb1b82a352ce22f81402bfde370223353b1df64cd11ec
|
||||||
{url = "https://files.pythonhosted.org/packages/1d/4e/30eda84159d5b3ad7fe663c40c49b16dd17436abe838f10a56c34bee44e8/starlette-0.22.0-py3-none-any.whl", hash = "sha256:b5eda991ad5f0ee5d8ce4c4540202a573bb6691ecd0c712262d0bc85cf8f2c50"},
|
{url = "https://files.pythonhosted.org/packages/1d/4e/30eda84159d5b3ad7fe663c40c49b16dd17436abe838f10a56c34bee44e8/starlette-0.22.0-py3-none-any.whl", hash = "sha256:b5eda991ad5f0ee5d8ce4c4540202a573bb6691ecd0c712262d0bc85cf8f2c50"},
|
||||||
{url = "https://files.pythonhosted.org/packages/f7/ff/64bd3362f80e81402f21e0f1ba55f8801cd899ad3f2a1bcc4a94d284c786/starlette-0.22.0.tar.gz", hash = "sha256:b092cbc365bea34dd6840b42861bdabb2f507f8671e642e8272d2442e08ea4ff"},
|
{url = "https://files.pythonhosted.org/packages/f7/ff/64bd3362f80e81402f21e0f1ba55f8801cd899ad3f2a1bcc4a94d284c786/starlette-0.22.0.tar.gz", hash = "sha256:b092cbc365bea34dd6840b42861bdabb2f507f8671e642e8272d2442e08ea4ff"},
|
||||||
]
|
]
|
||||||
|
"tomli 2.0.1" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||||
|
]
|
||||||
|
"tomlkit 0.11.6" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/2b/df/971fa5db3250bb022105d17f340339370f73d502e65e687a94ca1a4c4b1f/tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/ff/04/58b4c11430ed4b7b8f1723a5e4f20929d59361e9b17f0872d69681fd8ffd/tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"},
|
||||||
|
]
|
||||||
"typing-extensions 4.4.0" = [
|
"typing-extensions 4.4.0" = [
|
||||||
{url = "https://files.pythonhosted.org/packages/0b/8e/f1a0a5a76cfef77e1eb6004cb49e5f8d72634da638420b9ea492ce8305e8/typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
|
{url = "https://files.pythonhosted.org/packages/0b/8e/f1a0a5a76cfef77e1eb6004cb49e5f8d72634da638420b9ea492ce8305e8/typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
|
||||||
{url = "https://files.pythonhosted.org/packages/e3/a7/8f4e456ef0adac43f452efc2d0e4b242ab831297f1bac60ac815d37eb9cf/typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
|
{url = "https://files.pythonhosted.org/packages/e3/a7/8f4e456ef0adac43f452efc2d0e4b242ab831297f1bac60ac815d37eb9cf/typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
|
||||||
|
@ -436,3 +565,69 @@ content_hash = "sha256:b322cb00d8d7fb1b82a352ce22f81402bfde370223353b1df64cd11ec
|
||||||
{url = "https://files.pythonhosted.org/packages/f9/15/ab0e9155700d3037ffe4a146a719f3e68ee025c9d45d6a39b027e928db52/websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"},
|
{url = "https://files.pythonhosted.org/packages/f9/15/ab0e9155700d3037ffe4a146a719f3e68ee025c9d45d6a39b027e928db52/websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"},
|
||||||
{url = "https://files.pythonhosted.org/packages/fd/42/07f31d9f9e142b38cde8d3ea0c8ea1bacf9bc366f2f573eca57086e9f2a6/websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"},
|
{url = "https://files.pythonhosted.org/packages/fd/42/07f31d9f9e142b38cde8d3ea0c8ea1bacf9bc366f2f573eca57086e9f2a6/websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"},
|
||||||
]
|
]
|
||||||
|
"wrapt 1.14.1" = [
|
||||||
|
{url = "https://files.pythonhosted.org/packages/00/61/04422b7469534650b622d5baa1dd335c4b91d35c8d33548b272f33060519/wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/03/c6/d864b8da8afa57a638b12596c3a58dfe3471acda900961c02a904010e0e9/wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/07/06/2b4aaaa4403f766c938f9780c700d7399726bce3dfd94f5a57c4e5b9dc68/wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/0a/61/330f24065b8f2fc02f94321092a24e0c30aefcbac89ab5c860e180366c9f/wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/0d/dc/3f588e42e09fb5170349924366587319e1e49d50a1a58dbe78d6046ca812/wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/11/eb/e06e77394d6cf09977d92bff310cb0392930c08a338f99af6066a5a98f92/wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/12/cd/da6611401655ac2b8496b316ad9e21a3fd4f8e62e2c3b3e3c50207770517/wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/1b/77/9f3660dca3d6b7079c3b1b64ad0795db3603cb9345fba3ca580ccdc3fef5/wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/21/55/42ff84a671415db8fc87a1c301c6c7f52b978669324059bdb8dbd7d3f0ce/wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/23/8b/e4de40ac2fa6d53e694310c576e160bec3db8a282fbdcd5596544f6bc69e/wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/2a/86/c9ef2fa4899ec069c8efe43fc92ca2ba0c5a7921cfaf83090030cf7b1487/wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/30/31/c3f80ed75bec31fc3b4e3193f660b96da8fef70811f0ed67a4dc873412bc/wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/33/cd/7335d8b82ff0a442581ab37a8d275ad76b4c1f33ace63c1a4d7c23791eee/wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/36/ee/944dc7e5462662270e8a379755bcc543fc8f09029866288060dc163ed5b4/wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/38/38/5b338163b3b4f1ab718306984678c3d180b85a25d72654ea4c61aa6b0968/wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/39/4d/34599a47c8a41b3ea4986e14f728c293a8a96cd6c23663fe33657c607d34/wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/39/a1/9b4d07b6836a62c6999e8bb5cefced5b34a26fb03941a19c27af98eecec0/wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/40/f4/7be7124a06c14b92be53912f93c8dc84247f1cb93b4003bed460a430d1de/wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/49/a8/528295a24655f901148177355edb6a22b84abb2abfadacc1675643c1434a/wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/4b/07/782463e367a7c6b418af231ded753e4b2dd3293a157d9b0bb010806fc0c0/wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/4b/5b/3cf79a5fce7a91c0c10275835199fafdf30c1b8c7008fa671af3c4e8046c/wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/4f/83/2669bf2cb4cc2b346c40799478d29749ccd17078cb4f69b4a9f95921ff6d/wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/50/d5/bf619c4d204fe8888460f65222b465c7ecfa43590fdb31864fe0e266da29/wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/5b/02/5ac7ea3b6722c84a2882d349ac581a9711b4047fe7a58475903832caa295/wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/5c/46/b91791db2ac7cc4c186408b7aed37b994463970f2397d0548f38b2b47aca/wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/5e/d3/bd44864e0274b7e162e2a68c71fffbd8b3a7b620efd23320fd0f70333cff/wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/67/b4/b5504dddcb2ff9486f8569953938591e0013cca09c912b28747d1d9cb04f/wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/6a/12/76bbe26dc39d05f1a7be8d570d91c87bb79297e08e885148ed670ed17b7b/wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/72/24/490a0bbc67135f737d2eb4b270bfc91e54cc3f0b5e97b4ceec91a44bb898/wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/79/9c/f5d1209c8e4e091e250eb3ed099056e7e1ad0ec1e9ca46f6d88389e2d6d4/wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/82/27/1eac9e63b9ef0e0929e00e17872d45de9d7d965c7f49b933e2daa22c7896/wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/88/ef/05655df7648752ae0a57fe2b9820e340ff025cecec9341aad7936c589a2f/wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/92/b5/788b92550804405424e0d0b1a95250137cbf0e050bb5c461e8ad0fefdc86/wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/93/12/b20ae4dbefa94ef5d667ba71324763d870b86064a944c8ec9533042a41fc/wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/93/8c/1bbba9357142e6f9bcf55c79e2aa6fd5f4066c331e731376705777a0077f/wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/93/b1/007fd8d5c8c366ee1c1b93a99962de5fd34f81dae679ee2bf6a6e0ffc8f0/wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/94/4b/ff8d58aee32ed91744f1ff4970e590f0c8fdda3fa6d702dc82281e0309bd/wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/94/56/fd707fb8e1ea86e72503d823549fb002a0f16cb4909619748996daeb3a82/wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/94/59/60b2fe919ffb190cf8cae0307bafdaf1695eac8655921f59768ce3bf1084/wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/98/0f/3db7e01896b726e68fa2ba918ed0d79f3cc2da2ce928799282264d14c6f6/wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/a2/a7/dd6e91c68d76328d09dd61a7aadac19d49ec509a07e853173036dc05fb79/wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/a7/0d/a52a0268c98a687785c5452324e10f9462d289e850066e281aa327505aa7/wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/b1/ca/ec539e402932bb64814a039f471d327d0deb4612199506094ca60821b94c/wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/bb/70/73c54e24ea69a8b06ae9649e61d5e64f2b4bdfc6f202fc7794abeac1ed20/wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/c0/1e/e5a5ac09e92fd112d50e1793e5b9982dc9e510311ed89dacd2e801f82967/wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/c7/1b/0cdff572d22600fcf47353e8eb1077d83cab3f161ebfb4843565c6e07e66/wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/c8/03/b36a48dcb6f6332d754017b2dd617757687984a6c433e44ca59bb7fefd4c/wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/ca/16/e79e786d930b69a20481174c7bc97e989fb67d2a181a5043e1d3c70c9b21/wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/cd/ec/383d9552df0641e9915454b03139571e0c6e055f5d414d8f3d04f3892f38/wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/d9/3b/f6b760bf04d13e5ddb70d019779466c22952637cf0f606a26d5f784f27ff/wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/d9/ab/3ba5816dd466ffd7242913708771d258569825ab76fd29d7fd85b9361311/wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/da/f4/7af9e01b6c1126b2daef72d5ba2cbf59a7229fd57c5b23166f694d758a8f/wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e0/20/9716fb522d17a726364c4d032c8806ffe312268773dd46a394436b2787cc/wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e0/6a/3c660fa34c8106aa9719f2a6636c1c3ea7afd5931ae665eb197fdf4def84/wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e0/80/af9da7379ee6df583875d0aeb80f9d5f0bd5f081dd1ee5ce06587d8bfec7/wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e6/57/d5673f5201ccbc287e70a574868319267735de3041e496e1e26b48d8f653/wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e7/a1/a9596c5858c4a58be8cdd5e8b0e5f53f9c1c17f0616b47edde8de1a356fe/wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/e8/f6/7e30a8c53d27ef8c1ff872dc4fb75247c99eb73d834c91a49a55d046c127/wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/f0/db/2a9ea49cd8bdde87a85262e517563d42b9e5b760473597b9da511fcbd54d/wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/f1/96/d22461ba08d61a859c45cda5064b878f2baa61f142d3acfa8adabd82bf07/wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/f7/92/121147bb2f9ed1aa35a8780c636d5da9c167545f97737f0860b4c6c92086/wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/f8/c4/3f8130d646bfc89382966adfb3d6428f26d0f752543a7e2fd92c1e493be6/wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/f9/3c/110e52b9da396a4ef3a0521552a1af9c7875a762361f48678c1ac272fd7e/wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"},
|
||||||
|
{url = "https://files.pythonhosted.org/packages/fd/70/8a133c88a394394dd57159083b86a564247399440b63f2da0ad727593570/wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"},
|
||||||
|
]
|
||||||
|
|
|
@ -3,11 +3,11 @@ name = "webfinger"
|
||||||
version = "1"
|
version = "1"
|
||||||
description = "Simple WebFinger server that returns static resources. Written with Python and FastAPI."
|
description = "Simple WebFinger server that returns static resources. Written with Python and FastAPI."
|
||||||
authors = [
|
authors = [
|
||||||
{name = "a", email = "a@trwnh.com"},
|
{name = "a", email = "a@trwnh.com"},
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastapi>=0.88.0",
|
"fastapi>=0.88.0",
|
||||||
"uvicorn[standard]>=0.20.0",
|
"uvicorn[standard]>=0.20.0",
|
||||||
]
|
]
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
license = {text = "AGPL"}
|
license = {text = "AGPL"}
|
||||||
|
@ -19,3 +19,18 @@ build-backend = "pdm.pep517.api"
|
||||||
[tool.pdm.scripts]
|
[tool.pdm.scripts]
|
||||||
dev = "uvicorn webfinger:app --port 7033 --reload"
|
dev = "uvicorn webfinger:app --port 7033 --reload"
|
||||||
start = "python -m webfinger"
|
start = "python -m webfinger"
|
||||||
|
lint = "pylint webfinger"
|
||||||
|
|
||||||
|
[tool.pdm.dev-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pylint>=2.15.9",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.pylint.format]
|
||||||
|
indent-string = "\t"
|
||||||
|
|
||||||
|
[tool.pylint.messages_control]
|
||||||
|
extension-pkg-whitelist = "pydantic"
|
||||||
|
disable = [
|
||||||
|
"missing-final-newline"
|
||||||
|
]
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
Initialize the WebFinger server with FastAPI
|
||||||
|
"""
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
import webfinger.lookup
|
import webfinger.lookup
|
||||||
|
|
||||||
|
@ -9,9 +13,9 @@ app = FastAPI(
|
||||||
app.include_router(webfinger.lookup.router)
|
app.include_router(webfinger.lookup.router)
|
||||||
|
|
||||||
|
|
||||||
def cleanup_openapi(app: FastAPI) -> None:
|
def cleanup_openapi(fastapi_app: FastAPI) -> None:
|
||||||
"""Cleanup inconsistencies in the OpenAPI documentation"""
|
"""Cleanup inconsistencies in the OpenAPI documentation"""
|
||||||
openapi_schema = app.openapi()
|
openapi_schema = fastapi_app.openapi()
|
||||||
|
|
||||||
# Remove 422 Validation Error from Webfinger lookup (RFC7033 uses 400 Bad Request)
|
# Remove 422 Validation Error from Webfinger lookup (RFC7033 uses 400 Bad Request)
|
||||||
webfinger_responses: dict = openapi_schema["paths"]["/.well-known/webfinger"]["get"]["responses"]
|
webfinger_responses: dict = openapi_schema["paths"]["/.well-known/webfinger"]["get"]["responses"]
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
from webfinger import app
|
"""
|
||||||
|
Run the FastAPI app with Uvicorn if the package is run as a module
|
||||||
|
"""
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
from webfinger import app
|
||||||
|
|
||||||
uvicorn.run(app=app, port=7033)
|
uvicorn.run(app=app, port=7033)
|
|
@ -1,11 +1,21 @@
|
||||||
|
"""
|
||||||
|
Functions that perform read-write operations
|
||||||
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from os import environ as env
|
from os import environ as env
|
||||||
from urllib.parse import quote_plus as url_encode
|
from urllib.parse import quote_plus as url_encode
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
def get_jrd(resource: str) -> dict[str, str | list[str] | dict[str,str]]:
|
from webfinger.models import JRD, Link
|
||||||
|
|
||||||
|
|
||||||
|
DictJRD = dict[str, str | list[str] | dict[str,str] | list[dict[str,str]]]
|
||||||
|
|
||||||
|
|
||||||
|
def get_jrd_as_dict(resource: str) -> DictJRD:
|
||||||
"""
|
"""
|
||||||
Obtain a JSON Resource Descriptor (JRD)
|
Obtain a JSON Resource Descriptor (JRD) as a dictionary
|
||||||
|
|
||||||
A JRD is a JSON object containing the following:
|
A JRD is a JSON object containing the following:
|
||||||
- subject (string value; SHOULD be present)
|
- subject (string value; SHOULD be present)
|
||||||
|
@ -15,9 +25,9 @@ def get_jrd(resource: str) -> dict[str, str | list[str] | dict[str,str]]:
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
resource (str): The URI of the resouce
|
resource (str): The URI of the resouce
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
jrd (dict): Parsed JRD
|
jrd (dict): Parsed JRD dictionary
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
FileNotFoundError: No JRD file exists in the resource directory
|
FileNotFoundError: No JRD file exists in the resource directory
|
||||||
|
@ -25,30 +35,69 @@ def get_jrd(resource: str) -> dict[str, str | list[str] | dict[str,str]]:
|
||||||
json.JSONDecodeError: A file exists, but does not contain a valid JSON object
|
json.JSONDecodeError: A file exists, but does not contain a valid JSON object
|
||||||
"""
|
"""
|
||||||
# Get a filename for the resource document.
|
# Get a filename for the resource document.
|
||||||
dir = env.get("RESOURCE_DIR") or "resource"
|
directory = env.get("RESOURCE_DIR") or "resource"
|
||||||
filename = resource
|
filename = resource
|
||||||
path = f"{dir}/{filename}.jrd"
|
path = f"{directory}/{filename}.jrd"
|
||||||
|
|
||||||
# If we can't get a file, try percent-encoding
|
# If we can't get a file, try percent-encoding
|
||||||
if not Path(path).is_file():
|
if not Path(path).is_file():
|
||||||
filename = url_encode(resource)
|
filename = url_encode(resource)
|
||||||
path = f"{dir}/{filename}.jrd"
|
path = f"{directory}/{filename}.jrd"
|
||||||
|
|
||||||
# Try plain JSON
|
# Try plain JSON
|
||||||
if not Path(path).is_file():
|
if not Path(path).is_file():
|
||||||
filename = resource
|
filename = resource
|
||||||
path = f"{dir}/{filename}.json"
|
path = f"{directory}/{filename}.json"
|
||||||
|
|
||||||
# Try plain JSON and percent-encoding
|
# Try plain JSON and percent-encoding
|
||||||
if not Path(path).is_file():
|
if not Path(path).is_file():
|
||||||
filename = resource
|
filename = resource
|
||||||
path = f"{dir}/{filename}.json"
|
path = f"{directory}/{filename}.json"
|
||||||
|
|
||||||
# Open the file and load the JSON as a dictionary.
|
# Open the file and load the JSON as a dictionary.
|
||||||
try:
|
# This may fail and raise an exception.
|
||||||
with open(path, "r") as file:
|
with open(path, mode="r", encoding="utf-8") as file:
|
||||||
jrd: dict[str, str | list[str] | dict[str,str]] = json.loads(file.read())
|
jrd: DictJRD = json.loads(file.read())
|
||||||
except:
|
|
||||||
raise
|
|
||||||
|
|
||||||
return jrd
|
return {k: v for k, v in jrd.items() if v} # remove null values
|
||||||
|
|
||||||
|
|
||||||
|
def get_jrd(resource: str) -> JRD:
|
||||||
|
"""
|
||||||
|
Obtain a JSON Resource Descriptor (JRD) as a Pydantic model
|
||||||
|
|
||||||
|
A JRD is a JSON object containing the following:
|
||||||
|
- subject (string value; SHOULD be present)
|
||||||
|
- aliases (array of string values; OPTIONAL)
|
||||||
|
- properties (object containing key-value pairs as strings; OPTIONAL)
|
||||||
|
- links (array of objects containing link relation information; OPTIONAL)
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
resource (str): The URI of the resouce
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
jrd (JRD): Parsed and valid JRD model
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: No JRD file exists in the resource directory
|
||||||
|
OSError: A file may exist, but it is not readable
|
||||||
|
json.JSONDecodeError: A file exists, but does not contain a valid JSON object
|
||||||
|
pydantic.ValidationError: A file exists and was parsed, but some properties failed validation
|
||||||
|
"""
|
||||||
|
|
||||||
|
jrd = get_jrd_as_dict(resource)
|
||||||
|
return JRD(
|
||||||
|
subject = jrd.get('subject') or resource,
|
||||||
|
aliases = jrd.get('aliases'),
|
||||||
|
properties = jrd.get('properties'),
|
||||||
|
links = [
|
||||||
|
Link(
|
||||||
|
rel = link.get('rel'),
|
||||||
|
type = link.get('type'),
|
||||||
|
href = link.get('href'),
|
||||||
|
titles = link.get('titles'),
|
||||||
|
properties = link.get('properties'),
|
||||||
|
)
|
||||||
|
for link in jrd.get('links', [])
|
||||||
|
],
|
||||||
|
)
|
|
@ -1,11 +1,17 @@
|
||||||
from fastapi import APIRouter, Response
|
"""
|
||||||
|
Perform WebFinger lookups according to RFC7033
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from fastapi import APIRouter
|
||||||
from fastapi.responses import PlainTextResponse, JSONResponse
|
from fastapi.responses import PlainTextResponse, JSONResponse
|
||||||
from fastapi.params import Query
|
from fastapi.params import Query
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import ValidationError
|
||||||
import json
|
|
||||||
|
|
||||||
from webfinger.io import get_jrd
|
from webfinger.io import get_jrd
|
||||||
|
from webfinger.models import JRD, JRDResponse
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
|
@ -21,62 +27,23 @@ HEADERS = {'Access-Control-Allow-Origin': '*'}
|
||||||
# headers.update({'Access-Control-Allow-Origin': allowed_origins})
|
# headers.update({'Access-Control-Allow-Origin': allowed_origins})
|
||||||
|
|
||||||
|
|
||||||
## Pydantic models for OpenAPI schema
|
|
||||||
|
|
||||||
class Link(BaseModel):
|
|
||||||
rel: str
|
|
||||||
type: str | None
|
|
||||||
href: str | None
|
|
||||||
titles: str | None
|
|
||||||
properties: str | None
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
schema_extra = {
|
|
||||||
"example": r'''{
|
|
||||||
"rel": "https://webfinger.net/rel/profile-page/",
|
|
||||||
"type": "text/html",
|
|
||||||
"href": "https://trwnh.com/~a"
|
|
||||||
}'''
|
|
||||||
}
|
|
||||||
|
|
||||||
class JRD(BaseModel):
|
|
||||||
subject: str
|
|
||||||
aliases: list[str] | None
|
|
||||||
links: list[Link] | None
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
schema_extra = {
|
|
||||||
"example": r'''{
|
|
||||||
"subject": "acct:a@trwnh.com",
|
|
||||||
"aliases": ["https://ap.trwnh.com/actors/7057bc10-db1c-4ebe-9e00-22cf04be4e5e", "https://trwnh.com/~a", "acct:trwnh@ap.trwnh.com"],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"rel": "self",
|
|
||||||
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
|
|
||||||
"href": "https://trwnh.com/actors/7057bc10-db1c-4ebe-9e00-22cf04be4e5e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"rel": "https://webfinger.net/rel/profile-page/",
|
|
||||||
"type": "text/html",
|
|
||||||
"href": "https://trwnh.com/~a"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}'''
|
|
||||||
}
|
|
||||||
|
|
||||||
class JRDResponse(Response):
|
|
||||||
media_type = "application/jrd+json"
|
|
||||||
|
|
||||||
|
|
||||||
## Example responses for OpenAPI schema
|
## Example responses for OpenAPI schema
|
||||||
|
|
||||||
RESOURCE_NOT_PROVIDED = "Query ?resource={resource} to obtain information about that resource."
|
RESOURCE_NOT_PROVIDED = \
|
||||||
RESOURCE_NOT_FOUND = "Resource not found"
|
"Query ?resource={resource} to obtain information about that resource."
|
||||||
RESOURCE_NOT_PARSED = "Resource contains invalid JSON or was unreadable"
|
RESOURCE_NOT_FOUND = \
|
||||||
|
"Resource not found"
|
||||||
|
RESOURCE_NOT_PARSED = \
|
||||||
|
"Resource contains invalid JSON or was unreadable"
|
||||||
|
RESOURCE_NOT_VALID = \
|
||||||
|
"Some errors occurred while validating the JRD"
|
||||||
|
|
||||||
RESPONSES = {
|
RESPONSES = {
|
||||||
200: {
|
200: {
|
||||||
"description": "OK: The resource you requested was found, and has the returned resource document.",
|
"description": (
|
||||||
|
"OK:"
|
||||||
|
" The resource you requested was found,"
|
||||||
|
" and has the returned resource document."),
|
||||||
"model": JRD,
|
"model": JRD,
|
||||||
"content": {
|
"content": {
|
||||||
"application/jrd+json": {
|
"application/jrd+json": {
|
||||||
|
@ -85,7 +52,9 @@ RESPONSES = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
"description": "Bad Request: No resource was provided.",
|
"description": (
|
||||||
|
"Bad Request:"
|
||||||
|
" No resource was provided."),
|
||||||
"content": {
|
"content": {
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"example": RESOURCE_NOT_PROVIDED
|
"example": RESOURCE_NOT_PROVIDED
|
||||||
|
@ -93,7 +62,9 @@ RESPONSES = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
404: {
|
404: {
|
||||||
"description": "Not Found: Could not find a document for the provided resource.",
|
"description": (
|
||||||
|
"Not Found:"
|
||||||
|
" Could not find a document for the provided resource."),
|
||||||
"content": {
|
"content": {
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"example": RESOURCE_NOT_FOUND
|
"example": RESOURCE_NOT_FOUND
|
||||||
|
@ -101,7 +72,10 @@ RESPONSES = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
500: {
|
500: {
|
||||||
"description": "Server Error: The resource exists, but contains invalid JSON or was unreadable.",
|
"description": (
|
||||||
|
"Server Error:"
|
||||||
|
" The resource exists,"
|
||||||
|
" but contains invalid JSON or was unreadable."),
|
||||||
"content": {
|
"content": {
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"example": RESOURCE_NOT_PARSED
|
"example": RESOURCE_NOT_PARSED
|
||||||
|
@ -116,7 +90,9 @@ RESPONSES = {
|
||||||
@router.get(
|
@router.get(
|
||||||
"",
|
"",
|
||||||
summary = "Lookup a Webfinger resource",
|
summary = "Lookup a Webfinger resource",
|
||||||
description = "Query the Webfinger service for a resource URI and obtain its associated resource document",
|
description = (
|
||||||
|
"Query the Webfinger service for a resource URI"
|
||||||
|
" and obtain its associated resource document"),
|
||||||
tags = ["RFC7033"],
|
tags = ["RFC7033"],
|
||||||
response_model = JRD,
|
response_model = JRD,
|
||||||
response_class = JRDResponse,
|
response_class = JRDResponse,
|
||||||
|
@ -126,12 +102,18 @@ async def lookup(
|
||||||
resource: str = Query(
|
resource: str = Query(
|
||||||
None,
|
None,
|
||||||
title = "Resource URI",
|
title = "Resource URI",
|
||||||
description = "The subject whose document you are looking up. If not provided, you will get a 400 Bad Request."
|
description = (
|
||||||
|
"The subject whose document you are looking up."
|
||||||
|
" If not provided, you will get a 400 Bad Request."
|
||||||
|
),
|
||||||
),
|
),
|
||||||
rel: list[str] = Query(
|
rel: list[str] = Query(
|
||||||
None,
|
None,
|
||||||
title = "Link relation",
|
title = "Link relation",
|
||||||
description = "If provided, filter the links array for this rel-value only. This parameter may be included multiple times."
|
description = (
|
||||||
|
"If provided, filter the links array for this rel-value only."
|
||||||
|
" This parameter may be included multiple times."
|
||||||
|
),
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
|
@ -144,43 +126,43 @@ async def lookup(
|
||||||
status_code=400,
|
status_code=400,
|
||||||
headers = HEADERS,
|
headers = HEADERS,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Otherwise, try to read the resource document.
|
# Otherwise, try to read the resource document.
|
||||||
try:
|
try:
|
||||||
jrd = get_jrd(resource)
|
jrd = get_jrd(resource)
|
||||||
except FileNotFoundError: # JRD file does not exist
|
except FileNotFoundError:
|
||||||
|
# JRD file does not exist
|
||||||
return PlainTextResponse(
|
return PlainTextResponse(
|
||||||
content = RESOURCE_NOT_FOUND,
|
content = RESOURCE_NOT_FOUND,
|
||||||
status_code = 404,
|
status_code = 404,
|
||||||
headers = HEADERS,
|
headers = HEADERS,
|
||||||
)
|
)
|
||||||
except: # JRD file could not be read or parsed
|
except (OSError, json.JSONDecodeError):
|
||||||
|
# JRD file could not be read or parsed
|
||||||
return PlainTextResponse(
|
return PlainTextResponse(
|
||||||
content = RESOURCE_NOT_PARSED,
|
content = RESOURCE_NOT_PARSED,
|
||||||
status_code = 500,
|
status_code = 500,
|
||||||
headers = HEADERS,
|
headers = HEADERS,
|
||||||
)
|
)
|
||||||
|
except ValidationError as exception:
|
||||||
# Obtain values from the resource document.
|
# JRD was parsed but contained type or value errors
|
||||||
subject: str = jrd.get('subject', None) or resource
|
errors = [RESOURCE_NOT_VALID]
|
||||||
aliases: list[str] = [alias for alias in jrd.get('aliases', [])]
|
for error in exception.errors():
|
||||||
properties: dict[str, str] = jrd.get('properties', {})
|
print(error)
|
||||||
links: list[dict[str,str]] = [link for link in jrd.get('links', [])]
|
errors.append(f"{error['msg']} for {error['loc'][0]}")
|
||||||
|
return PlainTextResponse(
|
||||||
|
content = '\n- '.join(errors),
|
||||||
|
status_code=500,
|
||||||
|
headers = HEADERS,
|
||||||
|
)
|
||||||
|
|
||||||
# If optional rel is provided, then filter only for links with that rel-type.
|
# If optional rel is provided, then filter only for links with that rel-type.
|
||||||
if rel:
|
if rel:
|
||||||
links = [link for link in links if link.get('rel', '') in rel]
|
jrd.links = [link for link in jrd.links if link.rel in rel]
|
||||||
|
|
||||||
# Construct JSON response and return it.
|
# Construct JSON response and return it.
|
||||||
content = {
|
|
||||||
"subject": subject,
|
|
||||||
"aliases": aliases,
|
|
||||||
"properties": properties,
|
|
||||||
"links": links,
|
|
||||||
}
|
|
||||||
content = {k: v for k, v in content.items() if v} # remove null values
|
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content = content,
|
content = jrd.dict(exclude_none=True),
|
||||||
media_type = "application/jrd+json",
|
media_type = "application/jrd+json",
|
||||||
headers = HEADERS,
|
headers = HEADERS,
|
||||||
)
|
)
|
66
webfinger/models.py
Normal file
66
webfinger/models.py
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
"""
|
||||||
|
Models used for validation and OpenAPI responses
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pydantic import BaseModel, StrictStr
|
||||||
|
from fastapi import Response
|
||||||
|
|
||||||
|
class Link(BaseModel):
|
||||||
|
"""
|
||||||
|
Describes an entry in the JRD `link` array
|
||||||
|
"""
|
||||||
|
rel: StrictStr
|
||||||
|
type: StrictStr | None
|
||||||
|
href: StrictStr | None
|
||||||
|
titles: StrictStr | None
|
||||||
|
properties: dict[StrictStr, StrictStr] | None
|
||||||
|
|
||||||
|
class Config: # pylint: disable=too-few-public-methods
|
||||||
|
"""
|
||||||
|
Provide an example `link` item
|
||||||
|
"""
|
||||||
|
schema_extra = {
|
||||||
|
"example": r'''{
|
||||||
|
"rel": "https://webfinger.net/rel/profile-page/",
|
||||||
|
"type": "text/html",
|
||||||
|
"href": "https://trwnh.com/~a"
|
||||||
|
}'''
|
||||||
|
}
|
||||||
|
|
||||||
|
class JRD(BaseModel):
|
||||||
|
"""
|
||||||
|
Describes a JSON Resource Descriptor document
|
||||||
|
"""
|
||||||
|
subject: StrictStr
|
||||||
|
aliases: list[StrictStr] | None
|
||||||
|
links: list[Link] | None
|
||||||
|
properties: dict[StrictStr, StrictStr] | None
|
||||||
|
|
||||||
|
class Config: # pylint: disable=too-few-public-methods
|
||||||
|
"""
|
||||||
|
Provide an example JRD document
|
||||||
|
"""
|
||||||
|
schema_extra = {
|
||||||
|
"example": r'''{
|
||||||
|
"subject": "acct:a@trwnh.com",
|
||||||
|
"aliases": ["https://ap.trwnh.com/actors/7057bc10-db1c-4ebe-9e00-22cf04be4e5e", "https://trwnh.com/~a", "acct:trwnh@ap.trwnh.com"],
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"rel": "self",
|
||||||
|
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
|
||||||
|
"href": "https://trwnh.com/actors/7057bc10-db1c-4ebe-9e00-22cf04be4e5e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "https://webfinger.net/rel/profile-page/",
|
||||||
|
"type": "text/html",
|
||||||
|
"href": "https://trwnh.com/~a"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}'''
|
||||||
|
}
|
||||||
|
|
||||||
|
class JRDResponse(Response):
|
||||||
|
"""
|
||||||
|
Specify JRD Content-Type for responding to WebFinger lookup requests
|
||||||
|
"""
|
||||||
|
media_type = "application/jrd+json"
|
Loading…
Reference in a new issue