diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..01ee5229 --- /dev/null +++ b/.flake8 @@ -0,0 +1,7 @@ +[flake8] +max-line-length = 79 +# E203: whitespace before :, flake8 disagrees with PEP-8 +# W503: line break after binary operator, flake8 disagrees with PEP-8 +ignore = E203, W503 +exclude = + docs/conf.py diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 04eabcee..50e49c05 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,7 +22,7 @@ jobs: strategy: matrix: python: - - "3.10" + - "3.11" steps: - uses: actions/checkout@v3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9297cd26..e7011a73 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,23 +1,23 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.4.0 hooks: - id: check-yaml - id: check-toml - repo: https://github.com/pycqa/isort - rev: 5.10.1 + rev: 5.12.0 hooks: - id: isort additional_dependencies: - toml - repo: https://github.com/psf/black - rev: 22.6.0 + rev: 23.3.0 hooks: - id: black - repo: https://github.com/pycqa/flake8 - rev: 5.0.3 + rev: 6.0.0 hooks: - id: flake8 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 131338ee..d0ee8da6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change log ========== +0.7.0 (2023-04-19) +------------------ + +- Adopt ``safir.redis.pydantic`` for Redis-backed storage. +- Adopt ``safir.github`` creating the GitHub App client and modelling of GitHub resources with Pydantic. +- Fix handling of disabled pages so that they aren't executed in a GitHub check, and are dropped if they previously existed in the database. +- Update to Python 3.11 + 0.6.0 (2022-08-18) ------------------ diff --git a/Dockerfile b/Dockerfile index 7ee0ef68..d494b5eb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ # - Runs a non-root user. # - Sets up the entrypoint and port. -FROM python:3.10.7-slim-bullseye as base-image +FROM python:3.11.3-slim-bullseye as base-image # Update system packages COPY scripts/install-base-packages.sh . diff --git a/Makefile b/Makefile index 6f467ce8..df73f759 100644 --- a/Makefile +++ b/Makefile @@ -24,4 +24,4 @@ update: update-deps init .PHONY: run run: - tox -e run + tox run -e=run diff --git a/pyproject.toml b/pyproject.toml index 42698f21..14ce58f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,36 @@ -[build-system] -requires = [ - "setuptools>=42", - "wheel", - "setuptools_scm[toml]>=3.4" +[project] +name = "times-square" +description = "Times Square is a service for parameterized Jupyter Notebooks as dynamic webpages." +license = { file = "LICENSE" } +readme = "README.rst" +keywords = ["rubin", "lsst"] +# https://pypi.org/classifiers/ +classifiers = [ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Intended Audience :: Developers", + "Natural Language :: English", + "Operating System :: POSIX", + "Typing :: Typed", ] -build-backend = 'setuptools.build_meta' +requires-python = ">=3.11" +# Use requirements/main.in for runtime dependencies instead. +dependencies = [] +dynamic = ["version"] + +[project.scripts] +times-square = "timessquare.cli:main" + +[project.urls] +Homepage = "https://times-square.lsst.io" +Source = "https://github.com/lsst-sqre/times-square" + +[build-system] +requires = ["setuptools>=61", "wheel", "setuptools_scm[toml]>=6.2"] +build-backend = "setuptools.build_meta" [tool.setuptools_scm] @@ -32,7 +58,7 @@ exclude_lines = [ [tool.black] line-length = 79 -target-version = ['py38'] +target-version = ['py311'] exclude = ''' /( \.eggs @@ -49,8 +75,8 @@ exclude = ''' # Multi-line strings are implicitly treated by black as regular expressions [tool.isort] -include_trailing_comma = true -multi_line_output = 3 +profile = "black" +line_length = 79 known_first_party = ["timessquare", "tests"] skip = ["docs/conf.py"] @@ -60,3 +86,22 @@ python_files = [ "tests/*.py", "tests/*/*.py" ] + +[tool.mypy] +disallow_untyped_defs = true +disallow_incomplete_defs = true +ignore_missing_imports = true +local_partial_types = true +plugins = ["sqlalchemy.ext.mypy.plugin", "pydantic.mypy"] +no_implicit_reexport = true +show_error_codes = true +strict_equality = true +warn_redundant_casts = true +warn_unreachable = true +warn_unused_ignores = true + +[tool.pydantic-mypy] +init_forbid_extra = true +init_typed = true +warn_required_dynamic_aliases = true +warn_untyped_fields = true diff --git a/requirements/dev.in b/requirements/dev.in index 22c36c5c..69b949c1 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -20,3 +20,4 @@ sqlalchemy[mypy] holdup respx types-PyYAML +types-redis diff --git a/requirements/dev.txt b/requirements/dev.txt index d634d186..485ad832 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,169 +1,692 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: # -# pip-compile --allow-unsafe --output-file=requirements/dev.txt requirements/dev.in +# pip-compile --generate-hashes --output-file=requirements/dev.txt requirements/dev.in # -anyio==3.6.1 +anyio==3.6.2 \ + --hash=sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421 \ + --hash=sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3 # via # -c requirements/main.txt # httpcore # watchfiles -asgi-lifespan==1.0.1 +asgi-lifespan==2.1.0 \ + --hash=sha256:5e2effaf0bfe39829cf2d64e7ecc47c7d86d676a6599f7afba378c31f5e3a308 \ + --hash=sha256:ed840706680e28428c01e14afb3875d7d76d3206f3d5b2f2294e059b5c23804f # via -r requirements/dev.in -attrs==22.1.0 - # via - # -c requirements/main.txt - # pytest -certifi==2022.6.15 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via # -c requirements/main.txt # httpcore # httpx -cfgv==3.3.1 +cffi==1.15.1 \ + --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ + --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ + --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ + --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ + --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ + --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ + --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ + --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ + --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ + --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ + --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ + --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ + --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ + --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ + --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ + --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ + --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ + --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ + --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ + --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ + --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ + --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ + --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ + --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ + --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ + --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ + --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ + --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ + --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ + --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ + --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ + --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ + --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ + --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ + --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ + --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ + --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ + --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ + --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ + --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ + --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ + --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ + --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ + --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ + --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ + --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ + --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ + --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ + --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ + --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ + --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ + --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ + --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ + --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ + --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ + --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ + --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ + --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ + --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ + --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ + --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ + --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ + --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ + --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 + # via + # -c requirements/main.txt + # cryptography +cfgv==3.3.1 \ + --hash=sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426 \ + --hash=sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736 # via pre-commit -click==8.1.3 +click==8.1.3 \ + --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ + --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 # via # -c requirements/main.txt # uvicorn -coverage[toml]==6.4.3 +coverage[toml]==7.2.3 \ + --hash=sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93 \ + --hash=sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013 \ + --hash=sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f \ + --hash=sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21 \ + --hash=sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462 \ + --hash=sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc \ + --hash=sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df \ + --hash=sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1 \ + --hash=sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235 \ + --hash=sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934 \ + --hash=sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9 \ + --hash=sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1 \ + --hash=sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48 \ + --hash=sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4 \ + --hash=sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe \ + --hash=sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a \ + --hash=sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b \ + --hash=sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21 \ + --hash=sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d \ + --hash=sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa \ + --hash=sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367 \ + --hash=sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535 \ + --hash=sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152 \ + --hash=sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e \ + --hash=sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539 \ + --hash=sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1 \ + --hash=sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925 \ + --hash=sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0 \ + --hash=sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2 \ + --hash=sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab \ + --hash=sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841 \ + --hash=sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30 \ + --hash=sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91 \ + --hash=sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c \ + --hash=sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257 \ + --hash=sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9 \ + --hash=sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040 \ + --hash=sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911 \ + --hash=sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623 \ + --hash=sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259 \ + --hash=sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c \ + --hash=sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79 \ + --hash=sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5 \ + --hash=sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4 \ + --hash=sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4 \ + --hash=sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22 \ + --hash=sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd \ + --hash=sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1 \ + --hash=sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910 \ + --hash=sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859 \ + --hash=sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312 # via # -r requirements/dev.in # pytest-cov -distlib==0.3.5 +cryptography==40.0.2 \ + --hash=sha256:05dc219433b14046c476f6f09d7636b92a1c3e5808b9a6536adf4932b3b2c440 \ + --hash=sha256:0dcca15d3a19a66e63662dc8d30f8036b07be851a8680eda92d079868f106288 \ + --hash=sha256:142bae539ef28a1c76794cca7f49729e7c54423f615cfd9b0b1fa90ebe53244b \ + --hash=sha256:3daf9b114213f8ba460b829a02896789751626a2a4e7a43a28ee77c04b5e4958 \ + --hash=sha256:48f388d0d153350f378c7f7b41497a54ff1513c816bcbbcafe5b829e59b9ce5b \ + --hash=sha256:4df2af28d7bedc84fe45bd49bc35d710aede676e2a4cb7fc6d103a2adc8afe4d \ + --hash=sha256:4f01c9863da784558165f5d4d916093737a75203a5c5286fde60e503e4276c7a \ + --hash=sha256:7a38250f433cd41df7fcb763caa3ee9362777fdb4dc642b9a349721d2bf47404 \ + --hash=sha256:8f79b5ff5ad9d3218afb1e7e20ea74da5f76943ee5edb7f76e56ec5161ec782b \ + --hash=sha256:956ba8701b4ffe91ba59665ed170a2ebbdc6fc0e40de5f6059195d9f2b33ca0e \ + --hash=sha256:a04386fb7bc85fab9cd51b6308633a3c271e3d0d3eae917eebab2fac6219b6d2 \ + --hash=sha256:a95f4802d49faa6a674242e25bfeea6fc2acd915b5e5e29ac90a32b1139cae1c \ + --hash=sha256:adc0d980fd2760c9e5de537c28935cc32b9353baaf28e0814df417619c6c8c3b \ + --hash=sha256:aecbb1592b0188e030cb01f82d12556cf72e218280f621deed7d806afd2113f9 \ + --hash=sha256:b12794f01d4cacfbd3177b9042198f3af1c856eedd0a98f10f141385c809a14b \ + --hash=sha256:c0764e72b36a3dc065c155e5b22f93df465da9c39af65516fe04ed3c68c92636 \ + --hash=sha256:c33c0d32b8594fa647d2e01dbccc303478e16fdd7cf98652d5b3ed11aa5e5c99 \ + --hash=sha256:cbaba590180cba88cb99a5f76f90808a624f18b169b90a4abb40c1fd8c19420e \ + --hash=sha256:d5a1bd0e9e2031465761dfa920c16b0065ad77321d8a8c1f5ee331021fda65e9 + # via + # -c requirements/main.txt + # types-pyopenssl + # types-redis +distlib==0.3.6 \ + --hash=sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46 \ + --hash=sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e # via virtualenv -filelock==3.8.0 +filelock==3.12.0 \ + --hash=sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9 \ + --hash=sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718 # via virtualenv -greenlet==1.1.2 +greenlet==2.0.2 \ + --hash=sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a \ + --hash=sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a \ + --hash=sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43 \ + --hash=sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33 \ + --hash=sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8 \ + --hash=sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088 \ + --hash=sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca \ + --hash=sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343 \ + --hash=sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645 \ + --hash=sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db \ + --hash=sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df \ + --hash=sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3 \ + --hash=sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86 \ + --hash=sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2 \ + --hash=sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a \ + --hash=sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf \ + --hash=sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7 \ + --hash=sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394 \ + --hash=sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40 \ + --hash=sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3 \ + --hash=sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6 \ + --hash=sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74 \ + --hash=sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0 \ + --hash=sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3 \ + --hash=sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91 \ + --hash=sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5 \ + --hash=sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9 \ + --hash=sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8 \ + --hash=sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b \ + --hash=sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6 \ + --hash=sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb \ + --hash=sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73 \ + --hash=sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b \ + --hash=sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df \ + --hash=sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9 \ + --hash=sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f \ + --hash=sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0 \ + --hash=sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857 \ + --hash=sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a \ + --hash=sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249 \ + --hash=sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30 \ + --hash=sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292 \ + --hash=sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b \ + --hash=sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d \ + --hash=sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b \ + --hash=sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c \ + --hash=sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca \ + --hash=sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7 \ + --hash=sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75 \ + --hash=sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae \ + --hash=sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b \ + --hash=sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470 \ + --hash=sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564 \ + --hash=sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9 \ + --hash=sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099 \ + --hash=sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0 \ + --hash=sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5 \ + --hash=sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19 \ + --hash=sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1 \ + --hash=sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526 # via # -c requirements/main.txt # sqlalchemy -h11==0.12.0 +h11==0.14.0 \ + --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ + --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 # via # -c requirements/main.txt # httpcore # uvicorn -holdup==3.0.0 +holdup==4.0.0 \ + --hash=sha256:6e9cb2895b6342a76ec328c78e4591f98b988b7925b19291bf9588a0de6a1964 \ + --hash=sha256:eb5040e5d21a4c977d7389b8bc688b8511f8dc029bd10125dc4d67e7a33c0725 # via -r requirements/dev.in -httpcore==0.15.0 +httpcore==0.17.0 \ + --hash=sha256:0fdfea45e94f0c9fd96eab9286077f9ff788dd186635ae61b312693e4d943599 \ + --hash=sha256:cc045a3241afbf60ce056202301b4d8b6af08845e3294055eb26b09913ef903c # via # -c requirements/main.txt # httpx -httptools==0.4.0 +httptools==0.5.0 \ + --hash=sha256:0297822cea9f90a38df29f48e40b42ac3d48a28637368f3ec6d15eebefd182f9 \ + --hash=sha256:1af91b3650ce518d226466f30bbba5b6376dbd3ddb1b2be8b0658c6799dd450b \ + --hash=sha256:1f90cd6fd97c9a1b7fe9215e60c3bd97336742a0857f00a4cb31547bc22560c2 \ + --hash=sha256:24bb4bb8ac3882f90aa95403a1cb48465de877e2d5298ad6ddcfdebec060787d \ + --hash=sha256:295874861c173f9101960bba332429bb77ed4dcd8cdf5cee9922eb00e4f6bc09 \ + --hash=sha256:3625a55886257755cb15194efbf209584754e31d336e09e2ffe0685a76cb4b60 \ + --hash=sha256:3a47a34f6015dd52c9eb629c0f5a8a5193e47bf2a12d9a3194d231eaf1bc451a \ + --hash=sha256:3cb8acf8f951363b617a8420768a9f249099b92e703c052f9a51b66342eea89b \ + --hash=sha256:4b098e4bb1174096a93f48f6193e7d9aa7071506a5877da09a783509ca5fff42 \ + --hash=sha256:4d9ebac23d2de960726ce45f49d70eb5466725c0087a078866043dad115f850f \ + --hash=sha256:50d4613025f15f4b11f1c54bbed4761c0020f7f921b95143ad6d58c151198142 \ + --hash=sha256:5230a99e724a1bdbbf236a1b58d6e8504b912b0552721c7c6b8570925ee0ccde \ + --hash=sha256:54465401dbbec9a6a42cf737627fb0f014d50dc7365a6b6cd57753f151a86ff0 \ + --hash=sha256:550059885dc9c19a072ca6d6735739d879be3b5959ec218ba3e013fd2255a11b \ + --hash=sha256:557be7fbf2bfa4a2ec65192c254e151684545ebab45eca5d50477d562c40f986 \ + --hash=sha256:5b65be160adcd9de7a7e6413a4966665756e263f0d5ddeffde277ffeee0576a5 \ + --hash=sha256:64eba6f168803a7469866a9c9b5263a7463fa8b7a25b35e547492aa7322036b6 \ + --hash=sha256:72ad589ba5e4a87e1d404cc1cb1b5780bfcb16e2aec957b88ce15fe879cc08ca \ + --hash=sha256:7d0c1044bce274ec6711f0770fd2d5544fe392591d204c68328e60a46f88843b \ + --hash=sha256:7e5eefc58d20e4c2da82c78d91b2906f1a947ef42bd668db05f4ab4201a99f49 \ + --hash=sha256:850fec36c48df5a790aa735417dca8ce7d4b48d59b3ebd6f83e88a8125cde324 \ + --hash=sha256:85b392aba273566c3d5596a0a490978c085b79700814fb22bfd537d381dd230c \ + --hash=sha256:8c2a56b6aad7cc8f5551d8e04ff5a319d203f9d870398b94702300de50190f63 \ + --hash=sha256:8f470c79061599a126d74385623ff4744c4e0f4a0997a353a44923c0b561ee51 \ + --hash=sha256:8ffce9d81c825ac1deaa13bc9694c0562e2840a48ba21cfc9f3b4c922c16f372 \ + --hash=sha256:9423a2de923820c7e82e18980b937893f4aa8251c43684fa1772e341f6e06887 \ + --hash=sha256:9b571b281a19762adb3f48a7731f6842f920fa71108aff9be49888320ac3e24d \ + --hash=sha256:a04fe458a4597aa559b79c7f48fe3dceabef0f69f562daf5c5e926b153817281 \ + --hash=sha256:aa47ffcf70ba6f7848349b8a6f9b481ee0f7637931d91a9860a1838bfc586901 \ + --hash=sha256:bede7ee075e54b9a5bde695b4fc8f569f30185891796b2e4e09e2226801d09bd \ + --hash=sha256:c1d2357f791b12d86faced7b5736dea9ef4f5ecdc6c3f253e445ee82da579449 \ + --hash=sha256:c6eeefd4435055a8ebb6c5cc36111b8591c192c56a95b45fe2af22d9881eee25 \ + --hash=sha256:ca1b7becf7d9d3ccdbb2f038f665c0f4857e08e1d8481cbcc1a86a0afcfb62b2 \ + --hash=sha256:e67d4f8734f8054d2c4858570cc4b233bf753f56e85217de4dfb2495904cf02e \ + --hash=sha256:e8a34e4c0ab7b1ca17b8763613783e2458e77938092c18ac919420ab8655c8c1 \ + --hash=sha256:e90491a4d77d0cb82e0e7a9cb35d86284c677402e4ce7ba6b448ccc7325c5421 \ + --hash=sha256:ef1616b3ba965cd68e6f759eeb5d34fbf596a79e84215eeceebf34ba3f61fdc7 \ + --hash=sha256:f222e1e9d3f13b68ff8a835574eda02e67277d51631d69d7cf7f8e07df678c86 \ + --hash=sha256:f5e3088f4ed33947e16fd865b8200f9cfae1144f41b64a8cf19b599508e096bc \ + --hash=sha256:f659d7a48401158c59933904040085c200b4be631cb5f23a7d561fbae593ec1f \ + --hash=sha256:fe9c766a0c35b7e3d6b6939393c8dfdd5da3ac5dec7f971ec9134f284c6c36d6 # via # -c requirements/main.txt # uvicorn -httpx==0.23.0 +httpx==0.24.0 \ + --hash=sha256:447556b50c1921c351ea54b4fe79d91b724ed2b027462ab9a329465d147d5a4e \ + --hash=sha256:507d676fc3e26110d41df7d35ebd8b3b8585052450f4097401c9be59d928c63e # via # -c requirements/main.txt # -r requirements/dev.in # respx -identify==2.5.3 +identify==2.5.22 \ + --hash=sha256:f0faad595a4687053669c112004178149f6c326db71ee999ae4636685753ad2f \ + --hash=sha256:f7a93d6cf98e29bd07663c60728e7a4057615068d7a639d132dc883b2d54d31e # via pre-commit -idna==3.3 +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 # via # -c requirements/main.txt # anyio - # rfc3986 -iniconfig==1.1.1 + # httpx +iniconfig==2.0.0 \ + --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ + --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 # via pytest -mypy==0.971 +mypy==1.2.0 \ + --hash=sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521 \ + --hash=sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140 \ + --hash=sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48 \ + --hash=sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128 \ + --hash=sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336 \ + --hash=sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a \ + --hash=sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41 \ + --hash=sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f \ + --hash=sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e \ + --hash=sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8 \ + --hash=sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238 \ + --hash=sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119 \ + --hash=sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb \ + --hash=sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d \ + --hash=sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed \ + --hash=sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9 \ + --hash=sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e \ + --hash=sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a \ + --hash=sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5 \ + --hash=sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950 \ + --hash=sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937 \ + --hash=sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394 \ + --hash=sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6 \ + --hash=sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602 \ + --hash=sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1 \ + --hash=sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba # via # -r requirements/dev.in # sqlalchemy -mypy-extensions==0.4.3 +mypy-extensions==1.0.0 \ + --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ + --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 # via mypy -nodeenv==1.7.0 +nodeenv==1.7.0 \ + --hash=sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e \ + --hash=sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b # via pre-commit -packaging==21.3 +packaging==23.1 \ + --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ + --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f # via # -c requirements/main.txt # pytest -platformdirs==2.5.2 - # via virtualenv -pluggy==1.0.0 +platformdirs==3.2.0 \ + --hash=sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08 \ + --hash=sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e + # via + # -c requirements/main.txt + # virtualenv +pluggy==1.0.0 \ + --hash=sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159 \ + --hash=sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3 # via pytest -pre-commit==2.20.0 +pre-commit==3.2.2 \ + --hash=sha256:0b4210aea813fe81144e87c5a291f09ea66f199f367fa1df41b55e1d26e1e2b4 \ + --hash=sha256:5b808fcbda4afbccf6d6633a56663fed35b6c2bc08096fd3d47ce197ac351d9d # via -r requirements/dev.in -py==1.11.0 - # via pytest -pyparsing==3.0.9 +pycparser==2.21 \ + --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ + --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 # via # -c requirements/main.txt - # packaging -pytest==7.1.2 + # cffi +pytest==7.3.1 \ + --hash=sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362 \ + --hash=sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3 # via # -r requirements/dev.in # pytest-asyncio # pytest-cov -pytest-asyncio==0.19.0 +pytest-asyncio==0.21.0 \ + --hash=sha256:2b38a496aef56f56b0e87557ec313e11e1ab9276fc3863f6a7be0f1d0e415e1b \ + --hash=sha256:f2b3366b7cd501a4056858bd39349d5af19742aed2d81660b7998b6341c7eb9c # via -r requirements/dev.in -pytest-cov==3.0.0 +pytest-cov==4.0.0 \ + --hash=sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b \ + --hash=sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470 # via -r requirements/dev.in -python-dotenv==0.20.0 +python-dotenv==1.0.0 \ + --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \ + --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a # via # -c requirements/main.txt # uvicorn -pyyaml==6.0 +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via # -c requirements/main.txt # pre-commit # uvicorn -respx==0.19.2 +respx==0.20.1 \ + --hash=sha256:372f06991c03d1f7f480a420a2199d01f1815b6ed5a802f4e4628043a93bd03e \ + --hash=sha256:cc47a86d7010806ab65abdcf3b634c56337a737bb5c4d74c19a0dfca83b3bc73 # via -r requirements/dev.in -rfc3986[idna2008]==1.5.0 - # via - # -c requirements/main.txt - # httpx -sniffio==1.2.0 +sniffio==1.3.0 \ + --hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \ + --hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 # via # -c requirements/main.txt # anyio # asgi-lifespan # httpcore # httpx -sqlalchemy[asyncio,mypy]==1.4.40 +sqlalchemy[asyncio,mypy]==2.0.9 \ + --hash=sha256:07950fc82f844a2de67ddb4e535f29b65652b4d95e8b847823ce66a6d540a41d \ + --hash=sha256:0a865b5ec4ba24f57c33b633b728e43fde77b968911a6046443f581b25d29dd9 \ + --hash=sha256:0b49f1f71d7a44329a43d3edd38cc5ee4c058dfef4487498393d16172007954b \ + --hash=sha256:13f984a190d249769a050634b248aef8991acc035e849d02b634ea006c028fa8 \ + --hash=sha256:1b69666e25cc03c602d9d3d460e1281810109e6546739187044fc256c67941ef \ + --hash=sha256:1d06e119cf79a3d80ab069f064a07152eb9ba541d084bdaee728d8a6f03fd03d \ + --hash=sha256:246712af9fc761d6c13f4f065470982e175d902e77aa4218c9cb9fc9ff565a0c \ + --hash=sha256:34eb96c1de91d8f31e988302243357bef3f7785e1b728c7d4b98bd0c117dafeb \ + --hash=sha256:4c3020afb144572c7bfcba9d7cce57ad42bff6e6115dffcfe2d4ae6d444a214f \ + --hash=sha256:4f759eccb66e6d495fb622eb7f4ac146ae674d829942ec18b7f5a35ddf029597 \ + --hash=sha256:68ed381bc340b4a3d373dbfec1a8b971f6350139590c4ca3cb722fdb50035777 \ + --hash=sha256:6b72dccc5864ea95c93e0a9c4e397708917fb450f96737b4a8395d009f90b868 \ + --hash=sha256:6e84ab63d25d8564d7a8c05dc080659931a459ee27f6ed1cf4c91f292d184038 \ + --hash=sha256:734805708632e3965c2c40081f9a59263c29ffa27cba9b02d4d92dfd57ba869f \ + --hash=sha256:78612edf4ba50d407d0eb3a64e9ec76e6efc2b5d9a5c63415d53e540266a230a \ + --hash=sha256:7e472e9627882f2d75b87ff91c5a2bc45b31a226efc7cc0a054a94fffef85862 \ + --hash=sha256:865392a50a721445156809c1a6d6ab6437be70c1c2599f591a8849ed95d3c693 \ + --hash=sha256:8d118e233f416d713aac715e2c1101e17f91e696ff315fc9efbc75b70d11e740 \ + --hash=sha256:8d3ece5960b3e821e43a4927cc851b6e84a431976d3ffe02aadb96519044807e \ + --hash=sha256:93c78d42c14aa9a9e0866eacd5b48df40a50d0e2790ee377af7910d224afddcf \ + --hash=sha256:95719215e3ec7337b9f57c3c2eda0e6a7619be194a5166c07c1e599f6afc20fa \ + --hash=sha256:9838bd247ee42eb74193d865e48dd62eb50e45e3fdceb0fdef3351133ee53dcf \ + --hash=sha256:aa5c270ece17c0c0e0a38f2530c16b20ea05d8b794e46c79171a86b93b758891 \ + --hash=sha256:ac6a0311fb21a99855953f84c43fcff4bdca27a2ffcc4f4d806b26b54b5cddc9 \ + --hash=sha256:ad5363a1c65fde7b7466769d4261126d07d872fc2e816487ae6cec93da604b6b \ + --hash=sha256:b3e5864eba71a3718236a120547e52c8da2ccb57cc96cecd0480106a0c799c92 \ + --hash=sha256:bbda1da8d541904ba262825a833c9f619e93cb3fd1156be0a5e43cd54d588dcd \ + --hash=sha256:c6e27189ff9aebfb2c02fd252c629ea58657e7a5ff1a321b7fc9c2bf6dc0b5f3 \ + --hash=sha256:c8239ce63a90007bce479adf5460d48c1adae4b933d8e39a4eafecfc084e503c \ + --hash=sha256:d209594e68bec103ad5243ecac1b40bf5770c9ebf482df7abf175748a34f4853 \ + --hash=sha256:d5327f54a9c39e7871fc532639616f3777304364a0bb9b89d6033ad34ef6c5f8 \ + --hash=sha256:db4bd1c4792da753f914ff0b688086b9a8fd78bb9bc5ae8b6d2e65f176b81eb9 \ + --hash=sha256:e4780be0f19e5894c17f75fc8de2fe1ae233ab37827125239ceb593c6f6bd1e2 \ + --hash=sha256:e4a019f723b6c1e6b3781be00fb9e0844bc6156f9951c836ff60787cc3938d76 \ + --hash=sha256:e62c4e762d6fd2901692a093f208a6a6575b930e9458ad58c2a7f080dd6132da \ + --hash=sha256:e730603cae5747bc6d6dece98b45a57d647ed553c8d5ecef602697b1c1501cf2 \ + --hash=sha256:ebc4eeb1737a5a9bdb0c24f4c982319fa6edd23cdee27180978c29cbb026f2bd \ + --hash=sha256:ee2946042cc7851842d7a086a92b9b7b494cbe8c3e7e4627e27bc912d3a7655e \ + --hash=sha256:f005245e1cb9b8ca53df73ee85e029ac43155e062405015e49ec6187a2e3fb44 \ + --hash=sha256:f49c5d3c070a72ecb96df703966c9678dda0d4cb2e2736f88d15f5e1203b4159 \ + --hash=sha256:f61ab84956dc628c8dfe9d105b6aec38afb96adae3e5e7da6085b583ff6ea789 # via # -c requirements/main.txt # -r requirements/dev.in -sqlalchemy2-stubs==0.0.2a25 - # via sqlalchemy -toml==0.10.2 - # via pre-commit -tomli==2.0.1 - # via - # -c requirements/main.txt - # coverage - # mypy - # pytest -types-pyyaml==6.0.11 +types-pyopenssl==23.1.0.2 \ + --hash=sha256:20b80971b86240e8432a1832bd8124cea49c3088c7bfc77dfd23be27ffe4a517 \ + --hash=sha256:b050641aeff6dfebf231ad719bdac12d53b8ee818d4afb67b886333484629957 + # via types-redis +types-pyyaml==6.0.12.9 \ + --hash=sha256:5aed5aa66bd2d2e158f75dda22b059570ede988559f030cf294871d3b647e3e8 \ + --hash=sha256:c51b1bd6d99ddf0aa2884a7a328810ebf70a4262c292195d3f4f9a0005f9eeb6 + # via -r requirements/dev.in +types-redis==4.5.4.1 \ + --hash=sha256:2db530f54facec3149147bfe61d5ac24f5fe4e871823d95a601cd2c1d775d8a0 \ + --hash=sha256:bf04192f415b2b42ecefd70bb4b91eb0352e48f2716a213e038e35c096a639c2 # via -r requirements/dev.in -typing-extensions==4.3.0 +typing-extensions==4.5.0 \ + --hash=sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb \ + --hash=sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4 # via # -c requirements/main.txt # mypy - # sqlalchemy2-stubs -uvicorn[standard]==0.18.2 + # sqlalchemy +uvicorn[standard]==0.21.1 \ + --hash=sha256:0fac9cb342ba099e0d582966005f3fdba5b0290579fed4a6266dc702ca7bb032 \ + --hash=sha256:e47cac98a6da10cd41e6fd036d472c6f58ede6c5dbee3dbee3ef7a100ed97742 # via # -c requirements/main.txt # -r requirements/dev.in -uvloop==0.16.0 +uvloop==0.17.0 \ + --hash=sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d \ + --hash=sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1 \ + --hash=sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595 \ + --hash=sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b \ + --hash=sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05 \ + --hash=sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8 \ + --hash=sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20 \ + --hash=sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded \ + --hash=sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c \ + --hash=sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8 \ + --hash=sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474 \ + --hash=sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f \ + --hash=sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62 \ + --hash=sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376 \ + --hash=sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c \ + --hash=sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e \ + --hash=sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b \ + --hash=sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4 \ + --hash=sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578 \ + --hash=sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811 \ + --hash=sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d \ + --hash=sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738 \ + --hash=sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa \ + --hash=sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9 \ + --hash=sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539 \ + --hash=sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c \ + --hash=sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718 \ + --hash=sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667 \ + --hash=sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c \ + --hash=sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024 # via # -c requirements/main.txt # uvicorn -virtualenv==20.16.3 +virtualenv==20.21.0 \ + --hash=sha256:31712f8f2a17bd06234fa97fdf19609e789dd4e3e4bf108c3da71d710651adbc \ + --hash=sha256:f50e3e60f990a0757c9b68333c9fdaa72d7188caa417f96af9e52407831a3b68 # via pre-commit -watchfiles==0.16.1 +watchfiles==0.19.0 \ + --hash=sha256:0089c6dc24d436b373c3c57657bf4f9a453b13767150d17284fc6162b2791911 \ + --hash=sha256:09ea3397aecbc81c19ed7f025e051a7387feefdb789cf768ff994c1228182fda \ + --hash=sha256:176a9a7641ec2c97b24455135d58012a5be5c6217fc4d5fef0b2b9f75dbf5154 \ + --hash=sha256:18b28f6ad871b82df9542ff958d0c86bb0d8310bb09eb8e87d97318a3b5273af \ + --hash=sha256:20b44221764955b1e703f012c74015306fb7e79a00c15370785f309b1ed9aa8d \ + --hash=sha256:3d7d267d27aceeeaa3de0dd161a0d64f0a282264d592e335fff7958cc0cbae7c \ + --hash=sha256:5471582658ea56fca122c0f0d0116a36807c63fefd6fdc92c71ca9a4491b6b48 \ + --hash=sha256:5569fc7f967429d4bc87e355cdfdcee6aabe4b620801e2cf5805ea245c06097c \ + --hash=sha256:68dce92b29575dda0f8d30c11742a8e2b9b8ec768ae414b54f7453f27bdf9545 \ + --hash=sha256:79c533ff593db861ae23436541f481ec896ee3da4e5db8962429b441bbaae16e \ + --hash=sha256:7f3920b1285a7d3ce898e303d84791b7bf40d57b7695ad549dc04e6a44c9f120 \ + --hash=sha256:91633e64712df3051ca454ca7d1b976baf842d7a3640b87622b323c55f3345e7 \ + --hash=sha256:945be0baa3e2440151eb3718fd8846751e8b51d8de7b884c90b17d271d34cae8 \ + --hash=sha256:9afd0d69429172c796164fd7fe8e821ade9be983f51c659a38da3faaaaac44dc \ + --hash=sha256:9c75eff897786ee262c9f17a48886f4e98e6cfd335e011c591c305e5d083c056 \ + --hash=sha256:b538014a87f94d92f98f34d3e6d2635478e6be6423a9ea53e4dd96210065e193 \ + --hash=sha256:b6577b8c6c8701ba8642ea9335a129836347894b666dd1ec2226830e263909d3 \ + --hash=sha256:c0376deac92377817e4fb8f347bf559b7d44ff556d9bc6f6208dd3f79f104aaf \ + --hash=sha256:cae3dde0b4b2078f31527acff6f486e23abed307ba4d3932466ba7cdd5ecec79 \ + --hash=sha256:cb5d45c4143c1dd60f98a16187fd123eda7248f84ef22244818c18d531a249d1 \ + --hash=sha256:d9b073073e048081e502b6c6b0b88714c026a1a4c890569238d04aca5f9ca74b \ + --hash=sha256:fac19dc9cbc34052394dbe81e149411a62e71999c0a19e1e09ce537867f95ae0 # via # -c requirements/main.txt # uvicorn -websockets==10.3 +websockets==11.0.2 \ + --hash=sha256:0fb4480556825e4e6bf2eebdbeb130d9474c62705100c90e59f2f56459ddab42 \ + --hash=sha256:13bd5bebcd16a4b5e403061b8b9dcc5c77e7a71e3c57e072d8dff23e33f70fba \ + --hash=sha256:143782041e95b63083b02107f31cda999f392903ae331de1307441f3a4557d51 \ + --hash=sha256:1b52def56d2a26e0e9c464f90cadb7e628e04f67b0ff3a76a4d9a18dfc35e3dd \ + --hash=sha256:1df2413266bf48430ef2a752c49b93086c6bf192d708e4a9920544c74cd2baa6 \ + --hash=sha256:2174a75d579d811279855df5824676d851a69f52852edb0e7551e0eeac6f59a4 \ + --hash=sha256:220d5b93764dd70d7617f1663da64256df7e7ea31fc66bc52c0e3750ee134ae3 \ + --hash=sha256:232b6ba974f5d09b1b747ac232f3a3d8f86de401d7b565e837cc86988edf37ac \ + --hash=sha256:25aae96c1060e85836552a113495db6d857400288161299d77b7b20f2ac569f2 \ + --hash=sha256:25e265686ea385f22a00cc2b719b880797cd1bb53b46dbde969e554fb458bfde \ + --hash=sha256:2abeeae63154b7f63d9f764685b2d299e9141171b8b896688bd8baec6b3e2303 \ + --hash=sha256:2acdc82099999e44fa7bd8c886f03c70a22b1d53ae74252f389be30d64fd6004 \ + --hash=sha256:2eb042734e710d39e9bc58deab23a65bd2750e161436101488f8af92f183c239 \ + --hash=sha256:3178d965ec204773ab67985a09f5696ca6c3869afeed0bb51703ea404a24e975 \ + --hash=sha256:320ddceefd2364d4afe6576195201a3632a6f2e6d207b0c01333e965b22dbc84 \ + --hash=sha256:34a6f8996964ccaa40da42ee36aa1572adcb1e213665e24aa2f1037da6080909 \ + --hash=sha256:3565a8f8c7bdde7c29ebe46146bd191290413ee6f8e94cf350609720c075b0a1 \ + --hash=sha256:392d409178db1e46d1055e51cc850136d302434e12d412a555e5291ab810f622 \ + --hash=sha256:3a09cce3dacb6ad638fdfa3154d9e54a98efe7c8f68f000e55ca9c716496ca67 \ + --hash=sha256:3a2100b02d1aaf66dc48ff1b2a72f34f6ebc575a02bc0350cc8e9fbb35940166 \ + --hash=sha256:3b87cd302f08ea9e74fdc080470eddbed1e165113c1823fb3ee6328bc40ca1d3 \ + --hash=sha256:3e79065ff6549dd3c765e7916067e12a9c91df2affea0ac51bcd302aaf7ad207 \ + --hash=sha256:3ffe251a31f37e65b9b9aca5d2d67fd091c234e530f13d9dce4a67959d5a3fba \ + --hash=sha256:46388a050d9e40316e58a3f0838c63caacb72f94129eb621a659a6e49bad27ce \ + --hash=sha256:46dda4bc2030c335abe192b94e98686615f9274f6b56f32f2dd661fb303d9d12 \ + --hash=sha256:4c54086b2d2aec3c3cb887ad97e9c02c6be9f1d48381c7419a4aa932d31661e4 \ + --hash=sha256:5004c087d17251938a52cce21b3dbdabeecbbe432ce3f5bbbf15d8692c36eac9 \ + --hash=sha256:502683c5dedfc94b9f0f6790efb26aa0591526e8403ad443dce922cd6c0ec83b \ + --hash=sha256:518ed6782d9916c5721ebd61bb7651d244178b74399028302c8617d0620af291 \ + --hash=sha256:580cc95c58118f8c39106be71e24d0b7e1ad11a155f40a2ee687f99b3e5e432e \ + --hash=sha256:58477b041099bb504e1a5ddd8aa86302ed1d5c6995bdd3db2b3084ef0135d277 \ + --hash=sha256:5875f623a10b9ba154cb61967f940ab469039f0b5e61c80dd153a65f024d9fb7 \ + --hash=sha256:5c7de298371d913824f71b30f7685bb07ad13969c79679cca5b1f7f94fec012f \ + --hash=sha256:634239bc844131863762865b75211a913c536817c0da27f691400d49d256df1d \ + --hash=sha256:6d872c972c87c393e6a49c1afbdc596432df8c06d0ff7cd05aa18e885e7cfb7c \ + --hash=sha256:752fbf420c71416fb1472fec1b4cb8631c1aa2be7149e0a5ba7e5771d75d2bb9 \ + --hash=sha256:7742cd4524622cc7aa71734b51294644492a961243c4fe67874971c4d3045982 \ + --hash=sha256:808b8a33c961bbd6d33c55908f7c137569b09ea7dd024bce969969aa04ecf07c \ + --hash=sha256:87c69f50281126dcdaccd64d951fb57fbce272578d24efc59bce72cf264725d0 \ + --hash=sha256:8df63dcd955eb6b2e371d95aacf8b7c535e482192cff1b6ce927d8f43fb4f552 \ + --hash=sha256:8f24cd758cbe1607a91b720537685b64e4d39415649cac9177cd1257317cf30c \ + --hash=sha256:8f392587eb2767afa8a34e909f2fec779f90b630622adc95d8b5e26ea8823cb8 \ + --hash=sha256:954eb789c960fa5daaed3cfe336abc066941a5d456ff6be8f0e03dd89886bb4c \ + --hash=sha256:955fcdb304833df2e172ce2492b7b47b4aab5dcc035a10e093d911a1916f2c87 \ + --hash=sha256:95c09427c1c57206fe04277bf871b396476d5a8857fa1b99703283ee497c7a5d \ + --hash=sha256:a4fe2442091ff71dee0769a10449420fd5d3b606c590f78dd2b97d94b7455640 \ + --hash=sha256:aa7b33c1fb2f7b7b9820f93a5d61ffd47f5a91711bc5fa4583bbe0c0601ec0b2 \ + --hash=sha256:adf6385f677ed2e0b021845b36f55c43f171dab3a9ee0ace94da67302f1bc364 \ + --hash=sha256:b1a69701eb98ed83dd099de4a686dc892c413d974fa31602bc00aca7cb988ac9 \ + --hash=sha256:b2a573c8d71b7af937852b61e7ccb37151d719974146b5dc734aad350ef55a02 \ + --hash=sha256:b444366b605d2885f0034dd889faf91b4b47668dd125591e2c64bfde611ac7e1 \ + --hash=sha256:b985ba2b9e972cf99ddffc07df1a314b893095f62c75bc7c5354a9c4647c6503 \ + --hash=sha256:c78ca3037a954a4209b9f900e0eabbc471fb4ebe96914016281df2c974a93e3e \ + --hash=sha256:ca9b2dced5cbbc5094678cc1ec62160f7b0fe4defd601cd28a36fde7ee71bbb5 \ + --hash=sha256:cb46d2c7631b2e6f10f7c8bac7854f7c5e5288f024f1c137d4633c79ead1e3c0 \ + --hash=sha256:ce69f5c742eefd039dce8622e99d811ef2135b69d10f9aa79fbf2fdcc1e56cd7 \ + --hash=sha256:cf45d273202b0c1cec0f03a7972c655b93611f2e996669667414557230a87b88 \ + --hash=sha256:d1881518b488a920434a271a6e8a5c9481a67c4f6352ebbdd249b789c0467ddc \ + --hash=sha256:d3cc3e48b6c9f7df8c3798004b9c4b92abca09eeea5e1b0a39698f05b7a33b9d \ + --hash=sha256:d6b2bfa1d884c254b841b0ff79373b6b80779088df6704f034858e4d705a4802 \ + --hash=sha256:d70a438ef2a22a581d65ad7648e949d4ccd20e3c8ed7a90bbc46df4e60320891 \ + --hash=sha256:daa1e8ea47507555ed7a34f8b49398d33dff5b8548eae3de1dc0ef0607273a33 \ + --hash=sha256:dca9708eea9f9ed300394d4775beb2667288e998eb6f542cdb6c02027430c599 \ + --hash=sha256:dd906b0cdc417ea7a5f13bb3c6ca3b5fd563338dc596996cb0fdd7872d691c0a \ + --hash=sha256:e0eeeea3b01c97fd3b5049a46c908823f68b59bf0e18d79b231d8d6764bc81ee \ + --hash=sha256:e37a76ccd483a6457580077d43bc3dfe1fd784ecb2151fcb9d1c73f424deaeba \ + --hash=sha256:e8b967a4849db6b567dec3f7dd5d97b15ce653e3497b8ce0814e470d5e074750 \ + --hash=sha256:ec00401846569aaf018700249996143f567d50050c5b7b650148989f956547af \ + --hash=sha256:ede13a6998ba2568b21825809d96e69a38dc43184bdeebbde3699c8baa21d015 \ + --hash=sha256:f97e03d4d5a4f0dca739ea274be9092822f7430b77d25aa02da6775e490f6846 # via # -c requirements/main.txt # uvicorn -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.0.0 - # via - # -c requirements/main.txt - # nodeenv +# WARNING: The following packages were not pinned, but pip requires them to be +# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag. +# setuptools diff --git a/requirements/main.in b/requirements/main.in index d8a58d16..c1b789d2 100644 --- a/requirements/main.in +++ b/requirements/main.in @@ -12,14 +12,14 @@ starlette uvicorn[standard] # Other dependencies. -safir[db,arq] +# git+https://github.com/lsst-sqre/safir.git@main#egg=safir[db,arq,redis] +safir[db,arq,redis] pydantic[email] click nbformat nbconvert jsonschema jinja2 -aioredis gidgethub markdown-it-py[linkify,plugins] mdformat diff --git a/requirements/main.txt b/requirements/main.txt index d038bbf4..9d32ae1a 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -1,237 +1,1049 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: # -# pip-compile --allow-unsafe --output-file=requirements/main.txt requirements/main.in +# pip-compile --generate-hashes --output-file=requirements/main.txt requirements/main.in # -aioredis==2.0.1 - # via -r requirements/main.in -anyio==3.6.1 +anyio==3.6.2 \ + --hash=sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421 \ + --hash=sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3 # via # httpcore # starlette # watchfiles -arq==0.23a1 +arq==0.25.0 \ + --hash=sha256:d176ebadfba920c039dc578814d19b7814d67fa15f82fdccccaedb4330d65dae \ + --hash=sha256:db072d0f39c0bc06b436db67ae1f315c81abc1527563b828955670531815290b # via safir -async-timeout==4.0.2 - # via - # aioredis - # redis -asyncpg==0.26.0 +async-timeout==4.0.2 \ + --hash=sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15 \ + --hash=sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c + # via redis +asyncpg==0.27.0 \ + --hash=sha256:16ba8ec2e85d586b4a12bcd03e8d29e3d99e832764d6a1d0b8c27dbbe4a2569d \ + --hash=sha256:18f77e8e71e826ba2d0c3ba6764930776719ae2b225ca07e014590545928b576 \ + --hash=sha256:1b6499de06fe035cf2fa932ec5617ed3f37d4ebbf663b655922e105a484a6af9 \ + --hash=sha256:20b596d8d074f6f695c13ffb8646d0b6bb1ab570ba7b0cfd349b921ff03cfc1e \ + --hash=sha256:2232ebae9796d4600a7819fc383da78ab51b32a092795f4555575fc934c1c89d \ + --hash=sha256:4750f5cf49ed48a6e49c6e5aed390eee367694636c2dcfaf4a273ca832c5c43c \ + --hash=sha256:4bb366ae34af5b5cabc3ac6a5347dfb6013af38c68af8452f27968d49085ecc0 \ + --hash=sha256:5710cb0937f696ce303f5eed6d272e3f057339bb4139378ccecafa9ee923a71c \ + --hash=sha256:609054a1f47292a905582a1cfcca51a6f3f30ab9d822448693e66fdddde27920 \ + --hash=sha256:62932f29cf2433988fcd799770ec64b374a3691e7902ecf85da14d5e0854d1ea \ + --hash=sha256:69aa1b443a182b13a17ff926ed6627af2d98f62f2fe5890583270cc4073f63bf \ + --hash=sha256:71cca80a056ebe19ec74b7117b09e650990c3ca535ac1c35234a96f65604192f \ + --hash=sha256:720986d9a4705dd8a40fdf172036f5ae787225036a7eb46e704c45aa8f62c054 \ + --hash=sha256:768e0e7c2898d40b16d4ef7a0b44e8150db3dd8995b4652aa1fe2902e92c7df8 \ + --hash=sha256:7a6206210c869ebd3f4eb9e89bea132aefb56ff3d1b7dd7e26b102b17e27bbb1 \ + --hash=sha256:7d8585707ecc6661d07367d444bbaa846b4e095d84451340da8df55a3757e152 \ + --hash=sha256:8113e17cfe236dc2277ec844ba9b3d5312f61bd2fdae6d3ed1c1cdd75f6cf2d8 \ + --hash=sha256:879c29a75969eb2722f94443752f4720d560d1e748474de54ae8dd230bc4956b \ + --hash=sha256:88b62164738239f62f4af92567b846a8ef7cf8abf53eddd83650603de4d52163 \ + --hash=sha256:8934577e1ed13f7d2d9cea3cc016cc6f95c19faedea2c2b56a6f94f257cea672 \ + --hash=sha256:9654085f2b22f66952124de13a8071b54453ff972c25c59b5ce1173a4283ffd9 \ + --hash=sha256:975a320baf7020339a67315284a4d3bf7460e664e484672bd3e71dbd881bc692 \ + --hash=sha256:9a3a4ff43702d39e3c97a8786314123d314e0f0e4dabc8367db5b665c93914de \ + --hash=sha256:a7a94c03386bb95456b12c66026b3a87d1b965f0f1e5733c36e7229f8f137747 \ + --hash=sha256:ab0f21c4818d46a60ca789ebc92327d6d874d3b7ccff3963f7af0a21dc6cff52 \ + --hash=sha256:bb71211414dd1eeb8d31ec529fe77cff04bf53efc783a5f6f0a32d84923f45cf \ + --hash=sha256:bf21ebf023ec67335258e0f3d3ad7b91bb9507985ba2b2206346de488267cad0 \ + --hash=sha256:bfc3980b4ba6f97138b04f0d32e8af21d6c9fa1f8e6e140c07d15690a0a99279 \ + --hash=sha256:c2232d4625c558f2aa001942cac1d7952aa9f0dbfc212f63bc754277769e1ef2 \ + --hash=sha256:ccddb9419ab4e1c48742457d0c0362dbdaeb9b28e6875115abfe319b29ee225d \ + --hash=sha256:d20dea7b83651d93b1eb2f353511fe7fd554752844523f17ad30115d8b9c8cd6 \ + --hash=sha256:e56ac8a8237ad4adec97c0cd4728596885f908053ab725e22900b5902e7f8e69 \ + --hash=sha256:eb4b2fdf88af4fb1cc569781a8f933d2a73ee82cd720e0cb4edabbaecf2a905b \ + --hash=sha256:eca01eb112a39d31cc4abb93a5aef2a81514c23f70956729f42fb83b11b3483f \ + --hash=sha256:fca608d199ffed4903dce1bcd97ad0fe8260f405c1c225bdf0002709132171c2 \ + --hash=sha256:fddcacf695581a8d856654bc4c8cfb73d5c9df26d5f55201722d3e6a699e9629 # via safir -attrs==22.1.0 +attrs==23.1.0 \ + --hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \ + --hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015 # via jsonschema -beautifulsoup4==4.11.1 +beautifulsoup4==4.12.2 \ + --hash=sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da \ + --hash=sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a # via nbconvert -bleach==5.0.1 +bleach==6.0.0 \ + --hash=sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414 \ + --hash=sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4 # via nbconvert -certifi==2022.6.15 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via # httpcore # httpx -cffi==1.15.1 +cffi==1.15.1 \ + --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ + --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ + --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ + --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ + --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ + --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ + --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ + --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ + --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ + --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ + --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ + --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ + --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ + --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ + --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ + --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ + --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ + --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ + --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ + --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ + --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ + --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ + --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ + --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ + --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ + --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ + --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ + --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ + --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ + --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ + --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ + --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ + --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ + --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ + --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ + --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ + --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ + --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ + --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ + --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ + --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ + --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ + --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ + --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ + --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ + --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ + --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ + --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ + --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ + --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ + --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ + --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ + --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ + --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ + --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ + --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ + --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ + --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ + --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ + --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ + --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ + --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ + --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ + --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 # via cryptography -click==8.1.3 +click==8.1.3 \ + --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ + --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 # via # -r requirements/main.in # arq # uvicorn -cryptography==37.0.4 - # via pyjwt -defusedxml==0.7.1 +cryptography==40.0.2 \ + --hash=sha256:05dc219433b14046c476f6f09d7636b92a1c3e5808b9a6536adf4932b3b2c440 \ + --hash=sha256:0dcca15d3a19a66e63662dc8d30f8036b07be851a8680eda92d079868f106288 \ + --hash=sha256:142bae539ef28a1c76794cca7f49729e7c54423f615cfd9b0b1fa90ebe53244b \ + --hash=sha256:3daf9b114213f8ba460b829a02896789751626a2a4e7a43a28ee77c04b5e4958 \ + --hash=sha256:48f388d0d153350f378c7f7b41497a54ff1513c816bcbbcafe5b829e59b9ce5b \ + --hash=sha256:4df2af28d7bedc84fe45bd49bc35d710aede676e2a4cb7fc6d103a2adc8afe4d \ + --hash=sha256:4f01c9863da784558165f5d4d916093737a75203a5c5286fde60e503e4276c7a \ + --hash=sha256:7a38250f433cd41df7fcb763caa3ee9362777fdb4dc642b9a349721d2bf47404 \ + --hash=sha256:8f79b5ff5ad9d3218afb1e7e20ea74da5f76943ee5edb7f76e56ec5161ec782b \ + --hash=sha256:956ba8701b4ffe91ba59665ed170a2ebbdc6fc0e40de5f6059195d9f2b33ca0e \ + --hash=sha256:a04386fb7bc85fab9cd51b6308633a3c271e3d0d3eae917eebab2fac6219b6d2 \ + --hash=sha256:a95f4802d49faa6a674242e25bfeea6fc2acd915b5e5e29ac90a32b1139cae1c \ + --hash=sha256:adc0d980fd2760c9e5de537c28935cc32b9353baaf28e0814df417619c6c8c3b \ + --hash=sha256:aecbb1592b0188e030cb01f82d12556cf72e218280f621deed7d806afd2113f9 \ + --hash=sha256:b12794f01d4cacfbd3177b9042198f3af1c856eedd0a98f10f141385c809a14b \ + --hash=sha256:c0764e72b36a3dc065c155e5b22f93df465da9c39af65516fe04ed3c68c92636 \ + --hash=sha256:c33c0d32b8594fa647d2e01dbccc303478e16fdd7cf98652d5b3ed11aa5e5c99 \ + --hash=sha256:cbaba590180cba88cb99a5f76f90808a624f18b169b90a4abb40c1fd8c19420e \ + --hash=sha256:d5a1bd0e9e2031465761dfa920c16b0065ad77321d8a8c1f5ee331021fda65e9 + # via + # pyjwt + # safir +defusedxml==0.7.1 \ + --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ + --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 # via nbconvert -deprecated==1.2.13 - # via redis -dnspython==2.2.1 +dnspython==2.3.0 \ + --hash=sha256:224e32b03eb46be70e12ef6d64e0be123a64e621ab4c0822ff6d450d52a540b9 \ + --hash=sha256:89141536394f909066cabd112e3e1a37e4e654db00a25308b0f130bc3152eb46 # via email-validator -email-validator==1.2.1 +email-validator==2.0.0.post1 \ + --hash=sha256:26efa040ae50e65cc130667080fa0f372f0ac3d852923a76166a54cf6a0ee780 \ + --hash=sha256:314114acd9421728ae6f74d0c0a5d6ec547d44ef4f20425af4093828af2266f3 # via pydantic -entrypoints==0.4 - # via - # jupyter-client - # nbconvert -fastapi==0.79.0 +fastapi==0.95.1 \ + --hash=sha256:9569f0a381f8a457ec479d90fa01005cfddaae07546eb1f3fa035bc4797ae7d5 \ + --hash=sha256:a870d443e5405982e1667dfe372663abf10754f246866056336d7f01c21dab07 # via # -r requirements/main.in # safir -fastjsonschema==2.16.1 +fastjsonschema==2.16.3 \ + --hash=sha256:04fbecc94300436f628517b05741b7ea009506ce8f946d40996567c669318490 \ + --hash=sha256:4a30d6315a68c253cfa8f963b9697246315aa3db89f98b97235e345dedfb0b8e # via nbformat -gidgethub==5.2.0 - # via -r requirements/main.in -greenlet==1.1.2 +gidgethub==5.2.1 \ + --hash=sha256:8ac9cf5314aac0f3a33f46127d4a538d0ed1a7030027eb2fc4aa3b55c66abcef \ + --hash=sha256:a533f85a57955261433c250701476304cc374037c0ab66b0e5372b4846749d5c + # via + # -r requirements/main.in + # safir +greenlet==2.0.2 \ + --hash=sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a \ + --hash=sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a \ + --hash=sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43 \ + --hash=sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33 \ + --hash=sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8 \ + --hash=sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088 \ + --hash=sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca \ + --hash=sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343 \ + --hash=sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645 \ + --hash=sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db \ + --hash=sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df \ + --hash=sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3 \ + --hash=sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86 \ + --hash=sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2 \ + --hash=sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a \ + --hash=sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf \ + --hash=sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7 \ + --hash=sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394 \ + --hash=sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40 \ + --hash=sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3 \ + --hash=sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6 \ + --hash=sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74 \ + --hash=sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0 \ + --hash=sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3 \ + --hash=sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91 \ + --hash=sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5 \ + --hash=sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9 \ + --hash=sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8 \ + --hash=sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b \ + --hash=sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6 \ + --hash=sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb \ + --hash=sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73 \ + --hash=sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b \ + --hash=sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df \ + --hash=sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9 \ + --hash=sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f \ + --hash=sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0 \ + --hash=sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857 \ + --hash=sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a \ + --hash=sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249 \ + --hash=sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30 \ + --hash=sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292 \ + --hash=sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b \ + --hash=sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d \ + --hash=sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b \ + --hash=sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c \ + --hash=sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca \ + --hash=sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7 \ + --hash=sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75 \ + --hash=sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae \ + --hash=sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b \ + --hash=sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470 \ + --hash=sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564 \ + --hash=sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9 \ + --hash=sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099 \ + --hash=sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0 \ + --hash=sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5 \ + --hash=sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19 \ + --hash=sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1 \ + --hash=sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526 # via sqlalchemy -gunicorn==20.1.0 +gunicorn==20.1.0 \ + --hash=sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e \ + --hash=sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8 # via -r requirements/main.in -h11==0.12.0 +h11==0.14.0 \ + --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ + --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 # via # httpcore # uvicorn -httpcore==0.15.0 +hiredis==2.2.2 \ + --hash=sha256:01e2e588392b5fdcc3a6aa0eb62a2eb2a142f829082fa4c3354228029d3aa1ce \ + --hash=sha256:02b9f928dc6cd43ed0f0ffc1c75fb209fb180f004b7e2e19994805f998d247aa \ + --hash=sha256:03ab1d545794bb0e09f3b1e2c8b3adcfacd84f6f2d402bfdcd441a98c0e9643c \ + --hash=sha256:03ab760fc96e0c5d36226eb727f30645bf6a53c97f14bfc0a4d0401bfc9b8af7 \ + --hash=sha256:03dfb4ab7a2136ce1be305592553f102e1bd91a96068ab2778e3252aed20d9bc \ + --hash=sha256:0fc1f9a9791d028b2b8afa318ccff734c7fc8861d37a04ca9b3d27c9b05f9718 \ + --hash=sha256:10dc34854e9acfb3e7cc4157606e2efcb497b1c6fca07bd6c3be34ae5e413f13 \ + --hash=sha256:14dfccf4696d75395c587a5dafafb4f7aa0a5d55309341d10bc2e7f1eaa20771 \ + --hash=sha256:1570fe4f93bc1ea487fb566f2b863fd0ed146f643a4ea31e4e07036db9e0c7f8 \ + --hash=sha256:18103090b8eda9c529830e26594e88b0b1472055785f3ed29b8adc694d03862a \ + --hash=sha256:1b084fbc3e69f99865242f8e1ccd4ea2a34bf6a3983d015d61133377526c0ce2 \ + --hash=sha256:1eb39b34d15220095dc49ad1e1082580d35cd3b6d9741def52988b5075e4ff03 \ + --hash=sha256:1f1c44242c18b1f02e6d1162f133d65d00e09cc10d9165dccc78662def72abc2 \ + --hash=sha256:20cfbc469400669a5999aa34ccba3872a1e34490ec3d5c84e8c0752c27977b7c \ + --hash=sha256:20ecbf87aac4f0f33f9c55ae15cb73b485d256c57518c590b7d0c9c152150632 \ + --hash=sha256:24301ca2bf9b2f843b4c3015c90f161798fa3bbc5b95fd494785751b137dbbe2 \ + --hash=sha256:2a355aff8dfa02ebfe67f0946dd706e490bddda9ea260afac9cdc43942310c53 \ + --hash=sha256:2c18b00a382546e19bcda8b83dcca5b6e0dbc238d235723434405f48a18e8f77 \ + --hash=sha256:2d1ba0799f3487294f72b2157944d5c3a4fb33c99e2d495d63eab98c7ec7234b \ + --hash=sha256:2ddc573809ca4374da1b24b48604f34f3d5f0911fcccfb1c403ff8d8ca31c232 \ + --hash=sha256:2e10a66680023bd5c5a3d605dae0844e3dde60eac5b79e39f51395a2aceaf634 \ + --hash=sha256:2e2f0ce3e8ab1314a52f562386220f6714fd24d7968a95528135ad04e88cc741 \ + --hash=sha256:2f220b71235d2deab1b4b22681c8aee444720d973b80f1b86a4e2a85f6bcf1e1 \ + --hash=sha256:339af17bb9817f8acb127247c79a99cad63db6738c0fb2aec9fa3d4f35d2a250 \ + --hash=sha256:359e662324318baadb768d3c4ade8c4bdcfbb313570eb01e15d75dc5db781815 \ + --hash=sha256:3645590b9234cafd21c8ecfbf252ad9aa1d67629f4bdc98ba3627f48f8f7b5aa \ + --hash=sha256:3a5fefac31c84143782ec1ebc323c04e733a6e4bfebcef9907a34e47a465e648 \ + --hash=sha256:40ff3f1ec3a4046732e9e41df08dcb1a559847196755d295d43e32528aae39e6 \ + --hash=sha256:449e18506d22af40977abd0f5a8979f57f88d4562fe591478a3438d76a15133d \ + --hash=sha256:4997f55e1208af95a8fbd0fa187b04c672fcec8f66e49b9ab7fcc45cc1657dc4 \ + --hash=sha256:4cb992e3f9753c5a0c637f333c2010d1ad702aebf2d730ee4d484f32b19bae97 \ + --hash=sha256:4ee9fe7cef505e8d925c70bebcc16bfab12aa7af922f948346baffd4730f7b00 \ + --hash=sha256:5155bc1710df8e21aa48c9b2f4d4e13e4987e1efff363a1ef9c84fae2cc6c145 \ + --hash=sha256:544d52fde3a8dac7854673eac20deca05214758193c01926ffbb0d57c6bf4ffe \ + --hash=sha256:55c7e9a9e05f8c0555bfba5c16d98492f8b6db650e56d0c35cc28aeabfc86020 \ + --hash=sha256:57f73aa04d0b70ff436fb35fa7ea2b796aa7addbd7ebb8d1aa1f3d1b3e4439f1 \ + --hash=sha256:5dac177a6ab8b4eb4d5e74978c29eef7cc9eef14086f814cb3893f7465578044 \ + --hash=sha256:5f2cfd323f83985f2bed6ed013107873275025af270485b7d04c338bfb47bd14 \ + --hash=sha256:632d79fd02b03e8d9fbaebbe40bfe34b920c5d0a9c0ef6270752e0db85208175 \ + --hash=sha256:674f296c3c89cb53f97aa9ba2508d3f360ad481b9e0c0e3a59b342a15192adaf \ + --hash=sha256:688b9b7458b4f3f452fea6ed062c04fa1fd9a69d9223d95c6cb052581aba553b \ + --hash=sha256:6e6ea7532221c97fa6d79f7d19d452cd9d1141d759c54279cc4774ce24728f13 \ + --hash=sha256:75349f7c8f77eb0fd33ede4575d1e5b0a902a8176a436bf03293d7fec4bd3894 \ + --hash=sha256:82f869ca44bcafa37cd71cfa1429648fa354d6021dcd72f03a2f66bcb339c546 \ + --hash=sha256:831461abe5b63e73719621a5f31d8fc175528a05dc09d5a8aa8ef565d6deefa4 \ + --hash=sha256:855d258e7f1aee3d7fbd5b1dc87790b1b5016e23d369a97b934a25ae7bc0171f \ + --hash=sha256:8753c561b37cccbda7264c9b4486e206a6318c18377cd647beb3aa41a15a6beb \ + --hash=sha256:8c3a6998f6f88d7ca4d082fd26525074df13162b274d7c64034784b6fdc56666 \ + --hash=sha256:8d43a7bba66a800279e33229a206861be09c279e261eaa8db4824e59465f4848 \ + --hash=sha256:8e16dc949cc2e9c5fbcd08de05b5fb61b89ff65738d772863c5c96248628830e \ + --hash=sha256:9873898e26e50cd41415e9d1ea128bfdb60eb26abb4f5be28a4500fd7834dc0c \ + --hash=sha256:990916e8b0b4eedddef787e73549b562f8c9e73a7fea82f9b8ff517806774ad0 \ + --hash=sha256:99350e89f52186146938bdba0b9c6cd68802c20346707d6ca8366f2d69d89b2f \ + --hash=sha256:9c270bd0567a9c60673284e000132f603bb4ecbcd707567647a68f85ef45c4d4 \ + --hash=sha256:9e0f444d9062f7e487ef42bab2fb2e290f1704afcbca48ad3ec23de63eef0fda \ + --hash=sha256:9eb14339e399554bb436cc4628e8aaa3943adf7afcf34aba4cbd1e3e6b9ec7ec \ + --hash=sha256:a06d0dd84f10be6b15a92edbca2490b64917280f66d8267c63de99b6550308ad \ + --hash=sha256:a1ce725542133dbdda9e8704867ef52651886bd1ef568c6fd997a27404381985 \ + --hash=sha256:a32a4474f7a4abdea954f3365608edee3f90f1de9fa05b81d214d4cad04c718a \ + --hash=sha256:a7114961ed78d708142f6c6eb1d2ed65dc3da4b5ae8a4660ad889dd7fc891971 \ + --hash=sha256:a89f5afb9827eab07b9c8c585cd4dc95e5232c727508ae2c935d09531abe9e33 \ + --hash=sha256:a9b306f4e870747eea8b008dcba2e9f1e4acd12b333a684bc1cc120e633a280e \ + --hash=sha256:aa90a5ee7a7f30c3d72d3513914b8f51f953a71b8cbd52a241b6db6685e55645 \ + --hash=sha256:ac15e7e1efca51b4695e540c80c328accb352c9608da7c2df82d1fa1a3c539ef \ + --hash=sha256:ac7f8d68826f95a3652e44b0c12bfa74d3aa6531d47d5dbe6a2fbfc7979bc20f \ + --hash=sha256:b083a69e158138ffa95740ff6984d328259387b5596908021b3ccb946469ff66 \ + --hash=sha256:b11960237a3025bf248135e5b497dc4923e83d137eb798fbfe78b40d57c4b156 \ + --hash=sha256:b5d290f3d8f7a05c4adbe6c355055b87c7081bfa1eccd1ae5491216307ee5f53 \ + --hash=sha256:ba6123ff137275e2f4c31fc74b93813fcbb79160d43f5357163e09638c7743de \ + --hash=sha256:bae004a0b978bf62e38d0eef5ab9156f8101d01167b3ca7054bd0994b773e917 \ + --hash=sha256:c24d856e13c02bd9d28a189e47be70cbba6f2c2a4bd85a8cc98819db9e7e3e06 \ + --hash=sha256:c446a2007985ae49c2ecd946dd819dea72b931beb5f647ba08655a1a1e133fa8 \ + --hash=sha256:c73aa295c5369135247ff63aa1fbb116067485d0506cd787cc0c868e72bbee55 \ + --hash=sha256:c9488ffb10acc6b121c498875278b0a6715d193742dc92d21a281712169ac06d \ + --hash=sha256:c95be6f20377d5995ef41a98314542e194d2dc9c2579d8f130a1aea78d48fd42 \ + --hash=sha256:ccc33d87866d213f84f857a98f69c13f94fbf99a3304e328869890c9e49c8d65 \ + --hash=sha256:d1acb7c957e5343303b3862947df3232dc7395da320b3b9ae076dfaa56ad59dc \ + --hash=sha256:d8bc89c7e33fecb083a199ade0131a34d20365a8c32239e218da57290987ca9a \ + --hash=sha256:d995846acc8e3339fb7833cd19bf6f3946ff5157c8488a4df9c51cd119a36870 \ + --hash=sha256:e4e2da61a04251121cb551f569c3250e6e27e95f2a80f8351c36822eda1f5d2b \ + --hash=sha256:e4ec57886f20f4298537cb1ab9dbda98594fb8d7c724c5fbf9a4b55329fd4a63 \ + --hash=sha256:e61c22fda5fc25d31bbced24a8322d33c5cb8cad9ba698634c16edb5b3e79a91 \ + --hash=sha256:e7e61ab75b851aac2d6bc634d03738a242a6ef255a44178437b427c5ebac0a87 \ + --hash=sha256:e86c800c6941698777fc58419216a66a7f76504f1cea72381d2ee206888e964d \ + --hash=sha256:e97d4e650b8d933a1229f341db92b610fc52b8d752490235977b63b81fbbc2cb \ + --hash=sha256:eaff526c2fed31c971b0fa338a25237ae5513550ef75d0b85b9420ec778cca45 \ + --hash=sha256:ed44b3c711cecde920f238ac35f70ac08744f2079b6369655856e43944464a72 \ + --hash=sha256:f1f1efbe9cc29a3af39cf7eed27225f951aed3f48a1149c7fb74529fb5ab86d4 \ + --hash=sha256:fd0ca35e2cf44866137cbb5ae7e439fab18a0b0e0e1cf51d45137622d59ec012 + # via redis +httpcore==0.17.0 \ + --hash=sha256:0fdfea45e94f0c9fd96eab9286077f9ff788dd186635ae61b312693e4d943599 \ + --hash=sha256:cc045a3241afbf60ce056202301b4d8b6af08845e3294055eb26b09913ef903c # via httpx -httptools==0.4.0 +httptools==0.5.0 \ + --hash=sha256:0297822cea9f90a38df29f48e40b42ac3d48a28637368f3ec6d15eebefd182f9 \ + --hash=sha256:1af91b3650ce518d226466f30bbba5b6376dbd3ddb1b2be8b0658c6799dd450b \ + --hash=sha256:1f90cd6fd97c9a1b7fe9215e60c3bd97336742a0857f00a4cb31547bc22560c2 \ + --hash=sha256:24bb4bb8ac3882f90aa95403a1cb48465de877e2d5298ad6ddcfdebec060787d \ + --hash=sha256:295874861c173f9101960bba332429bb77ed4dcd8cdf5cee9922eb00e4f6bc09 \ + --hash=sha256:3625a55886257755cb15194efbf209584754e31d336e09e2ffe0685a76cb4b60 \ + --hash=sha256:3a47a34f6015dd52c9eb629c0f5a8a5193e47bf2a12d9a3194d231eaf1bc451a \ + --hash=sha256:3cb8acf8f951363b617a8420768a9f249099b92e703c052f9a51b66342eea89b \ + --hash=sha256:4b098e4bb1174096a93f48f6193e7d9aa7071506a5877da09a783509ca5fff42 \ + --hash=sha256:4d9ebac23d2de960726ce45f49d70eb5466725c0087a078866043dad115f850f \ + --hash=sha256:50d4613025f15f4b11f1c54bbed4761c0020f7f921b95143ad6d58c151198142 \ + --hash=sha256:5230a99e724a1bdbbf236a1b58d6e8504b912b0552721c7c6b8570925ee0ccde \ + --hash=sha256:54465401dbbec9a6a42cf737627fb0f014d50dc7365a6b6cd57753f151a86ff0 \ + --hash=sha256:550059885dc9c19a072ca6d6735739d879be3b5959ec218ba3e013fd2255a11b \ + --hash=sha256:557be7fbf2bfa4a2ec65192c254e151684545ebab45eca5d50477d562c40f986 \ + --hash=sha256:5b65be160adcd9de7a7e6413a4966665756e263f0d5ddeffde277ffeee0576a5 \ + --hash=sha256:64eba6f168803a7469866a9c9b5263a7463fa8b7a25b35e547492aa7322036b6 \ + --hash=sha256:72ad589ba5e4a87e1d404cc1cb1b5780bfcb16e2aec957b88ce15fe879cc08ca \ + --hash=sha256:7d0c1044bce274ec6711f0770fd2d5544fe392591d204c68328e60a46f88843b \ + --hash=sha256:7e5eefc58d20e4c2da82c78d91b2906f1a947ef42bd668db05f4ab4201a99f49 \ + --hash=sha256:850fec36c48df5a790aa735417dca8ce7d4b48d59b3ebd6f83e88a8125cde324 \ + --hash=sha256:85b392aba273566c3d5596a0a490978c085b79700814fb22bfd537d381dd230c \ + --hash=sha256:8c2a56b6aad7cc8f5551d8e04ff5a319d203f9d870398b94702300de50190f63 \ + --hash=sha256:8f470c79061599a126d74385623ff4744c4e0f4a0997a353a44923c0b561ee51 \ + --hash=sha256:8ffce9d81c825ac1deaa13bc9694c0562e2840a48ba21cfc9f3b4c922c16f372 \ + --hash=sha256:9423a2de923820c7e82e18980b937893f4aa8251c43684fa1772e341f6e06887 \ + --hash=sha256:9b571b281a19762adb3f48a7731f6842f920fa71108aff9be49888320ac3e24d \ + --hash=sha256:a04fe458a4597aa559b79c7f48fe3dceabef0f69f562daf5c5e926b153817281 \ + --hash=sha256:aa47ffcf70ba6f7848349b8a6f9b481ee0f7637931d91a9860a1838bfc586901 \ + --hash=sha256:bede7ee075e54b9a5bde695b4fc8f569f30185891796b2e4e09e2226801d09bd \ + --hash=sha256:c1d2357f791b12d86faced7b5736dea9ef4f5ecdc6c3f253e445ee82da579449 \ + --hash=sha256:c6eeefd4435055a8ebb6c5cc36111b8591c192c56a95b45fe2af22d9881eee25 \ + --hash=sha256:ca1b7becf7d9d3ccdbb2f038f665c0f4857e08e1d8481cbcc1a86a0afcfb62b2 \ + --hash=sha256:e67d4f8734f8054d2c4858570cc4b233bf753f56e85217de4dfb2495904cf02e \ + --hash=sha256:e8a34e4c0ab7b1ca17b8763613783e2458e77938092c18ac919420ab8655c8c1 \ + --hash=sha256:e90491a4d77d0cb82e0e7a9cb35d86284c677402e4ce7ba6b448ccc7325c5421 \ + --hash=sha256:ef1616b3ba965cd68e6f759eeb5d34fbf596a79e84215eeceebf34ba3f61fdc7 \ + --hash=sha256:f222e1e9d3f13b68ff8a835574eda02e67277d51631d69d7cf7f8e07df678c86 \ + --hash=sha256:f5e3088f4ed33947e16fd865b8200f9cfae1144f41b64a8cf19b599508e096bc \ + --hash=sha256:f659d7a48401158c59933904040085c200b4be631cb5f23a7d561fbae593ec1f \ + --hash=sha256:fe9c766a0c35b7e3d6b6939393c8dfdd5da3ac5dec7f971ec9134f284c6c36d6 # via uvicorn -httpx==0.23.0 +httpx==0.24.0 \ + --hash=sha256:447556b50c1921c351ea54b4fe79d91b724ed2b027462ab9a329465d147d5a4e \ + --hash=sha256:507d676fc3e26110d41df7d35ebd8b3b8585052450f4097401c9be59d928c63e # via safir -idna==3.3 +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 # via # anyio # email-validator - # rfc3986 -jinja2==3.1.2 + # httpx +jinja2==3.1.2 \ + --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ + --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 # via # -r requirements/main.in # nbconvert -jsonschema==4.9.1 +jsonschema==4.17.3 \ + --hash=sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d \ + --hash=sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6 # via # -r requirements/main.in # nbformat -jupyter-client==7.3.4 +jupyter-client==8.2.0 \ + --hash=sha256:9fe233834edd0e6c0aa5f05ca2ab4bdea1842bfd2d8a932878212fc5301ddaf0 \ + --hash=sha256:b18219aa695d39e2ad570533e0d71fb7881d35a873051054a84ee2a17c4b7389 # via nbclient -jupyter-core==4.11.1 +jupyter-core==5.3.0 \ + --hash=sha256:6db75be0c83edbf1b7c9f91ec266a9a24ef945da630f3120e1a0046dc13713fc \ + --hash=sha256:d4201af84559bc8c70cead287e1ab94aeef3c512848dde077b7684b54d67730d # via # jupyter-client + # nbclient # nbconvert # nbformat -jupyterlab-pygments==0.2.2 +jupyterlab-pygments==0.2.2 \ + --hash=sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f \ + --hash=sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d # via nbconvert -linkify-it-py==1.0.3 +linkify-it-py==2.0.0 \ + --hash=sha256:1bff43823e24e507a099e328fc54696124423dd6320c75a9da45b4b754b748ad \ + --hash=sha256:476464480906bed8b2fa3813bf55566282e55214ad7e41b7d1c2b564666caf2f # via markdown-it-py -lxml==4.9.1 - # via nbconvert -markdown-it-py[linkify,plugins]==2.1.0 +markdown-it-py[linkify,plugins]==2.2.0 \ + --hash=sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30 \ + --hash=sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1 # via # -r requirements/main.in # mdformat # mdformat-gfm # mdit-py-plugins -markupsafe==2.1.1 +markupsafe==2.1.2 \ + --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ + --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ + --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ + --hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \ + --hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \ + --hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \ + --hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \ + --hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \ + --hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \ + --hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \ + --hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \ + --hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \ + --hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \ + --hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \ + --hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \ + --hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \ + --hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \ + --hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \ + --hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \ + --hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \ + --hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \ + --hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \ + --hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \ + --hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \ + --hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \ + --hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \ + --hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \ + --hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \ + --hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \ + --hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \ + --hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \ + --hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \ + --hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \ + --hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \ + --hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \ + --hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \ + --hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \ + --hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \ + --hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \ + --hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \ + --hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \ + --hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \ + --hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \ + --hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \ + --hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \ + --hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \ + --hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \ + --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ + --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ + --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 # via # jinja2 # nbconvert -mdformat==0.7.14 +mdformat==0.7.16 \ + --hash=sha256:76398d03baa394f331fb560fd0aed8257cf77b65b1c8146b92d395af16253662 \ + --hash=sha256:99b105033207d2ab70ba1ced8e07327ed4ef1e0a6bc1c7c00207ea73ab502782 # via # -r requirements/main.in # mdformat-gfm # mdformat-tables -mdformat-gfm==0.3.5 +mdformat-gfm==0.3.5 \ + --hash=sha256:1e627edc7665b59e008b3b9e5decc18c40cbd625c196d77e5ea3bc624e80ac8a \ + --hash=sha256:5ee5f0de1d3b56d5edfced023bfff0aeed958be328e5460dac3221ac1b61ce7c # via -r requirements/main.in -mdformat-tables==0.4.1 +mdformat-tables==0.4.1 \ + --hash=sha256:3024e88e9d29d7b8bb07fd6b59c9d5dcf14d2060122be29e30e72d27b65d7da9 \ + --hash=sha256:981f3dc7350027f78e3fd6a5fe8a16e123eec423af2d140e588d855751501019 # via mdformat-gfm -mdit-py-plugins==0.3.0 +mdit-py-plugins==0.3.5 \ + --hash=sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e \ + --hash=sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a # via # markdown-it-py # mdformat-gfm -mdurl==0.1.2 +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba # via markdown-it-py -mistune==0.8.4 +mistune==2.0.5 \ + --hash=sha256:0246113cb2492db875c6be56974a7c893333bf26cd92891c85f63151cee09d34 \ + --hash=sha256:bad7f5d431886fcbaf5f758118ecff70d31f75231b34024a1341120340a65ce8 # via nbconvert -nbclient==0.6.6 +nbclient==0.7.3 \ + --hash=sha256:26e41c6dca4d76701988bc34f64e1bfc2413ae6d368f13d7b5ac407efb08c755 \ + --hash=sha256:8fa96f7e36693d5e83408f5e840f113c14a45c279befe609904dbe05dad646d1 # via nbconvert -nbconvert==6.5.3 +nbconvert==7.3.1 \ + --hash=sha256:78685362b11d2e8058e70196fe83b09abed8df22d3e599cf271f4d39fdc48b9e \ + --hash=sha256:d2e95904666f1ff77d36105b9de4e0801726f93b862d5b28f69e93d99ad3b19c # via -r requirements/main.in -nbformat==5.4.0 +nbformat==5.8.0 \ + --hash=sha256:46dac64c781f1c34dfd8acba16547024110348f9fc7eab0f31981c2a3dc48d1f \ + --hash=sha256:d910082bd3e0bffcf07eabf3683ed7dda0727a326c446eeb2922abe102e65162 # via # -r requirements/main.in # nbclient # nbconvert -nest-asyncio==1.5.5 - # via - # jupyter-client - # nbclient -packaging==21.3 - # via - # nbconvert - # redis -pandocfilters==1.5.0 +packaging==23.1 \ + --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ + --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f # via nbconvert -pycparser==2.21 +pandocfilters==1.5.0 \ + --hash=sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38 \ + --hash=sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f + # via nbconvert +platformdirs==3.2.0 \ + --hash=sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08 \ + --hash=sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e + # via jupyter-core +pycparser==2.21 \ + --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ + --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 # via cffi -pydantic[email]==1.9.2 +pydantic[email]==1.10.7 \ + --hash=sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e \ + --hash=sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6 \ + --hash=sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd \ + --hash=sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca \ + --hash=sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b \ + --hash=sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a \ + --hash=sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245 \ + --hash=sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d \ + --hash=sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee \ + --hash=sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1 \ + --hash=sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3 \ + --hash=sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d \ + --hash=sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5 \ + --hash=sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914 \ + --hash=sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd \ + --hash=sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1 \ + --hash=sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e \ + --hash=sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e \ + --hash=sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a \ + --hash=sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd \ + --hash=sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f \ + --hash=sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209 \ + --hash=sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d \ + --hash=sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a \ + --hash=sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143 \ + --hash=sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918 \ + --hash=sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52 \ + --hash=sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e \ + --hash=sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f \ + --hash=sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e \ + --hash=sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb \ + --hash=sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe \ + --hash=sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe \ + --hash=sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d \ + --hash=sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209 \ + --hash=sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af # via # -r requirements/main.in - # arq # fastapi # safir -pygments==2.13.0 +pygments==2.15.1 \ + --hash=sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c \ + --hash=sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1 # via nbconvert -pyjwt[crypto]==2.4.0 +pyjwt[crypto]==2.6.0 \ + --hash=sha256:69285c7e31fc44f68a1feb309e948e0df53259d579295e6cfe2b1792329f05fd \ + --hash=sha256:d83c3d892a77bbb74d3e1a2cfa90afaadb60945205d1095d9221f04466f64c14 # via gidgethub -pyparsing==3.0.9 - # via packaging -pyrsistent==0.18.1 +pyrsistent==0.19.3 \ + --hash=sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8 \ + --hash=sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440 \ + --hash=sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a \ + --hash=sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c \ + --hash=sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3 \ + --hash=sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393 \ + --hash=sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9 \ + --hash=sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da \ + --hash=sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf \ + --hash=sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64 \ + --hash=sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a \ + --hash=sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3 \ + --hash=sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98 \ + --hash=sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2 \ + --hash=sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8 \ + --hash=sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf \ + --hash=sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc \ + --hash=sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7 \ + --hash=sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28 \ + --hash=sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2 \ + --hash=sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b \ + --hash=sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a \ + --hash=sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64 \ + --hash=sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19 \ + --hash=sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1 \ + --hash=sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9 \ + --hash=sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c # via jsonschema -python-dateutil==2.8.2 +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via jupyter-client -python-dotenv==0.20.0 +python-dotenv==1.0.0 \ + --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \ + --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a # via uvicorn -pyyaml==6.0 +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via # -r requirements/main.in # uvicorn -pyzmq==23.2.1 +pyzmq==25.0.2 \ + --hash=sha256:032f5c8483c85bf9c9ca0593a11c7c749d734ce68d435e38c3f72e759b98b3c9 \ + --hash=sha256:08bfcc21b5997a9be4fefa405341320d8e7f19b4d684fb9c0580255c5bd6d695 \ + --hash=sha256:1a843d26a8da1b752c74bc019c7b20e6791ee813cd6877449e6a1415589d22ff \ + --hash=sha256:1f124cb73f1aa6654d31b183810febc8505fd0c597afa127c4f40076be4574e0 \ + --hash=sha256:1f82906a2d8e4ee310f30487b165e7cc8ed09c009e4502da67178b03083c4ce0 \ + --hash=sha256:21ec0bf4831988af43c8d66ba3ccd81af2c5e793e1bf6790eb2d50e27b3c570a \ + --hash=sha256:24683285cc6b7bf18ad37d75b9db0e0fefe58404e7001f1d82bf9e721806daa7 \ + --hash=sha256:24abbfdbb75ac5039205e72d6c75f10fc39d925f2df8ff21ebc74179488ebfca \ + --hash=sha256:25e6873a70ad5aa31e4a7c41e5e8c709296edef4a92313e1cd5fc87bbd1874e2 \ + --hash=sha256:269968f2a76c0513490aeb3ba0dc3c77b7c7a11daa894f9d1da88d4a0db09835 \ + --hash=sha256:26b0358e8933990502f4513c991c9935b6c06af01787a36d133b7c39b1df37fa \ + --hash=sha256:28fdb9224a258134784a9cf009b59265a9dde79582fb750d4e88a6bcbc6fa3dc \ + --hash=sha256:2b9c9cc965cdf28381e36da525dcb89fc1571d9c54800fdcd73e3f73a2fc29bd \ + --hash=sha256:2da6813b7995b6b1d1307329c73d3e3be2fd2d78e19acfc4eff2e27262732388 \ + --hash=sha256:3059a6a534c910e1d5d068df42f60d434f79e6cc6285aa469b384fa921f78cf8 \ + --hash=sha256:312b3f0f066b4f1d17383aae509bacf833ccaf591184a1f3c7a1661c085063ae \ + --hash=sha256:34a6fddd159ff38aa9497b2e342a559f142ab365576284bc8f77cb3ead1f79c5 \ + --hash=sha256:374b55516393bfd4d7a7daa6c3b36d6dd6a31ff9d2adad0838cd6a203125e714 \ + --hash=sha256:38d9f78d69bcdeec0c11e0feb3bc70f36f9b8c44fc06e5d06d91dc0a21b453c7 \ + --hash=sha256:4a31992a8f8d51663ebf79df0df6a04ffb905063083d682d4380ab8d2c67257c \ + --hash=sha256:4a4b4261eb8f9ed71f63b9eb0198dd7c934aa3b3972dac586d0ef502ba9ab08b \ + --hash=sha256:510d8e55b3a7cd13f8d3e9121edf0a8730b87d925d25298bace29a7e7bc82810 \ + --hash=sha256:531e36d9fcd66f18de27434a25b51d137eb546931033f392e85674c7a7cea853 \ + --hash=sha256:54a96cf77684a3a537b76acfa7237b1e79a8f8d14e7f00e0171a94b346c5293e \ + --hash=sha256:56a94ab1d12af982b55ca96c6853db6ac85505e820d9458ac76364c1998972f4 \ + --hash=sha256:5c5fbb229e40a89a2fe73d0c1181916f31e30f253cb2d6d91bea7927c2e18413 \ + --hash=sha256:5d496815074e3e3d183fe2c7fcea2109ad67b74084c254481f87b64e04e9a471 \ + --hash=sha256:5eaeae038c68748082137d6896d5c4db7927e9349237ded08ee1bbd94f7361c9 \ + --hash=sha256:62ec8d979f56c0053a92b2b6a10ff54b9ec8a4f187db2b6ec31ee3dd6d3ca6e2 \ + --hash=sha256:64812f29d6eee565e129ca14b0c785744bfff679a4727137484101b34602d1a7 \ + --hash=sha256:6526d097b75192f228c09d48420854d53dfbc7abbb41b0e26f363ccb26fbc177 \ + --hash=sha256:659e62e1cbb063151c52f5b01a38e1df6b54feccfa3e2509d44c35ca6d7962ee \ + --hash=sha256:65c19a63b4a83ae45d62178b70223adeee5f12f3032726b897431b6553aa25af \ + --hash=sha256:67da1c213fbd208906ab3470cfff1ee0048838365135a9bddc7b40b11e6d6c89 \ + --hash=sha256:6a821a506822fac55d2df2085a52530f68ab15ceed12d63539adc32bd4410f6e \ + --hash=sha256:6a979e59d2184a0c8f2ede4b0810cbdd86b64d99d9cc8a023929e40dce7c86cc \ + --hash=sha256:6b8c1bbb70e868dc88801aa532cae6bd4e3b5233784692b786f17ad2962e5149 \ + --hash=sha256:6fadc60970714d86eff27821f8fb01f8328dd36bebd496b0564a500fe4a9e354 \ + --hash=sha256:715cff7644a80a7795953c11b067a75f16eb9fc695a5a53316891ebee7f3c9d5 \ + --hash=sha256:77942243ff4d14d90c11b2afd8ee6c039b45a0be4e53fb6fa7f5e4fd0b59da39 \ + --hash=sha256:7b504ae43d37e282301da586529e2ded8b36d4ee2cd5e6db4386724ddeaa6bbc \ + --hash=sha256:827bf60e749e78acb408a6c5af6688efbc9993e44ecc792b036ec2f4b4acf485 \ + --hash=sha256:8280ada89010735a12b968ec3ea9a468ac2e04fddcc1cede59cb7f5178783b9c \ + --hash=sha256:83d822e8687621bed87404afc1c03d83fa2ce39733d54c2fd52d8829edb8a7ff \ + --hash=sha256:8560756318ec7c4c49d2c341012167e704b5a46d9034905853c3d1ade4f55bee \ + --hash=sha256:85762712b74c7bd18e340c3639d1bf2f23735a998d63f46bb6584d904b5e401d \ + --hash=sha256:88649b19ede1cab03b96b66c364cbbf17c953615cdbc844f7f6e5f14c5e5261c \ + --hash=sha256:9a2e5fe42dfe6b73ca120b97ac9f34bfa8414feb15e00e37415dbd51cf227ef6 \ + --hash=sha256:9af0bb0277e92f41af35e991c242c9c71920169d6aa53ade7e444f338f4c8128 \ + --hash=sha256:9bdc40efb679b9dcc39c06d25629e55581e4c4f7870a5e88db4f1c51ce25e20d \ + --hash=sha256:9e1d2f2d86fc75ed7f8845a992c5f6f1ab5db99747fb0d78b5e4046d041164d2 \ + --hash=sha256:a2e92ff20ad5d13266bc999a29ed29a3b5b101c21fdf4b2cf420c09db9fb690e \ + --hash=sha256:a35960c8b2f63e4ef67fd6731851030df68e4b617a6715dd11b4b10312d19fef \ + --hash=sha256:a6f6ae12478fdc26a6d5fdb21f806b08fa5403cd02fd312e4cb5f72df078f96f \ + --hash=sha256:a9b5eeb5278a8a636bb0abdd9ff5076bcbb836cd2302565df53ff1fa7d106d54 \ + --hash=sha256:ab046e9cb902d1f62c9cc0eca055b1d11108bdc271caf7c2171487298f229b56 \ + --hash=sha256:ab2c056ac503f25a63f6c8c6771373e2a711b98b304614151dfb552d3d6c81f6 \ + --hash=sha256:abbce982a17c88d2312ec2cf7673985d444f1beaac6e8189424e0a0e0448dbb3 \ + --hash=sha256:ac178e666c097c8d3deb5097b58cd1316092fc43e8ef5b5fdb259b51da7e7315 \ + --hash=sha256:ad761cfbe477236802a7ab2c080d268c95e784fe30cafa7e055aacd1ca877eb0 \ + --hash=sha256:affec1470351178e892121b3414c8ef7803269f207bf9bef85f9a6dd11cde264 \ + --hash=sha256:b164cc3c8acb3d102e311f2eb6f3c305865ecb377e56adc015cb51f721f1dda6 \ + --hash=sha256:b48616a09d7df9dbae2f45a0256eee7b794b903ddc6d8657a9948669b345f220 \ + --hash=sha256:b491998ef886662c1f3d49ea2198055a9a536ddf7430b051b21054f2a5831800 \ + --hash=sha256:b733076ff46e7db5504c5e7284f04a9852c63214c74688bdb6135808531755a3 \ + --hash=sha256:c8fedc3ccd62c6b77dfe6f43802057a803a411ee96f14e946f4a76ec4ed0e117 \ + --hash=sha256:cb1f69a0a2a2b1aae8412979dd6293cc6bcddd4439bf07e4758d864ddb112354 \ + --hash=sha256:cca8524b61c0eaaa3505382dc9b9a3bc8165f1d6c010fdd1452c224225a26689 \ + --hash=sha256:cfb9f7eae02d3ac42fbedad30006b7407c984a0eb4189a1322241a20944d61e5 \ + --hash=sha256:d4427b4a136e3b7f85516c76dd2e0756c22eec4026afb76ca1397152b0ca8145 \ + --hash=sha256:d488c5c8630f7e782e800869f82744c3aca4aca62c63232e5d8c490d3d66956a \ + --hash=sha256:dd771a440effa1c36d3523bc6ba4e54ff5d2e54b4adcc1e060d8f3ca3721d228 \ + --hash=sha256:ed15e3a2c3c2398e6ae5ce86d6a31b452dfd6ad4cd5d312596b30929c4b6e182 \ + --hash=sha256:edbbf06cc2719889470a8d2bf5072bb00f423e12de0eb9ffec946c2c9748e149 \ + --hash=sha256:eef2a0b880ab40aca5a878933376cb6c1ec483fba72f7f34e015c0f675c90b20 \ + --hash=sha256:f7c8b8368e84381ae7c57f1f5283b029c888504aaf4949c32e6e6fb256ec9bf0 \ + --hash=sha256:ffc71111433bd6ec8607a37b9211f4ef42e3d3b271c6d76c813669834764b248 # via jupyter-client -redis==4.3.4 - # via arq -rfc3986[idna2008]==1.5.0 - # via httpx -safir[arq,db]==3.2.0 +redis[hiredis]==4.5.4 \ + --hash=sha256:2c19e6767c474f2e85167909061d525ed65bea9301c0770bb151e041b7ac89a2 \ + --hash=sha256:73ec35da4da267d6847e47f68730fdd5f62e2ca69e3ef5885c6a78a9374c3893 + # via + # arq + # safir +safir[arq,db,redis]==4.0.0 \ + --hash=sha256:9d883c2fbd30b2fb5804037291f81c75cd48326ac29f076e6b27198ea1d39f36 \ + --hash=sha256:eb7b4b1ba2fcca82d65e380acf524a90c5589c25e919b502fb5b686ad4cb3c68 # via -r requirements/main.in -six==1.16.0 +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 # via # bleach # python-dateutil -sniffio==1.2.0 +sniffio==1.3.0 \ + --hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \ + --hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 # via # anyio # httpcore # httpx -soupsieve==2.3.2.post1 +soupsieve==2.4.1 \ + --hash=sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8 \ + --hash=sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea # via beautifulsoup4 -sqlalchemy[asyncio]==1.4.40 +sqlalchemy[asyncio]==2.0.9 \ + --hash=sha256:07950fc82f844a2de67ddb4e535f29b65652b4d95e8b847823ce66a6d540a41d \ + --hash=sha256:0a865b5ec4ba24f57c33b633b728e43fde77b968911a6046443f581b25d29dd9 \ + --hash=sha256:0b49f1f71d7a44329a43d3edd38cc5ee4c058dfef4487498393d16172007954b \ + --hash=sha256:13f984a190d249769a050634b248aef8991acc035e849d02b634ea006c028fa8 \ + --hash=sha256:1b69666e25cc03c602d9d3d460e1281810109e6546739187044fc256c67941ef \ + --hash=sha256:1d06e119cf79a3d80ab069f064a07152eb9ba541d084bdaee728d8a6f03fd03d \ + --hash=sha256:246712af9fc761d6c13f4f065470982e175d902e77aa4218c9cb9fc9ff565a0c \ + --hash=sha256:34eb96c1de91d8f31e988302243357bef3f7785e1b728c7d4b98bd0c117dafeb \ + --hash=sha256:4c3020afb144572c7bfcba9d7cce57ad42bff6e6115dffcfe2d4ae6d444a214f \ + --hash=sha256:4f759eccb66e6d495fb622eb7f4ac146ae674d829942ec18b7f5a35ddf029597 \ + --hash=sha256:68ed381bc340b4a3d373dbfec1a8b971f6350139590c4ca3cb722fdb50035777 \ + --hash=sha256:6b72dccc5864ea95c93e0a9c4e397708917fb450f96737b4a8395d009f90b868 \ + --hash=sha256:6e84ab63d25d8564d7a8c05dc080659931a459ee27f6ed1cf4c91f292d184038 \ + --hash=sha256:734805708632e3965c2c40081f9a59263c29ffa27cba9b02d4d92dfd57ba869f \ + --hash=sha256:78612edf4ba50d407d0eb3a64e9ec76e6efc2b5d9a5c63415d53e540266a230a \ + --hash=sha256:7e472e9627882f2d75b87ff91c5a2bc45b31a226efc7cc0a054a94fffef85862 \ + --hash=sha256:865392a50a721445156809c1a6d6ab6437be70c1c2599f591a8849ed95d3c693 \ + --hash=sha256:8d118e233f416d713aac715e2c1101e17f91e696ff315fc9efbc75b70d11e740 \ + --hash=sha256:8d3ece5960b3e821e43a4927cc851b6e84a431976d3ffe02aadb96519044807e \ + --hash=sha256:93c78d42c14aa9a9e0866eacd5b48df40a50d0e2790ee377af7910d224afddcf \ + --hash=sha256:95719215e3ec7337b9f57c3c2eda0e6a7619be194a5166c07c1e599f6afc20fa \ + --hash=sha256:9838bd247ee42eb74193d865e48dd62eb50e45e3fdceb0fdef3351133ee53dcf \ + --hash=sha256:aa5c270ece17c0c0e0a38f2530c16b20ea05d8b794e46c79171a86b93b758891 \ + --hash=sha256:ac6a0311fb21a99855953f84c43fcff4bdca27a2ffcc4f4d806b26b54b5cddc9 \ + --hash=sha256:ad5363a1c65fde7b7466769d4261126d07d872fc2e816487ae6cec93da604b6b \ + --hash=sha256:b3e5864eba71a3718236a120547e52c8da2ccb57cc96cecd0480106a0c799c92 \ + --hash=sha256:bbda1da8d541904ba262825a833c9f619e93cb3fd1156be0a5e43cd54d588dcd \ + --hash=sha256:c6e27189ff9aebfb2c02fd252c629ea58657e7a5ff1a321b7fc9c2bf6dc0b5f3 \ + --hash=sha256:c8239ce63a90007bce479adf5460d48c1adae4b933d8e39a4eafecfc084e503c \ + --hash=sha256:d209594e68bec103ad5243ecac1b40bf5770c9ebf482df7abf175748a34f4853 \ + --hash=sha256:d5327f54a9c39e7871fc532639616f3777304364a0bb9b89d6033ad34ef6c5f8 \ + --hash=sha256:db4bd1c4792da753f914ff0b688086b9a8fd78bb9bc5ae8b6d2e65f176b81eb9 \ + --hash=sha256:e4780be0f19e5894c17f75fc8de2fe1ae233ab37827125239ceb593c6f6bd1e2 \ + --hash=sha256:e4a019f723b6c1e6b3781be00fb9e0844bc6156f9951c836ff60787cc3938d76 \ + --hash=sha256:e62c4e762d6fd2901692a093f208a6a6575b930e9458ad58c2a7f080dd6132da \ + --hash=sha256:e730603cae5747bc6d6dece98b45a57d647ed553c8d5ecef602697b1c1501cf2 \ + --hash=sha256:ebc4eeb1737a5a9bdb0c24f4c982319fa6edd23cdee27180978c29cbb026f2bd \ + --hash=sha256:ee2946042cc7851842d7a086a92b9b7b494cbe8c3e7e4627e27bc912d3a7655e \ + --hash=sha256:f005245e1cb9b8ca53df73ee85e029ac43155e062405015e49ec6187a2e3fb44 \ + --hash=sha256:f49c5d3c070a72ecb96df703966c9678dda0d4cb2e2736f88d15f5e1203b4159 \ + --hash=sha256:f61ab84956dc628c8dfe9d105b6aec38afb96adae3e5e7da6085b583ff6ea789 # via safir -starlette==0.19.1 +starlette==0.26.1 \ + --hash=sha256:41da799057ea8620e4667a3e69a5b1923ebd32b1819c8fa75634bbe8d8bea9bd \ + --hash=sha256:e87fce5d7cbdde34b76f0ac69013fd9d190d581d80681493016666e6f96c6d5e # via # -r requirements/main.in # fastapi # safir -structlog==22.1.0 +structlog==23.1.0 \ + --hash=sha256:270d681dd7d163c11ba500bc914b2472d2b50a8ef00faa999ded5ff83a2f906b \ + --hash=sha256:79b9e68e48b54e373441e130fa447944e6f87a05b35de23138e475c05d0f7e0e # via safir -tinycss2==1.1.1 +tinycss2==1.2.1 \ + --hash=sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847 \ + --hash=sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627 # via nbconvert -tomli==2.0.1 - # via mdformat -tornado==6.2 +tornado==6.3 \ + --hash=sha256:4546003dc8b5733489139d3bff5fa6a0211be505faf819bd9970e7c2b32e8122 \ + --hash=sha256:4d349846931557b7ec92f224b5d598b160e2ba26ae1812480b42e9622c884bf7 \ + --hash=sha256:6164571f5b9f73143d1334df4584cb9ac86d20c461e17b6c189a19ead8bb93c1 \ + --hash=sha256:6cfff1e9c15c79e106b8352269d201f8fc0815914a6260f3893ca18b724ea94b \ + --hash=sha256:720f53e6367b38190ae7fa398c25c086c69d88b3c6535bd6021a126b727fb5cd \ + --hash=sha256:912df5712024564e362ecce43c8d5862e14c78c8dd3846c9d889d44fbd7f4951 \ + --hash=sha256:c37b6a384d54ce6a31168d40ab21ad2591ddaf34973075cc0cad154402ecd9e8 \ + --hash=sha256:c659ab04d5aa477dbe44152c67d93f3ad3243b992d94f795ca1d5c73c37337ce \ + --hash=sha256:c9114a61a4588c09065b9996ae05462350d17160b92b9bf9a1e93689cc0424dc \ + --hash=sha256:d68f3192936ff2c4add04dc21a436a43b4408d466746b78bb2b9d0a53a18683f \ + --hash=sha256:d7b737e18f701de3e4a3b0824260b4d740e4d60607b8089bb80e80ffd464780e # via jupyter-client -traitlets==5.3.0 +traitlets==5.9.0 \ + --hash=sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8 \ + --hash=sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9 # via # jupyter-client # jupyter-core # nbclient # nbconvert # nbformat -typing-extensions==4.3.0 +typing-extensions==4.5.0 \ + --hash=sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb \ + --hash=sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4 # via - # aioredis + # arq # pydantic -uc-micro-py==1.0.1 + # sqlalchemy +uc-micro-py==1.0.1 \ + --hash=sha256:316cfb8b6862a0f1d03540f0ae6e7b033ff1fa0ddbe60c12cbe0d4cec846a69f \ + --hash=sha256:b7cdf4ea79433043ddfe2c82210208f26f7962c0cfbe3bacb05ee879a7fdb596 # via linkify-it-py -uritemplate==4.1.1 +uritemplate==4.1.1 \ + --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ + --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e # via gidgethub -uvicorn[standard]==0.18.2 +uvicorn[standard]==0.21.1 \ + --hash=sha256:0fac9cb342ba099e0d582966005f3fdba5b0290579fed4a6266dc702ca7bb032 \ + --hash=sha256:e47cac98a6da10cd41e6fd036d472c6f58ede6c5dbee3dbee3ef7a100ed97742 # via -r requirements/main.in -uvloop==0.16.0 +uvloop==0.17.0 \ + --hash=sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d \ + --hash=sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1 \ + --hash=sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595 \ + --hash=sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b \ + --hash=sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05 \ + --hash=sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8 \ + --hash=sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20 \ + --hash=sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded \ + --hash=sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c \ + --hash=sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8 \ + --hash=sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474 \ + --hash=sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f \ + --hash=sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62 \ + --hash=sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376 \ + --hash=sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c \ + --hash=sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e \ + --hash=sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b \ + --hash=sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4 \ + --hash=sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578 \ + --hash=sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811 \ + --hash=sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d \ + --hash=sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738 \ + --hash=sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa \ + --hash=sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9 \ + --hash=sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539 \ + --hash=sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c \ + --hash=sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718 \ + --hash=sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667 \ + --hash=sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c \ + --hash=sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024 # via uvicorn -watchfiles==0.16.1 +watchfiles==0.19.0 \ + --hash=sha256:0089c6dc24d436b373c3c57657bf4f9a453b13767150d17284fc6162b2791911 \ + --hash=sha256:09ea3397aecbc81c19ed7f025e051a7387feefdb789cf768ff994c1228182fda \ + --hash=sha256:176a9a7641ec2c97b24455135d58012a5be5c6217fc4d5fef0b2b9f75dbf5154 \ + --hash=sha256:18b28f6ad871b82df9542ff958d0c86bb0d8310bb09eb8e87d97318a3b5273af \ + --hash=sha256:20b44221764955b1e703f012c74015306fb7e79a00c15370785f309b1ed9aa8d \ + --hash=sha256:3d7d267d27aceeeaa3de0dd161a0d64f0a282264d592e335fff7958cc0cbae7c \ + --hash=sha256:5471582658ea56fca122c0f0d0116a36807c63fefd6fdc92c71ca9a4491b6b48 \ + --hash=sha256:5569fc7f967429d4bc87e355cdfdcee6aabe4b620801e2cf5805ea245c06097c \ + --hash=sha256:68dce92b29575dda0f8d30c11742a8e2b9b8ec768ae414b54f7453f27bdf9545 \ + --hash=sha256:79c533ff593db861ae23436541f481ec896ee3da4e5db8962429b441bbaae16e \ + --hash=sha256:7f3920b1285a7d3ce898e303d84791b7bf40d57b7695ad549dc04e6a44c9f120 \ + --hash=sha256:91633e64712df3051ca454ca7d1b976baf842d7a3640b87622b323c55f3345e7 \ + --hash=sha256:945be0baa3e2440151eb3718fd8846751e8b51d8de7b884c90b17d271d34cae8 \ + --hash=sha256:9afd0d69429172c796164fd7fe8e821ade9be983f51c659a38da3faaaaac44dc \ + --hash=sha256:9c75eff897786ee262c9f17a48886f4e98e6cfd335e011c591c305e5d083c056 \ + --hash=sha256:b538014a87f94d92f98f34d3e6d2635478e6be6423a9ea53e4dd96210065e193 \ + --hash=sha256:b6577b8c6c8701ba8642ea9335a129836347894b666dd1ec2226830e263909d3 \ + --hash=sha256:c0376deac92377817e4fb8f347bf559b7d44ff556d9bc6f6208dd3f79f104aaf \ + --hash=sha256:cae3dde0b4b2078f31527acff6f486e23abed307ba4d3932466ba7cdd5ecec79 \ + --hash=sha256:cb5d45c4143c1dd60f98a16187fd123eda7248f84ef22244818c18d531a249d1 \ + --hash=sha256:d9b073073e048081e502b6c6b0b88714c026a1a4c890569238d04aca5f9ca74b \ + --hash=sha256:fac19dc9cbc34052394dbe81e149411a62e71999c0a19e1e09ce537867f95ae0 # via uvicorn -webencodings==0.5.1 +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 # via # bleach # tinycss2 -websockets==10.3 +websockets==11.0.2 \ + --hash=sha256:0fb4480556825e4e6bf2eebdbeb130d9474c62705100c90e59f2f56459ddab42 \ + --hash=sha256:13bd5bebcd16a4b5e403061b8b9dcc5c77e7a71e3c57e072d8dff23e33f70fba \ + --hash=sha256:143782041e95b63083b02107f31cda999f392903ae331de1307441f3a4557d51 \ + --hash=sha256:1b52def56d2a26e0e9c464f90cadb7e628e04f67b0ff3a76a4d9a18dfc35e3dd \ + --hash=sha256:1df2413266bf48430ef2a752c49b93086c6bf192d708e4a9920544c74cd2baa6 \ + --hash=sha256:2174a75d579d811279855df5824676d851a69f52852edb0e7551e0eeac6f59a4 \ + --hash=sha256:220d5b93764dd70d7617f1663da64256df7e7ea31fc66bc52c0e3750ee134ae3 \ + --hash=sha256:232b6ba974f5d09b1b747ac232f3a3d8f86de401d7b565e837cc86988edf37ac \ + --hash=sha256:25aae96c1060e85836552a113495db6d857400288161299d77b7b20f2ac569f2 \ + --hash=sha256:25e265686ea385f22a00cc2b719b880797cd1bb53b46dbde969e554fb458bfde \ + --hash=sha256:2abeeae63154b7f63d9f764685b2d299e9141171b8b896688bd8baec6b3e2303 \ + --hash=sha256:2acdc82099999e44fa7bd8c886f03c70a22b1d53ae74252f389be30d64fd6004 \ + --hash=sha256:2eb042734e710d39e9bc58deab23a65bd2750e161436101488f8af92f183c239 \ + --hash=sha256:3178d965ec204773ab67985a09f5696ca6c3869afeed0bb51703ea404a24e975 \ + --hash=sha256:320ddceefd2364d4afe6576195201a3632a6f2e6d207b0c01333e965b22dbc84 \ + --hash=sha256:34a6f8996964ccaa40da42ee36aa1572adcb1e213665e24aa2f1037da6080909 \ + --hash=sha256:3565a8f8c7bdde7c29ebe46146bd191290413ee6f8e94cf350609720c075b0a1 \ + --hash=sha256:392d409178db1e46d1055e51cc850136d302434e12d412a555e5291ab810f622 \ + --hash=sha256:3a09cce3dacb6ad638fdfa3154d9e54a98efe7c8f68f000e55ca9c716496ca67 \ + --hash=sha256:3a2100b02d1aaf66dc48ff1b2a72f34f6ebc575a02bc0350cc8e9fbb35940166 \ + --hash=sha256:3b87cd302f08ea9e74fdc080470eddbed1e165113c1823fb3ee6328bc40ca1d3 \ + --hash=sha256:3e79065ff6549dd3c765e7916067e12a9c91df2affea0ac51bcd302aaf7ad207 \ + --hash=sha256:3ffe251a31f37e65b9b9aca5d2d67fd091c234e530f13d9dce4a67959d5a3fba \ + --hash=sha256:46388a050d9e40316e58a3f0838c63caacb72f94129eb621a659a6e49bad27ce \ + --hash=sha256:46dda4bc2030c335abe192b94e98686615f9274f6b56f32f2dd661fb303d9d12 \ + --hash=sha256:4c54086b2d2aec3c3cb887ad97e9c02c6be9f1d48381c7419a4aa932d31661e4 \ + --hash=sha256:5004c087d17251938a52cce21b3dbdabeecbbe432ce3f5bbbf15d8692c36eac9 \ + --hash=sha256:502683c5dedfc94b9f0f6790efb26aa0591526e8403ad443dce922cd6c0ec83b \ + --hash=sha256:518ed6782d9916c5721ebd61bb7651d244178b74399028302c8617d0620af291 \ + --hash=sha256:580cc95c58118f8c39106be71e24d0b7e1ad11a155f40a2ee687f99b3e5e432e \ + --hash=sha256:58477b041099bb504e1a5ddd8aa86302ed1d5c6995bdd3db2b3084ef0135d277 \ + --hash=sha256:5875f623a10b9ba154cb61967f940ab469039f0b5e61c80dd153a65f024d9fb7 \ + --hash=sha256:5c7de298371d913824f71b30f7685bb07ad13969c79679cca5b1f7f94fec012f \ + --hash=sha256:634239bc844131863762865b75211a913c536817c0da27f691400d49d256df1d \ + --hash=sha256:6d872c972c87c393e6a49c1afbdc596432df8c06d0ff7cd05aa18e885e7cfb7c \ + --hash=sha256:752fbf420c71416fb1472fec1b4cb8631c1aa2be7149e0a5ba7e5771d75d2bb9 \ + --hash=sha256:7742cd4524622cc7aa71734b51294644492a961243c4fe67874971c4d3045982 \ + --hash=sha256:808b8a33c961bbd6d33c55908f7c137569b09ea7dd024bce969969aa04ecf07c \ + --hash=sha256:87c69f50281126dcdaccd64d951fb57fbce272578d24efc59bce72cf264725d0 \ + --hash=sha256:8df63dcd955eb6b2e371d95aacf8b7c535e482192cff1b6ce927d8f43fb4f552 \ + --hash=sha256:8f24cd758cbe1607a91b720537685b64e4d39415649cac9177cd1257317cf30c \ + --hash=sha256:8f392587eb2767afa8a34e909f2fec779f90b630622adc95d8b5e26ea8823cb8 \ + --hash=sha256:954eb789c960fa5daaed3cfe336abc066941a5d456ff6be8f0e03dd89886bb4c \ + --hash=sha256:955fcdb304833df2e172ce2492b7b47b4aab5dcc035a10e093d911a1916f2c87 \ + --hash=sha256:95c09427c1c57206fe04277bf871b396476d5a8857fa1b99703283ee497c7a5d \ + --hash=sha256:a4fe2442091ff71dee0769a10449420fd5d3b606c590f78dd2b97d94b7455640 \ + --hash=sha256:aa7b33c1fb2f7b7b9820f93a5d61ffd47f5a91711bc5fa4583bbe0c0601ec0b2 \ + --hash=sha256:adf6385f677ed2e0b021845b36f55c43f171dab3a9ee0ace94da67302f1bc364 \ + --hash=sha256:b1a69701eb98ed83dd099de4a686dc892c413d974fa31602bc00aca7cb988ac9 \ + --hash=sha256:b2a573c8d71b7af937852b61e7ccb37151d719974146b5dc734aad350ef55a02 \ + --hash=sha256:b444366b605d2885f0034dd889faf91b4b47668dd125591e2c64bfde611ac7e1 \ + --hash=sha256:b985ba2b9e972cf99ddffc07df1a314b893095f62c75bc7c5354a9c4647c6503 \ + --hash=sha256:c78ca3037a954a4209b9f900e0eabbc471fb4ebe96914016281df2c974a93e3e \ + --hash=sha256:ca9b2dced5cbbc5094678cc1ec62160f7b0fe4defd601cd28a36fde7ee71bbb5 \ + --hash=sha256:cb46d2c7631b2e6f10f7c8bac7854f7c5e5288f024f1c137d4633c79ead1e3c0 \ + --hash=sha256:ce69f5c742eefd039dce8622e99d811ef2135b69d10f9aa79fbf2fdcc1e56cd7 \ + --hash=sha256:cf45d273202b0c1cec0f03a7972c655b93611f2e996669667414557230a87b88 \ + --hash=sha256:d1881518b488a920434a271a6e8a5c9481a67c4f6352ebbdd249b789c0467ddc \ + --hash=sha256:d3cc3e48b6c9f7df8c3798004b9c4b92abca09eeea5e1b0a39698f05b7a33b9d \ + --hash=sha256:d6b2bfa1d884c254b841b0ff79373b6b80779088df6704f034858e4d705a4802 \ + --hash=sha256:d70a438ef2a22a581d65ad7648e949d4ccd20e3c8ed7a90bbc46df4e60320891 \ + --hash=sha256:daa1e8ea47507555ed7a34f8b49398d33dff5b8548eae3de1dc0ef0607273a33 \ + --hash=sha256:dca9708eea9f9ed300394d4775beb2667288e998eb6f542cdb6c02027430c599 \ + --hash=sha256:dd906b0cdc417ea7a5f13bb3c6ca3b5fd563338dc596996cb0fdd7872d691c0a \ + --hash=sha256:e0eeeea3b01c97fd3b5049a46c908823f68b59bf0e18d79b231d8d6764bc81ee \ + --hash=sha256:e37a76ccd483a6457580077d43bc3dfe1fd784ecb2151fcb9d1c73f424deaeba \ + --hash=sha256:e8b967a4849db6b567dec3f7dd5d97b15ce653e3497b8ce0814e470d5e074750 \ + --hash=sha256:ec00401846569aaf018700249996143f567d50050c5b7b650148989f956547af \ + --hash=sha256:ede13a6998ba2568b21825809d96e69a38dc43184bdeebbde3699c8baa21d015 \ + --hash=sha256:f97e03d4d5a4f0dca739ea274be9092822f7430b77d25aa02da6775e490f6846 # via uvicorn -wrapt==1.14.1 - # via deprecated -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.0.0 - # via gunicorn +# WARNING: The following packages were not pinned, but pip requires them to be +# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag. +# setuptools diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 6b8c4f68..00000000 --- a/setup.cfg +++ /dev/null @@ -1,58 +0,0 @@ -[metadata] -name = times-square -description = Times Square is a service for parameterized Jupyter Notebooks as dynamic webpages. -author = Association of Universities for Research in Astronomy, Inc. (AURA) -author_email = sqre-admin@lists.lsst.org -long_description = file: README.rst, CHANGELOG.rst, LICENSE -long_description_content_type = text/x-rst -license = MIT -url = https://github.com/lsst-sqre/times-square -project_urls = - Change log = https://github.com/lsst-sqre/times-square/main/blob/CHANGELOG.rst - Source code = https://github.com/lsst-sqre/times-square - Issue tracker = https://github.com/lsst-sqre/times-square/issues -classifiers = - Development Status :: 4 - Beta - License :: OSI Approved :: MIT License - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.10 - Natural Language :: English - Operating System :: POSIX -keywords = - lsst - -[options] -zip_safe = False -include_package_data = True -package_dir = - = src -packages=find: -python_requires = >=3.10 -setup_requires = - setuptools_scm -# Use requirements/main.in for runtime dependencies instead of install_requires - -[options.packages.find] -where = src - -[options.entry_points] -console_scripts = - times-square = timessquare.cli:main - -[flake8] -max-line-length = 79 -# E203: whitespace before :, flake8 disagrees with PEP-8 -# W503: line break after binary operator, flake8 disagrees with PEP-8 -ignore = E203, W503 - -[mypy] -plugins = sqlalchemy.ext.mypy.plugin -disallow_untyped_defs = True -disallow_incomplete_defs = True -ignore_missing_imports = True -show_error_codes = True -strict_equality = True -warn_redundant_casts = True -warn_unreachable = True -warn_unused_ignores = True diff --git a/setup.py b/setup.py deleted file mode 100644 index d5d43d7c..00000000 --- a/setup.py +++ /dev/null @@ -1,3 +0,0 @@ -from setuptools import setup - -setup(use_scm_version=True) diff --git a/src/timessquare/cli.py b/src/timessquare/cli.py index a8380ee4..af37d33a 100644 --- a/src/timessquare/cli.py +++ b/src/timessquare/cli.py @@ -7,7 +7,7 @@ import click import structlog import uvicorn -from aioredis import Redis +from redis.asyncio import Redis from safir.asyncio import run_with_asyncio from safir.database import create_database_engine, initialize_database @@ -78,11 +78,10 @@ async def reset_html() -> None: redis = Redis.from_url(config.redis_url, password=None) try: html_store = NbHtmlCacheStore(redis) - record_count = await html_store.delete_all() - if record_count > 0: - click.echo(f"Deleted {record_count} HTML records") - else: - click.echo("No HTML records to delete") + html_store.scan("*") + n = len([r async for r in html_store.scan("*")]) + await html_store.delete_all("*") + click.echo(f"Deleted {n} HTML records") except Exception as e: click.echo(str(e)) finally: diff --git a/src/timessquare/config.py b/src/timessquare/config.py index ce1a884e..1455e94e 100644 --- a/src/timessquare/config.py +++ b/src/timessquare/config.py @@ -23,14 +23,12 @@ class Profile(str, Enum): - production = "production" development = "development" class LogLevel(str, Enum): - DEBUG = "DEBUG" INFO = "INFO" @@ -43,7 +41,6 @@ class LogLevel(str, Enum): class Config(BaseSettings): - name: str = Field("times-square", env="SAFIR_NAME") profile: Profile = Field(Profile.production, env="SAFIR_PROFILE") @@ -75,7 +72,12 @@ class Config(BaseSettings): database_password: SecretStr = Field(..., env="TS_DATABASE_PASSWORD") - redis_url: RedisDsn = Field("redis://localhost:6379/0", env="TS_REDIS_URL") + redis_url: RedisDsn = Field( + env="TS_REDIS_URL", + default_factory=lambda: RedisDsn( + "redis://localhost:6379/0", scheme="redis" + ), + ) """URL for the redis instance, used by the worker queue.""" github_app_id: Optional[str] = Field(None, env="TS_GITHUB_APP_ID") @@ -106,7 +108,10 @@ class Config(BaseSettings): """ redis_queue_url: RedisDsn = Field( - "redis://localhost:6379/1", env="TS_REDIS_QUEUE_URL" + env="TS_REDIS_QUEUE_URL", + default_factory=lambda: RedisDsn( + "redis://localhost:6379/1", scheme="redis" + ), ) queue_name: str = Field("arq:queue", env="TS_REDIS_QUEUE_NAME") diff --git a/src/timessquare/dependencies/redis.py b/src/timessquare/dependencies/redis.py index 82741ef1..114da89f 100644 --- a/src/timessquare/dependencies/redis.py +++ b/src/timessquare/dependencies/redis.py @@ -2,13 +2,13 @@ from typing import Optional -from aioredis import Redis +from redis.asyncio import Redis __all__ = ["RedisDependency", "redis_dependency"] class RedisDependency: - """Provides an aioredis pool as a dependency. + """Provides an asyncio-based Redis client as a dependency. Notes ----- @@ -17,7 +17,7 @@ class RedisDependency: """ def __init__(self) -> None: - self.redis: Optional[Redis] = None + self.redis: Redis | None = None async def initialize( self, redis_url: str, password: Optional[str] = None diff --git a/src/timessquare/dependencies/requestcontext.py b/src/timessquare/dependencies/requestcontext.py index b06a7c23..51609f32 100644 --- a/src/timessquare/dependencies/requestcontext.py +++ b/src/timessquare/dependencies/requestcontext.py @@ -3,9 +3,9 @@ from dataclasses import dataclass from typing import Optional -import aioredis from fastapi import Depends, Request, Response from httpx import AsyncClient +from redis.asyncio import Redis from safir.dependencies.db_session import db_session_dependency from safir.dependencies.http_client import http_client_dependency from safir.dependencies.logger import logger_dependency @@ -14,7 +14,7 @@ from timessquare.config import Config, config from timessquare.dependencies.redis import redis_dependency -from timessquare.services.github.repo import GitHubRepoService +from timessquare.services.githubrepo import GitHubRepoService from timessquare.services.page import PageService from timessquare.storage.nbhtmlcache import NbHtmlCacheStore from timessquare.storage.noteburstjobstore import NoteburstJobStore @@ -48,7 +48,7 @@ class RequestContext: session: async_scoped_session """The database session.""" - redis: aioredis.Redis + redis: Redis """Redis connection pool.""" http_client: AsyncClient @@ -105,7 +105,7 @@ async def context_dependency( response: Response, logger: BoundLogger = Depends(logger_dependency), session: async_scoped_session = Depends(db_session_dependency), - redis: aioredis.Redis = Depends(redis_dependency), + redis: Redis = Depends(redis_dependency), http_client: AsyncClient = Depends(http_client_dependency), ) -> RequestContext: """Provides a RequestContext as a dependency.""" diff --git a/src/timessquare/domain/githubapi.py b/src/timessquare/domain/githubapi.py deleted file mode 100644 index 855edd8f..00000000 --- a/src/timessquare/domain/githubapi.py +++ /dev/null @@ -1,324 +0,0 @@ -"""Pydantic models describing resources from the GitHub REST v3 API.""" - -from __future__ import annotations - -from base64 import b64decode -from enum import Enum -from typing import List, Optional - -from pydantic import BaseModel, Field, HttpUrl - - -class GitHubRepoOwnerModel(BaseModel): - """A Pydantic model for the "owner" field found in repository objects. - - https://docs.github.com/en/rest/repos/repos#get-a-repository - """ - - login: str = Field( - title="Login name of the owner (either a user or an organization)" - ) - - -class GitHubUserModel(BaseModel): - """A Pydantic model for the "user" field found in GitHub API resources. - - This contains brief (public) info about a user. - """ - - login: str = Field(title="Login name", description="GitHub username") - - html_url: HttpUrl = Field(description="Homepage for the user on GitHub") - - url: HttpUrl = Field( - description="URL for the user's resource in the GitHub API" - ) - - avatar_url: HttpUrl = Field(description="URL to the user's avatar") - - -class GitHubRepositoryModel(BaseModel): - """A Pydantic model for the "repository" field, often found in webhook - payloads. - - https://docs.github.com/en/rest/repos/repos#get-a-repository - """ - - name: str = Field( - title="Repository name", - description="Excludes owner prefix.", - example="times-square-demo", - ) - - full_name: str = Field( - title="Full name", - description="Includes owner prefix", - example="lsst-sqre/times-square-demo", - ) - - owner: GitHubRepoOwnerModel = Field(title="The repository's owner") - - default_branch: str = Field(title="The default branch", example="main") - - html_url: HttpUrl = Field( - title="URL of the repository for browsers", - example="https://github.com/lsst-sqre/times-square-demo", - ) - - branches_url: str = Field( - title="URI template for the repo's branches endpoint", - example=( - "https://github.com/lsst-sqre/times-square-demo/branches{/branch}" - ), - ) - - contents_url: str = Field( - title="URI template for the contents endpoint", - example=( - "https://github.com/lsst-sqre/times-square-demo/contents/{+path}" - ), - ) - - trees_url: str = Field( - title="URI template for the Git tree API", - example=( - "https://github.com/lsst-sqre/times-square-demo/git/trees{/sha}" - ), - ) - - blobs_url: str = Field( - title="URI template for the Git blobs API", - example=( - "https://github.com/lsst-sqre/times-square-demo/git/blobs{/sha}" - ), - ) - - -class GitHubPullState(str, Enum): - """The state of a GitHub PR. - - https://docs.github.com/en/rest/pulls/pulls#get-a-pull-request - """ - - open = "open" - closed = "closed" - - -class GitHubPullRequestModel(BaseModel): - """A Pydantic model for a GitHub Pull Request. - - This is also the ``pull_request`` field inside the - GitHubPullRequestEventModel. - - https://docs.github.com/en/rest/pulls/pulls#get-a-pull-request - """ - - html_url: HttpUrl = Field(title="Web URL of the PR") - - number: int = Field(title="Pull request number") - - title: str = Field(title="Title") - - state: GitHubPullState = Field( - description="Whether the PR is opened or closed" - ) - - draft: bool = Field(description="True if the PR is a draft") - - merged: bool = Field(description="True if the PR is merged") - - user: GitHubUserModel = Field(description="The user that opened the PR") - - -class GitHubBranchCommitModel(BaseModel): - """A Pydantic model for the commit field found in GitHubBranchModel.""" - - sha: str = Field(title="Git commit SHA") - - url: HttpUrl = Field(title="URL for commit resource") - - -class GitHubBranchModel(BaseModel): - """A Pydantic model for a GitHub branch. - - https://docs.github.com/en/rest/branches/branches#get-a-branch - """ - - name: str = Field(title="Branch name", example="main") - - commit: GitHubBranchCommitModel = Field(title="HEAD commit info") - - -class GitHubBlobModel(BaseModel): - """A Pydantic model for a blob, returned the GitHub blob endpoint - - See https://docs.github.com/en/rest/git/blobs#get-a-blob - """ - - content: str = Field(title="Encoded content") - - encoding: str = Field( - title="Content encoding", description="Typically is base64" - ) - - url: HttpUrl = Field(title="API url of this resource") - - sha: str = Field(title="Git sha of tree object") - - size: int = Field(title="Size of the content in bytes") - - def decode(self) -> str: - """Decode content. - - Currently supports these encodings: - - - base64 - """ - if self.encoding == "base64": - return b64decode(self.content).decode() - else: - raise NotImplementedError( - f"GitHub blob content encoding {self.encoding} " - f"is unknown by GitHubBlobModel for url {self.url}" - ) - - -class GitHubCheckSuiteStatus(str, Enum): - - queued = "queued" - in_progress = "in_progress" - completed = "completed" - - -class GitHubCheckSuiteConclusion(str, Enum): - - success = "success" - failure = "failure" - neutral = "neutral" - cancelled = "cancelled" - timed_out = "timed_out" - action_required = "action_required" - stale = "stale" - - -class GitHubCheckSuiteModel(BaseModel): - """A Pydantic model for the "check_suite" field in a check_suite webhook - (`GitHubCheckSuiteRequestModel`). - """ - - id: str = Field(description="Identifier for this check run") - - head_branch: str = Field( - title="Head branch", - description="Name of the branch the changes are on.", - ) - - head_sha: str = Field( - title="Head sha", - description="The SHA of the most recent commit for this check suite.", - ) - - url: HttpUrl = Field( - description="GitHub API URL for the check suite resource." - ) - - status: GitHubCheckSuiteStatus - - conclusion: Optional[GitHubCheckSuiteConclusion] - - -class GitHubCheckRunStatus(str, Enum): - """The check run status.""" - - queued = "queued" - in_progress = "in_progress" - completed = "completed" - - -class GitHubCheckRunConclusion(str, Enum): - """The check run conclusion state.""" - - success = "success" - failure = "failure" - neutral = "neutral" - cancelled = "cancelled" - timed_out = "timed_out" - action_required = "action_required" - stale = "stale" - - -class GitHubCheckRunAnnotationLevel(str, Enum): - """The level of a check run output annotation.""" - - notice = "notice" - warning = "warning" - failure = "failure" - - -class GitHubCheckSuiteId(BaseModel): - """Brief information about a check suite in the `GitHubCheckRunModel`.""" - - id: str = Field(description="Check suite ID") - - -class GitHubCheckRunOutput(BaseModel): - """Check run output report.""" - - title: Optional[str] = Field(None, description="Title of the report") - - summary: Optional[str] = Field( - None, description="Summary information (markdown formatted" - ) - - text: Optional[str] = Field(None, description="Extended report (markdown)") - - -class GitHubCheckRunPrInfoModel(BaseModel): - """A Pydantic model of the "pull_requsts[]" items in a check run - GitHub API model. - - https://docs.github.com/en/rest/checks/runs#get-a-check-run - """ - - url: HttpUrl = Field(description="GitHub API URL for this pull request") - - -class GitHubCheckRunModel(BaseModel): - """A Pydantic model for the "check_run" field in a check_run webhook - payload (`GitHubCheckRunPayloadModel`). - """ - - id: str = Field(description="Identifier for this check run") - - external_id: Optional[str] = Field( - description="Identifier set by the check runner." - ) - - head_sha: str = Field( - title="Head sha", - description="The SHA of the most recent commit for this check suite.", - ) - - status: GitHubCheckRunStatus = Field( - description="Status of the check run." - ) - - conclusion: Optional[GitHubCheckRunConclusion] = Field( - description="Conclusion status, if completed." - ) - - name: str = Field(description="Name of the check run.") - - url: HttpUrl = Field(description="URL of the check run API resource.") - - html_url: HttpUrl = Field(description="URL of the check run webpage.") - - check_suite: GitHubCheckSuiteId - - output: Optional[GitHubCheckRunOutput] = Field( - None, title="Output", description="Check run output, if available." - ) - - pull_requests: List[GitHubCheckRunPrInfoModel] = Field( - default_factory=list - ) diff --git a/src/timessquare/domain/githubcheckout.py b/src/timessquare/domain/githubcheckout.py index 04fc4fc1..9d4ef206 100644 --- a/src/timessquare/domain/githubcheckout.py +++ b/src/timessquare/domain/githubcheckout.py @@ -12,8 +12,8 @@ import yaml from gidgethub.httpx import GitHubAPI from pydantic import BaseModel, EmailStr, Field, HttpUrl, root_validator +from safir.github.models import GitHubBlobModel, GitHubRepositoryModel -from .githubapi import GitHubBlobModel, GitHubRepositoryModel from .page import PageParameterSchema, PersonModel diff --git a/src/timessquare/domain/githubcheckrun.py b/src/timessquare/domain/githubcheckrun.py index 82327eb1..270a6a95 100644 --- a/src/timessquare/domain/githubcheckrun.py +++ b/src/timessquare/domain/githubcheckrun.py @@ -9,10 +9,7 @@ from gidgethub.httpx import GitHubAPI from pydantic import ValidationError - -from timessquare.config import config - -from .githubapi import ( +from safir.github.models import ( GitHubBlobModel, GitHubCheckRunAnnotationLevel, GitHubCheckRunConclusion, @@ -20,6 +17,9 @@ GitHubCheckRunStatus, GitHubRepositoryModel, ) + +from timessquare.config import config + from .githubcheckout import ( GitHubRepositoryCheckout, NotebookSidecarFile, diff --git a/src/timessquare/domain/githubwebhook.py b/src/timessquare/domain/githubwebhook.py deleted file mode 100644 index 79e38138..00000000 --- a/src/timessquare/domain/githubwebhook.py +++ /dev/null @@ -1,166 +0,0 @@ -"""Domain models related to payloads from GitHub webhook events. - -These Pydantic models are designed to capture relevant subsets of data from -GitHub webhook payloads. -""" - -from __future__ import annotations - -from typing import List - -from pydantic import BaseModel, Field - -from .githubapi import ( - GitHubCheckRunModel, - GitHubCheckSuiteModel, - GitHubPullRequestModel, - GitHubRepositoryModel, -) - - -class GitHubAppInstallationModel(BaseModel): - """A Pydantic model for the "installation" field found in webhook payloads - for GitHub Apps. - """ - - id: str = Field(title="Installation ID") - - -class GitHubPushEventModel(BaseModel): - """A Pydantic model for the push event webhook.""" - - repository: GitHubRepositoryModel - - installation: GitHubAppInstallationModel - - ref: str = Field( - title="The full git_ref that was pushed.", - description=( - "The full git ref that was pushed. Example: refs/heads/main or " - "refs/tags/v3.14.1." - ), - example="refs/heads/main", - ) - - before: str = Field( - title="The SHA of the most recent commit on ref before the push." - ) - - after: str = Field( - title="The SHA of the most recent commit on ref after the push." - ) - - -class AppInstallationRepoModel(BaseModel): - """A pydantic model for repository objects used by - `GitHubAppInstallationRepositoriesEventModel`. - """ - - name: str - - full_name: str - - @property - def owner_name(self) -> str: - return self.full_name.split("/")[0] - - -class GitHubAppInstallationEventModel(BaseModel): - """A Pydantic model for an "installation" webhook. - - https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#installation - """ - - action: str = Field( - title="Action performed", description="Either 'added' or 'removed'." - ) - - repositories: List[AppInstallationRepoModel] = Field( - title="Repositories accessible to this installation" - ) - - installation: GitHubAppInstallationModel - - -class GitHubAppInstallationRepositoriesEventModel(BaseModel): - """A Pydantic model for a "installation_repositories" webhook. - - https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#installation_repositories - """ - - action: str = Field( - title="Action performed", description="Either 'added' or 'removed'." - ) - - repositories_added: List[AppInstallationRepoModel] = Field( - title="Repositories added" - ) - - repositories_removed: List[AppInstallationRepoModel] = Field( - title="Repositories removed" - ) - - installation: GitHubAppInstallationModel - - -class GitHubPullRequestEventModel(BaseModel): - """A Pydantic model for a "pull_request" webhook. - - https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#pull_request - """ - - repository: GitHubRepositoryModel - - installation: GitHubAppInstallationModel - - action: str = Field( - title="The action that was performed.", - description=( - "Many event types are possible. The most relevant to Times Square " - "are ``opened`` and ``synchronize`` (when the head branch is " - "updated)." - ), - ) - - number: int = Field(title="Pull request number") - - pull_request: GitHubPullRequestModel - - -class GitHubCheckSuiteEventModel(BaseModel): - """A Pydantic model for the "check_suite" webhook payload. - - https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#check_suite - """ - - action: str = Field( - title="Action performed", - description="Either requested or rerequested.", - ) - - check_suite: GitHubCheckSuiteModel - - repository: GitHubRepositoryModel - - installation: GitHubAppInstallationModel - - -class GitHubCheckRunEventModel(BaseModel): - """A Pydantic model for the "check_run" webhook payload. - - https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#check_run - """ - - action: str = Field( - title="The action that was performed.", - description=( - "Many event types are possible: created, completed, rerequested, " - "rerequested_action" - ), - ) - - repository: GitHubRepositoryModel - - installation: GitHubAppInstallationModel - - check_run: GitHubCheckRunModel diff --git a/src/timessquare/domain/noteburst.py b/src/timessquare/domain/noteburst.py index bbe5909d..2402ab57 100644 --- a/src/timessquare/domain/noteburst.py +++ b/src/timessquare/domain/noteburst.py @@ -76,7 +76,6 @@ def to_job_model(self) -> NoteburstJobModel: @dataclass class NoteburstApiResult: - data: Optional[NoteburstJobResponseModel] status_code: int diff --git a/src/timessquare/exceptions.py b/src/timessquare/exceptions.py index c3c47b01..12946d12 100644 --- a/src/timessquare/exceptions.py +++ b/src/timessquare/exceptions.py @@ -35,7 +35,6 @@ def to_dict(self) -> Dict[str, Union[List[str], str]]: class PageNotFoundError(TimesSquareError): - error = "page_not_found" status_code = 404 diff --git a/src/timessquare/handlers/external/__init__.py b/src/timessquare/handlers/external/__init__.py new file mode 100644 index 00000000..0c003247 --- /dev/null +++ b/src/timessquare/handlers/external/__init__.py @@ -0,0 +1,5 @@ +"""Base externally-facing API handlers.""" + +from .endpoints import external_router + +__all__ = ["external_router"] diff --git a/src/timessquare/handlers/external.py b/src/timessquare/handlers/external/endpoints.py similarity index 74% rename from src/timessquare/handlers/external.py rename to src/timessquare/handlers/external/endpoints.py index 989da6a7..e292de27 100644 --- a/src/timessquare/handlers/external.py +++ b/src/timessquare/handlers/external/endpoints.py @@ -1,39 +1,29 @@ -"""Handlers for the app's external root, ``/timessquare/``.""" +"""Handlers for the app's external root, ``/times-square/``.""" from __future__ import annotations import asyncio -import httpx from fastapi import APIRouter, Depends, Request, Response, status from gidgethub.sansio import Event -from pydantic import AnyHttpUrl, BaseModel, Field -from safir.dependencies.arq import ArqQueue, arq_dependency -from safir.dependencies.http_client import http_client_dependency +from pydantic import AnyHttpUrl +from safir.arq import ArqQueue +from safir.dependencies.arq import arq_dependency from safir.dependencies.logger import logger_dependency -from safir.metadata import Metadata as SafirMetadata from safir.metadata import get_metadata from structlog.stdlib import BoundLogger from timessquare.config import config -from timessquare.services.github.webhooks import router as webhook_router -__all__ = ["get_index", "external_router", "Index", "post_github_webhook"] +from .githubwebhooks import router as webhook_router +from .models import Index + +__all__ = ["get_index", "external_router", "post_github_webhook"] external_router = APIRouter() """FastAPI router for all external handlers.""" -class Index(BaseModel): - """Metadata returned by the external root URL of the application.""" - - metadata: SafirMetadata = Field(..., title="Package metadata") - - v1_api_base: AnyHttpUrl = Field(..., title="Base URL for the v1 REST API") - - api_docs: AnyHttpUrl = Field(..., tile="API documentation URL") - - @external_router.get( "/", response_model=Index, @@ -59,7 +49,9 @@ async def get_index( v1_api_url = f"{request.url}v1" doc_url = request.url.replace(path=f"/{config.name}/redoc") return Index( - metadata=metadata, v1_api_base=v1_api_url, api_docs=str(doc_url) + metadata=metadata, + v1_api_base=AnyHttpUrl(v1_api_url, scheme=request.url.scheme), + api_docs=AnyHttpUrl(str(doc_url), scheme=request.url.scheme), ) @@ -72,7 +64,6 @@ async def get_index( async def post_github_webhook( request: Request, logger: BoundLogger = Depends(logger_dependency), - http_client: httpx.AsyncClient = Depends(http_client_dependency), arq_queue: ArqQueue = Depends(arq_dependency), ) -> Response: """Process GitHub webhook events.""" @@ -98,6 +89,7 @@ async def post_github_webhook( logger = logger.bind(github_delivery=event.delivery_id) logger.debug("Received GitHub webhook", payload=event.data) + # Give GitHub some time to reach internal consistency. await asyncio.sleep(1) await webhook_router.dispatch(event, logger, arq_queue) diff --git a/src/timessquare/services/github/webhooks.py b/src/timessquare/handlers/external/githubwebhooks.py similarity index 96% rename from src/timessquare/services/github/webhooks.py rename to src/timessquare/handlers/external/githubwebhooks.py index 3a670f23..0e96b154 100644 --- a/src/timessquare/services/github/webhooks.py +++ b/src/timessquare/handlers/external/githubwebhooks.py @@ -7,10 +7,7 @@ from gidgethub.routing import Router from gidgethub.sansio import Event from safir.arq import ArqQueue -from structlog.stdlib import BoundLogger - -from timessquare.config import config -from timessquare.domain.githubwebhook import ( +from safir.github.webhooks import ( GitHubAppInstallationEventModel, GitHubAppInstallationRepositoriesEventModel, GitHubCheckRunEventModel, @@ -18,8 +15,26 @@ GitHubPullRequestEventModel, GitHubPushEventModel, ) +from structlog.stdlib import BoundLogger + +from timessquare.config import config -__all__ = ["router"] +__all__ = [ + "router", + "handle_installation_created", + "handle_installation_unsuspend", + "handle_installation_deleted", + "handle_installation_suspend", + "handle_repositories_added", + "handle_repositories_removed", + "handle_check_run_created", + "handle_check_run_rerequested", + "handle_check_suite_request", + "handle_pr_opened", + "handle_pr_sync", + "handle_push_event", + "handle_ping", +] router = Router() diff --git a/src/timessquare/handlers/external/models.py b/src/timessquare/handlers/external/models.py new file mode 100644 index 00000000..328a0284 --- /dev/null +++ b/src/timessquare/handlers/external/models.py @@ -0,0 +1,16 @@ +"""Models for the external handlers.""" + +from pydantic import AnyHttpUrl, BaseModel, Field +from safir.metadata import Metadata as SafirMetadata + +__all__ = ["Index"] + + +class Index(BaseModel): + """Metadata returned by the external root URL of the application.""" + + metadata: SafirMetadata = Field(..., title="Package metadata") + + v1_api_base: AnyHttpUrl = Field(..., title="Base URL for the v1 REST API") + + api_docs: AnyHttpUrl = Field(..., tile="API documentation URL") diff --git a/src/timessquare/handlers/v1/__init__.py b/src/timessquare/handlers/v1/__init__.py index aee6b580..cdb6ae41 100644 --- a/src/timessquare/handlers/v1/__init__.py +++ b/src/timessquare/handlers/v1/__init__.py @@ -1,3 +1,3 @@ -from .handlers import v1_router +from .endpoints import v1_router __all__ = ["v1_router"] diff --git a/src/timessquare/handlers/v1/handlers.py b/src/timessquare/handlers/v1/endpoints.py similarity index 94% rename from src/timessquare/handlers/v1/handlers.py rename to src/timessquare/handlers/v1/endpoints.py index 8dd547c9..5c52a38b 100644 --- a/src/timessquare/handlers/v1/handlers.py +++ b/src/timessquare/handlers/v1/endpoints.py @@ -4,6 +4,7 @@ from fastapi import APIRouter, Depends, HTTPException, Path, Request from fastapi.responses import HTMLResponse, PlainTextResponse +from pydantic import AnyHttpUrl from safir.metadata import get_metadata from timessquare.config import config @@ -85,7 +86,10 @@ async def get_index( application_name=config.name, ) doc_url = request.url.replace(path=f"/{config.name}/docs") - return Index(metadata=metadata, api_docs=str(doc_url)) + return Index( + metadata=metadata, + api_docs=AnyHttpUrl(str(doc_url), scheme=request.url.scheme), + ) @v1_router.get( @@ -105,8 +109,8 @@ async def get_page( async with context.session.begin(): page_domain = await page_service.get_page(page) - context.response.headers["location"] = context.request.url_for( - "get_page", page=page_domain.name + context.response.headers["location"] = str( + context.request.url_for("get_page", page=page_domain.name) ) return Page.from_domain(page=page_domain, request=context.request) @@ -217,8 +221,8 @@ async def post_page( ) page = await page_service.get_page(page_exec.name) - context.response.headers["location"] = context.request.url_for( - "get_page", page=page_exec.name + context.response.headers["location"] = str( + context.request.url_for("get_page", page=page_exec.name) ) return Page.from_domain(page=page, request=context.request) @@ -240,8 +244,8 @@ async def get_page_source( page_domain = await page_service.get_page(page) response_headers = { - "location": context.request.url_for( - "get_page_source", page=page_domain.name + "location": str( + context.request.url_for("get_page_source", page=page_domain.name) ) } @@ -358,8 +362,8 @@ async def get_github_page( async with context.session.begin(): page_domain = await page_service.get_github_backed_page(display_path) - context.response.headers["location"] = context.request.url_for( - "get_page", page=page_domain.name + context.response.headers["location"] = str( + context.request.url_for("get_page", page=page_domain.name) ) return Page.from_domain(page=page_domain, request=context.request) @@ -437,7 +441,7 @@ async def get_github_pr_page( path=path, ) - context.response.headers["location"] = context.request.url_for( - "get_page", page=page_domain.name + context.response.headers["location"] = str( + context.request.url_for("get_page", page=page_domain.name) ) return Page.from_domain(page=page_domain, request=context.request) diff --git a/src/timessquare/handlers/v1/models.py b/src/timessquare/handlers/v1/models.py index 1fcdf9e6..d28dfd57 100644 --- a/src/timessquare/handlers/v1/models.py +++ b/src/timessquare/handlers/v1/models.py @@ -10,15 +10,15 @@ from fastapi import Request from markdown_it import MarkdownIt from pydantic import AnyHttpUrl, BaseModel, EmailStr, Field, HttpUrl -from safir.metadata import Metadata as SafirMetadata - -from timessquare.domain.githubapi import ( +from safir.github.models import ( GitHubCheckRunConclusion, GitHubCheckRunModel, GitHubCheckRunStatus, GitHubPullRequestModel, GitHubPullState, ) +from safir.metadata import Metadata as SafirMetadata + from timessquare.domain.githubtree import GitHubNode, GitHubNodeType from timessquare.domain.nbhtml import NbHtmlModel from timessquare.domain.page import PageModel, PageSummaryModel, PersonModel @@ -55,7 +55,7 @@ class Index(BaseModel): ), ) -page_cache_ttl_field = Field( +page_cache_ttl_field: int | None = Field( None, example=864000, title="Page title", @@ -214,10 +214,13 @@ class GitHubSourceMetadata(BaseModel): @classmethod def from_domain(cls, *, page: PageModel) -> GitHubSourceMetadata: + # Assertions are are to help mypy distinguish a GitHub-based page assert page.github_owner is not None assert page.github_repo is not None sidecar_path = page.repository_sidecar_path source_path = page.repository_source_path + assert sidecar_path is not None + assert source_path is not None return cls( owner=page.github_owner, repository=page.github_repo, @@ -303,14 +306,25 @@ def from_domain(cls, *, page: PageModel, request: Request) -> Page: tags=page.tags, uploader_username=page.uploader_username, parameters=parameters, - self_url=request.url_for("get_page", page=page.name), - source_url=request.url_for("get_page_source", page=page.name), - rendered_url=request.url_for( - "get_rendered_notebook", page=page.name + self_url=AnyHttpUrl( + str(request.url_for("get_page", page=page.name)), + scheme=request.url.scheme, + ), + source_url=AnyHttpUrl( + str(request.url_for("get_page_source", page=page.name)), + scheme=request.url.scheme, ), - html_url=request.url_for("get_page_html", page=page.name), - html_status_url=request.url_for( - "get_page_html_status", page=page.name + rendered_url=AnyHttpUrl( + str(request.url_for("get_rendered_notebook", page=page.name)), + scheme=request.url.scheme, + ), + html_url=AnyHttpUrl( + str(request.url_for("get_page_html", page=page.name)), + scheme=request.url.scheme, + ), + html_status_url=AnyHttpUrl( + str(request.url_for("get_page_html_status", page=page.name)), + scheme=request.url.scheme, ), github=github_metadata, ) @@ -333,7 +347,10 @@ def from_domain( return cls( name=summary.name, title=summary.title, - self_url=request.url_for("get_page", page=summary.name), + self_url=AnyHttpUrl( + str(request.url_for("get_page", page=summary.name)), + scheme=request.url.scheme, + ), ) @@ -363,8 +380,8 @@ class HtmlStatus(BaseModel): def from_html( cls, *, html: Optional[NbHtmlModel], request: Request ) -> HtmlStatus: - base_html_url = request.url_for( - "get_page_html", page=request.path_params["page"] + base_html_url = str( + request.url_for("get_page_html", page=request.path_params["page"]) ) if html is None: @@ -375,7 +392,11 @@ def from_html( else: html_url = base_html_url - return cls(available=False, html_url=html_url, html_hash=None) + return cls( + available=False, + html_url=AnyHttpUrl(html_url, scheme=request.url.scheme), + html_hash=None, + ) else: query_params: Dict[str, Any] = {} query_params.update(html.values) @@ -390,7 +411,9 @@ def from_html( else: html_url = base_html_url return cls( - available=True, html_hash=html.html_hash, html_url=html_url + available=True, + html_hash=html.html_hash, + html_url=AnyHttpUrl(html_url, scheme=request.url.scheme), ) diff --git a/src/timessquare/main.py b/src/timessquare/main.py index 86e65a0e..58985b28 100644 --- a/src/timessquare/main.py +++ b/src/timessquare/main.py @@ -18,7 +18,7 @@ from safir.dependencies.arq import arq_dependency from safir.dependencies.db_session import db_session_dependency from safir.dependencies.http_client import http_client_dependency -from safir.logging import configure_logging +from safir.logging import configure_logging, configure_uvicorn_logging from safir.middleware.x_forwarded import XForwardedMiddleware from .config import config @@ -39,6 +39,7 @@ log_level=config.log_level, name=config.logger_name, ) +configure_uvicorn_logging(config.log_level) app = FastAPI( title="Times Square", @@ -51,6 +52,10 @@ ) """The FastAPI application for times-square.""" +# Add middleware +app.add_middleware(XForwardedMiddleware) + +# Add routers app.include_router(internal_router) app.include_router(external_router, prefix=f"{config.path_prefix}") app.include_router(v1_router, prefix=f"{config.path_prefix}/v1") @@ -65,7 +70,6 @@ async def startup_event() -> None: await arq_dependency.initialize( mode=config.arq_mode, redis_settings=config.arq_redis_settings ) - app.add_middleware(XForwardedMiddleware) @app.on_event("shutdown") diff --git a/src/timessquare/services/github/__init__.py b/src/timessquare/services/github/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/timessquare/services/github/client.py b/src/timessquare/services/github/client.py deleted file mode 100644 index b95f594d..00000000 --- a/src/timessquare/services/github/client.py +++ /dev/null @@ -1,128 +0,0 @@ -"""Factories for creating GitHub API clients based on the application -configuration. -""" - -from __future__ import annotations - -from typing import Optional - -import gidgethub.apps -import httpx -from gidgethub.httpx import GitHubAPI - -from timessquare.config import config - -__all__ = [ - "GitHubClientConfigError", - "get_app_jwt", - "create_github_installation_client", -] - - -class GitHubClientConfigError(Exception): - """Raised if there is an error with the GitHub App's configuration.""" - - -def get_app_jwt() -> str: - """Create the GitHub App's JWT based on application configuration. - - This token is for authenticating as the GitHub App itself, as opposed to - an installation of the app. See - https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#authenticating-as-a-github-app - - Parameters - ---------- - http_client : httpx.AsyncClient - The httpx client. - - Returns - ------- - str - The JWT token. - - Raises - ------ - GitHubClientError - Raised if there is an issue with the GitHub App configuration. - """ - if config.github_app_private_key is None: - raise GitHubClientConfigError( - "The GitHub app private key is not configured." - ) - private_key = config.github_app_private_key.get_secret_value() - - if config.github_app_id is None: - raise GitHubClientConfigError("The GitHub app id is not configured.") - app_id = config.github_app_id - - return gidgethub.apps.get_jwt(app_id=app_id, private_key=private_key) - - -def create_github_client( - *, http_client: httpx.AsyncClient, oauth_token: Optional[str] = None -) -> GitHubAPI: - """Create an HTTPx GitHub client. - - Parameters - ---------- - http_client : httpx.AsyncClient - The httpx client. - oauth_token : str, optional - If set, the client is authenticated with the oauth token (common - for clients acting as an app installation or on behalf of a user). - - Returns - ------- - gidgethub.httpx.GitHubAPI - """ - return GitHubAPI( - http_client, "lsst-sqre/times-square", oauth_token=oauth_token - ) - - -async def create_github_installation_client( - *, http_client: httpx.AsyncClient, installation_id: str -) -> GitHubAPI: - """Create a GitHub API client authorized as a GitHub App installation, - with specific permissions on the repository/organization the app is - installed into. - - Parameters - ---------- - http_client : httpx.AsyncClient - The httpx client. - installation_id : str - The installation ID, often obtained from a webhook payload - (``installation.id`` path), or from the ``id`` key returned by - `iter_installations`. - - Returns - ------- - gidgethub.httpx.GitHubAPI - The GitHub client with an embedded OAuth token that authenticates - all requests as the GitHub app installation. - """ - token = get_app_jwt() - - if config.github_app_id is None: - raise GitHubClientConfigError("The GitHub app id is not configured.") - app_id = config.github_app_id - - if config.github_app_private_key is None: - raise GitHubClientConfigError( - "The GitHub app private key is not configured." - ) - private_key = config.github_app_private_key.get_secret_value() - - anon_gh_app = create_github_client(http_client=http_client) - token_info = await gidgethub.apps.get_installation_access_token( - anon_gh_app, - installation_id=installation_id, - app_id=app_id, - private_key=private_key, - ) - token = token_info["token"] - - # Generate a new client with the embedded OAuth token. - gh = create_github_client(http_client=http_client, oauth_token=token) - return gh diff --git a/src/timessquare/services/github/repo.py b/src/timessquare/services/githubrepo.py similarity index 89% rename from src/timessquare/services/github/repo.py rename to src/timessquare/services/githubrepo.py index 835b6fa1..086b5457 100644 --- a/src/timessquare/services/github/repo.py +++ b/src/timessquare/services/githubrepo.py @@ -13,15 +13,24 @@ from gidgethub.httpx import GitHubAPI from httpx import AsyncClient -from structlog.stdlib import BoundLogger - -from timessquare.domain.githubapi import ( +from safir.github import GitHubAppClientFactory +from safir.github.models import ( GitHubBlobModel, GitHubBranchModel, GitHubCheckRunConclusion, GitHubCheckRunModel, + GitHubPullRequestModel, GitHubRepositoryModel, ) +from safir.github.webhooks import ( + GitHubCheckRunEventModel, + GitHubCheckSuiteEventModel, + GitHubPushEventModel, +) +from safir.slack.blockkit import SlackException +from structlog.stdlib import BoundLogger + +from timessquare.config import config from timessquare.domain.githubcheckout import ( GitHubRepositoryCheckout, RepositoryNotebookModel, @@ -31,21 +40,10 @@ GitHubConfigsCheck, NotebookExecutionsCheck, ) -from timessquare.domain.githubwebhook import ( - GitHubCheckRunEventModel, - GitHubCheckSuiteEventModel, - GitHubPullRequestModel, - GitHubPushEventModel, -) from timessquare.domain.noteburst import NoteburstJobStatus from timessquare.domain.page import PageExecutionInfo, PageModel -from ..page import PageService -from .client import ( - create_github_client, - create_github_installation_client, - get_app_jwt, -) +from .page import PageService class GitHubRepoService: @@ -109,16 +107,21 @@ async def create_for_repo( logger : `BoundLogger` A logger, ideally with request/worker job context already bound. """ - app_jwt = get_app_jwt() - app_client = create_github_client(http_client=http_client) - installation_data = await app_client.getitem( - "/repos/{owner}/{repo}/installation", - url_vars={"owner": owner, "repo": repo}, - jwt=app_jwt, + if not config.github_app_id or not config.github_app_private_key: + raise SlackException( + "github_app_id and github_app_private_key must be set to " + "create the GitHubRepoService." + ) + github_client_factory = GitHubAppClientFactory( + http_client=http_client, + id=config.github_app_id, + key=config.github_app_private_key.get_secret_value(), + name="lsst-sqre/times-square", ) - installation_id = installation_data["id"] - installation_client = await create_github_installation_client( - http_client=http_client, installation_id=installation_id + installation_client = ( + await github_client_factory.create_installation_client_for_repo( + owner=owner, repo=repo + ) ) return cls( http_client=http_client, @@ -219,6 +222,7 @@ async def sync_checkout( different. 2. If new, create the page. 3. If changed, modify the existing page + 4. If disabled, mark the page for deletion. 3. Delete any pages not found in the repository checkout. """ @@ -259,19 +263,41 @@ async def sync_checkout( or notebook.sidecar_git_tree_sha != page.repository_sidecar_sha ): - self._logger.debug( - "Notebook content has updated", - display_path=display_path, - ) - await self.update_page( - notebook=notebook, page=existing_pages[display_path] - ) + if notebook.sidecar.enabled is False: + self._logger.debug( + "Notebook is disabled. Dropping from update.", + display_path=display_path, + ) + try: + found_display_paths.remove(display_path) + except ValueError: + self._logger.debug( + "Tried to delete existing page, now disabled, " + "but it was not in found_display_paths.", + display_path=display_path, + found_display_paths=found_display_paths, + ) + else: + self._logger.debug( + "Notebook content has updated", + display_path=display_path, + ) + await self.update_page( + notebook=notebook, + page=existing_pages[display_path], + ) else: self._logger.debug( "Notebook content is the same; skipping", display_path=display_path, ) else: + if notebook.sidecar.enabled is False: + self._logger.debug( + "Notebook is disabled. Skipping", + display_path=display_path, + ) + continue # add new page self._logger.debug( "Creating new page for notebook", display_path=display_path @@ -476,6 +502,12 @@ async def run_notebook_check_run( notebook = await checkout.load_notebook( notebook_ref=notebook_ref, github_client=self._github_client ) + if notebook.sidecar.enabled is False: + self._logger.debug( + "Skipping notebook execution check for disabled notebook", + path=notebook_ref.notebook_source_path, + ) + continue page = await self.create_page( checkout=checkout, notebook=notebook, diff --git a/src/timessquare/services/page.py b/src/timessquare/services/page.py index 6f95c64a..a2d375fb 100644 --- a/src/timessquare/services/page.py +++ b/src/timessquare/services/page.py @@ -292,7 +292,7 @@ async def get_html( values=resolved_values, display_settings=display_settings, ) - nbhtml = await self._html_store.get(page_key) + nbhtml = await self._html_store.get_instance(page_key) if nbhtml is not None: self._logger.debug("Got HTML from cache") return nbhtml @@ -333,7 +333,7 @@ async def _get_html_from_noteburst_job( not presently available. """ # Is there an existing job in the noteburst job store? - job = await self._job_store.get(page_instance) + job = await self._job_store.get_instance(page_instance) if not job: self._logger.debug("No existing noteburst job available") # A record of a noteburst job is not available. Send a request @@ -370,7 +370,7 @@ async def _get_html_from_noteburst_job( self._logger.warning( "Got a 404 from a noteburst job", job_url=job.job_url ) - await self._job_store.delete(page_instance) + await self._job_store.delete_instance(page_instance) await self.request_noteburst_execution(page_instance) else: # server error from noteburst @@ -456,7 +456,7 @@ async def _create_html_matrix( "Stored new HTML", display_settings=asdict(matrix_key) ) - await self._job_store.delete(page_instance) + await self._job_store.delete_instance(page_instance) self._logger.debug("Deleted old job record") return html_matrix diff --git a/src/timessquare/storage/nbhtmlcache.py b/src/timessquare/storage/nbhtmlcache.py index 100724e5..fdb9386a 100644 --- a/src/timessquare/storage/nbhtmlcache.py +++ b/src/timessquare/storage/nbhtmlcache.py @@ -4,22 +4,24 @@ from typing import Optional -import aioredis +from redis.asyncio import Redis from timessquare.domain.nbhtml import NbHtmlModel -from .redisbase import RedisStore +from .redisbase import RedisPageInstanceStore +__all__ = ["NbHtmlCacheStore"] -class NbHtmlCacheStore(RedisStore[NbHtmlModel]): + +class NbHtmlCacheStore(RedisPageInstanceStore[NbHtmlModel]): """Manages the storage of HTML renderings of notebooks. The domain is `timessquare.domain.nbhtml.NbHtmlModel`. """ - def __init__(self, redis: aioredis.Redis) -> None: + def __init__(self, redis: Redis) -> None: super().__init__( - redis=redis, key_prefix="nbhtml", datatype=NbHtmlModel + redis=redis, key_prefix="nbhtml/", datatype=NbHtmlModel ) async def store_nbhtml( @@ -29,11 +31,11 @@ async def store_nbhtml( Parameters ---------- - nbhtml : `timessquare.domain.nbhtml.NbHtmlModel` + nbhtml The HTML page domain model. - lifetime : int, optional + lifetime The lifetime for the record in seconds. `None` to cache the record indefinitely. """ key = nbhtml.create_key() - await super().store(key, nbhtml, lifetime=lifetime) + await super().store_instance(key, nbhtml, lifetime=lifetime) diff --git a/src/timessquare/storage/noteburstjobstore.py b/src/timessquare/storage/noteburstjobstore.py index 77fd1269..0c3b3389 100644 --- a/src/timessquare/storage/noteburstjobstore.py +++ b/src/timessquare/storage/noteburstjobstore.py @@ -2,15 +2,15 @@ from __future__ import annotations -import aioredis +from redis.asyncio import Redis from timessquare.domain.noteburst import NoteburstJobModel from timessquare.domain.page import PageInstanceIdModel -from .redisbase import RedisStore +from .redisbase import RedisPageInstanceStore -class NoteburstJobStore(RedisStore[NoteburstJobModel]): +class NoteburstJobStore(RedisPageInstanceStore[NoteburstJobModel]): """The noteburst job store keeps track of open notebook execution job requests for a given page and set of parameters. @@ -18,9 +18,9 @@ class NoteburstJobStore(RedisStore[NoteburstJobModel]): `timessquare.domain.noteburst.NoteburstJobModel`. """ - def __init__(self, redis: aioredis.Redis) -> None: + def __init__(self, redis: Redis) -> None: super().__init__( - redis=redis, key_prefix="noteburst", datatype=NoteburstJobModel + redis=redis, key_prefix="noteburst/", datatype=NoteburstJobModel ) async def store_job( @@ -34,14 +34,14 @@ async def store_job( Parameters ---------- - job : `timessquare.domain.noteburst.NoteburstJobModel` + job The job record. - page_id : `timessquare.domain.page.PageInstanceIdModel` + page_id Identifier of the page instance, composed of the page's name and the values the page instance is rendered with. - lifetime : int + lifetime The lifetime of the record, in seconds. The lifetime should be set so that if it elapses, it can be assumed that noteburst has failed to process the original job and that a new request can be sent. """ - await super().store(page_id, job, lifetime=lifetime) + await super().store_instance(page_id, job, lifetime=lifetime) diff --git a/src/timessquare/storage/page.py b/src/timessquare/storage/page.py index fbafa830..c909d0b9 100644 --- a/src/timessquare/storage/page.py +++ b/src/timessquare/storage/page.py @@ -266,6 +266,10 @@ async def get_github_tree(self) -> List[GitHubNode]: nodes: List[GitHubNode] = [] for owner_name in result.scalars(): + if owner_name is None: + # This is a page that's not backed by GitHub; should already + # be filtered out by the query above, but for typing. + continue node = await self._generate_node_for_owner(owner_name) nodes.append(node) diff --git a/src/timessquare/storage/redisbase.py b/src/timessquare/storage/redisbase.py index f810f1db..ec10e688 100644 --- a/src/timessquare/storage/redisbase.py +++ b/src/timessquare/storage/redisbase.py @@ -1,66 +1,55 @@ -""""Base functionality for redis storage.""" +""""Base for Redis page instance cache storage.""" from __future__ import annotations -from typing import AsyncIterable, Generic, Optional, Type, TypeVar +from typing import AsyncIterable, Optional -import aioredis -from pydantic import BaseModel +from safir.redis import PydanticRedisStorage, S from timessquare.domain.page import PageInstanceIdModel -T = TypeVar("T", bound="BaseModel") +__all__ = ["RedisPageInstanceStore"] -class RedisStore(Generic[T]): - """A base class for Redis-based storage of Pydantic models as JSON. +class RedisPageInstanceStore(PydanticRedisStorage[S]): + """A base class for Redis-based storage of page-instance-related Pydantic + models as JSON. Parameters ---------- - redis : `aioredis.Redis` + datatype + The class of Pydantic model to store. + redis The Redis client. - key_prefix : `str` + key_prefix The prefix for any data stored in Redis. - datatype : `pydantic.BaseModel` - type - The pydantic class of object stored through this RedisStore. """ - def __init__( - self, - *, - redis: aioredis.Redis, - key_prefix: str, - datatype: Type[T], - ) -> None: - self._redis = redis - self._key_prefix = key_prefix - self._datatype = datatype - def calculate_redis_key(self, page_id: PageInstanceIdModel) -> str: """Create the redis key for given the page's name and - parameter values with a datastore's redis key prefix. + parameter values. Parameters ---------- - page_id : `timessquare.domain.page.PageInstanceIdModel` + page_id Identifier of the page instance, composed of the page's name and the values the page instance is rendered with. Returns ------- - key : `str` + str The unique redis key for this combination of page name and parameter values for a given datastore. """ - return f"{self._key_prefix}/{page_id.cache_key}" + return page_id.cache_key - async def store( + async def store_instance( self, page_id: PageInstanceIdModel, - data: T, + data: S, lifetime: Optional[int] = None, ) -> None: - """Store a pydantic object to Redis. + """Store a pydantic object for a page instance. The data is persisted in Redis as a JSON string. @@ -77,78 +66,57 @@ async def store( `None`, the data is persisted forever. """ key = self.calculate_redis_key(page_id) - serialized_data = data.json() - await self._redis.set(key, serialized_data, ex=lifetime) + await super().store(key, data, lifetime=lifetime) - async def get(self, page_id: PageInstanceIdModel) -> Optional[T]: + async def get_instance(self, page_id: PageInstanceIdModel) -> S | None: """Get the data stored for a page instance, deserializing it into the Pydantic model type. Parameters ---------- - page_id : `timessquare.domain.page.PageInstanceIdModel` + page_id Identifier of the page instance, composed of the page's name and the values the page instance is rendered with. Returns ------- - data : `pydantic.BaseModel`, optional + pydantic.BaseModel | None The dataset, as a Pydantic model. If the dataset is not found at the key, `None` is returned. """ key = self.calculate_redis_key(page_id) - serialized_data = await self._redis.get(key) - if not serialized_data: - return None - - return self._datatype.parse_raw(serialized_data.decode()) + return await super().get(key) async def iter_keys_for_page(self, page_name: str) -> AsyncIterable[str]: """Iterate over all keys for a page. Parameters ---------- - page_name : str + page_name The name of the page (corresponds to `timessquare.domain.page.PageModel.name`). Yields ------ - key : str + str Yields keys for a page. """ - pattern = f"{self._key_prefix}/{page_name}/*" - async for key in self._redis.scan_iter(pattern): + pattern = f"{page_name}/*" + async for key in super().scan(pattern): yield key - async def delete(self, page_id: PageInstanceIdModel) -> bool: + async def delete_instance(self, page_id: PageInstanceIdModel) -> bool: """Delete a dataset for a specific page instance. Parameters ---------- - key : `str` + key The key where the data is stored. Returns ------- - deleted : bool + bool `True` if a record was deleted, `False` otherwise. """ key = self.calculate_redis_key(page_id) - count = await self._redis.delete(key) - return count > 0 - - async def delete_all(self) -> int: - """Delete all records with the store's key prefix. - - Returns - ------- - count : `int` - The number of records deleted. - """ - pattern = f"{self._key_prefix}/*" - count = 0 - async for key in self._redis.scan_iter(pattern): - await self._redis.delete(key) - count += 1 - return count > 0 + return await super().delete(key) diff --git a/src/timessquare/worker/functions/compute_check_run.py b/src/timessquare/worker/functions/compute_check_run.py index 18af1455..18169af8 100644 --- a/src/timessquare/worker/functions/compute_check_run.py +++ b/src/timessquare/worker/functions/compute_check_run.py @@ -2,7 +2,7 @@ from typing import Any, Dict -from timessquare.domain.githubwebhook import GitHubCheckRunEventModel +from safir.github.webhooks import GitHubCheckRunEventModel async def compute_check_run( diff --git a/src/timessquare/worker/functions/create_check_run.py b/src/timessquare/worker/functions/create_check_run.py index 96f0816f..fc9cbab4 100644 --- a/src/timessquare/worker/functions/create_check_run.py +++ b/src/timessquare/worker/functions/create_check_run.py @@ -3,8 +3,8 @@ from typing import Any, Dict from safir.dependencies.db_session import db_session_dependency +from safir.github.webhooks import GitHubCheckSuiteEventModel -from timessquare.domain.githubwebhook import GitHubCheckSuiteEventModel from timessquare.worker.servicefactory import create_github_repo_service diff --git a/src/timessquare/worker/functions/create_rerequested_check_run.py b/src/timessquare/worker/functions/create_rerequested_check_run.py index 93e2f473..d65dde18 100644 --- a/src/timessquare/worker/functions/create_rerequested_check_run.py +++ b/src/timessquare/worker/functions/create_rerequested_check_run.py @@ -3,8 +3,8 @@ from typing import Any, Dict from safir.dependencies.db_session import db_session_dependency +from safir.github.webhooks import GitHubCheckRunEventModel -from timessquare.domain.githubwebhook import GitHubCheckRunEventModel from timessquare.worker.servicefactory import create_github_repo_service diff --git a/src/timessquare/worker/functions/pull_request_sync.py b/src/timessquare/worker/functions/pull_request_sync.py index aa25836c..9dfae3ef 100644 --- a/src/timessquare/worker/functions/pull_request_sync.py +++ b/src/timessquare/worker/functions/pull_request_sync.py @@ -3,8 +3,8 @@ from typing import Any, Dict from safir.dependencies.db_session import db_session_dependency +from safir.github.webhooks import GitHubPullRequestEventModel -from timessquare.domain.githubwebhook import GitHubPullRequestEventModel from timessquare.worker.servicefactory import create_github_repo_service diff --git a/src/timessquare/worker/functions/repo_added.py b/src/timessquare/worker/functions/repo_added.py index 8cf0ba15..3ba9bea9 100644 --- a/src/timessquare/worker/functions/repo_added.py +++ b/src/timessquare/worker/functions/repo_added.py @@ -3,12 +3,12 @@ from typing import Any, Dict, Union from safir.dependencies.db_session import db_session_dependency - -from timessquare.domain.githubwebhook import ( - AppInstallationRepoModel, +from safir.github.webhooks import ( GitHubAppInstallationEventModel, + GitHubAppInstallationEventRepoModel, GitHubAppInstallationRepositoriesEventModel, ) + from timessquare.worker.servicefactory import create_github_repo_service @@ -19,7 +19,7 @@ async def repo_added( GitHubAppInstallationRepositoriesEventModel, GitHubAppInstallationEventModel, ], - repo: AppInstallationRepoModel, + repo: GitHubAppInstallationEventRepoModel, ) -> str: """Process repo_added queue tasks, triggered by Times Square app installation events on GitHub. diff --git a/src/timessquare/worker/functions/repo_push.py b/src/timessquare/worker/functions/repo_push.py index 2e94b402..3dbe74f5 100644 --- a/src/timessquare/worker/functions/repo_push.py +++ b/src/timessquare/worker/functions/repo_push.py @@ -3,8 +3,8 @@ from typing import Any, Dict from safir.dependencies.db_session import db_session_dependency +from safir.github.webhooks import GitHubPushEventModel -from timessquare.domain.githubwebhook import GitHubPushEventModel from timessquare.worker.servicefactory import create_github_repo_service diff --git a/src/timessquare/worker/functions/repo_removed.py b/src/timessquare/worker/functions/repo_removed.py index 15ebf122..486c08f4 100644 --- a/src/timessquare/worker/functions/repo_removed.py +++ b/src/timessquare/worker/functions/repo_removed.py @@ -3,12 +3,12 @@ from typing import Any, Dict, Union from safir.dependencies.db_session import db_session_dependency - -from timessquare.domain.githubwebhook import ( - AppInstallationRepoModel, +from safir.github.webhooks import ( GitHubAppInstallationEventModel, + GitHubAppInstallationEventRepoModel, GitHubAppInstallationRepositoriesEventModel, ) + from timessquare.worker.servicefactory import create_page_service @@ -19,7 +19,7 @@ async def repo_removed( GitHubAppInstallationRepositoriesEventModel, GitHubAppInstallationEventModel, ], - repo: AppInstallationRepoModel, + repo: GitHubAppInstallationEventRepoModel, ) -> str: """Process repo_removed queue tasks, triggered by Times Square app installation events on GitHub. diff --git a/src/timessquare/worker/servicefactory.py b/src/timessquare/worker/servicefactory.py index 08bc5513..46cb4b97 100644 --- a/src/timessquare/worker/servicefactory.py +++ b/src/timessquare/worker/servicefactory.py @@ -1,14 +1,14 @@ from __future__ import annotations import httpx +from safir.github import GitHubAppClientFactory +from safir.slack.blockkit import SlackException from sqlalchemy.ext.asyncio import async_scoped_session from structlog.stdlib import BoundLogger +from timessquare.config import config from timessquare.dependencies.redis import redis_dependency -from timessquare.services.github.client import ( - create_github_installation_client, -) -from timessquare.services.github.repo import GitHubRepoService +from timessquare.services.githubrepo import GitHubRepoService from timessquare.services.page import PageService from timessquare.storage.nbhtmlcache import NbHtmlCacheStore from timessquare.storage.noteburstjobstore import NoteburstJobStore @@ -23,9 +23,19 @@ async def create_github_repo_service( installation_id: str, ) -> GitHubRepoService: """Create a GitHubRepoService for arq tasks.""" - github_client = await create_github_installation_client( + if not config.github_app_id or not config.github_app_private_key: + raise SlackException( + "github_app_id and github_app_private_key must be set to " + "create the GitHubRepoService." + ) + github_client_factory = GitHubAppClientFactory( http_client=http_client, - installation_id=installation_id, + id=config.github_app_id, + key=config.github_app_private_key.get_secret_value(), + name="lsst-sqre/times-square", + ) + github_client = await github_client_factory.create_installation_client( + installation_id=installation_id ) page_service = await create_page_service( diff --git a/tests/domain/githubcheckout_test.py b/tests/domain/githubcheckout_test.py index daaa22a5..fd580ef7 100644 --- a/tests/domain/githubcheckout_test.py +++ b/tests/domain/githubcheckout_test.py @@ -10,8 +10,8 @@ import respx from gidgethub.httpx import GitHubAPI from httpx import Response +from safir.github.models import GitHubBlobModel -from timessquare.domain.githubapi import GitHubBlobModel from timessquare.domain.githubcheckout import ( GitHubRepositoryCheckout, GitTreeMode, diff --git a/tests/domain/githubwebhook_test.py b/tests/domain/githubwebhook_test.py deleted file mode 100644 index 182cb7a2..00000000 --- a/tests/domain/githubwebhook_test.py +++ /dev/null @@ -1,101 +0,0 @@ -"""Tests for Github webhook domain models.""" - -from __future__ import annotations - -from pathlib import Path - -from timessquare.domain.githubapi import ( - GitHubCheckRunStatus, - GitHubCheckSuiteConclusion, - GitHubCheckSuiteStatus, -) -from timessquare.domain.githubwebhook import ( - GitHubAppInstallationEventModel, - GitHubAppInstallationRepositoriesEventModel, - GitHubCheckRunEventModel, - GitHubCheckSuiteEventModel, - GitHubPullRequestEventModel, - GitHubPushEventModel, -) - - -def test_push_event() -> None: - data_path = Path(__file__).parent.joinpath( - "../data/github_webhooks/push_event.json" - ) - data = GitHubPushEventModel.parse_raw(data_path.read_text()) - - assert data.ref == "refs/tags/simple-tag" - assert data.repository.name == "Hello-World" - - -def test_installation_event() -> None: - data_path = Path(__file__).parent.joinpath( - "../data/github_webhooks/installation.json" - ) - data = GitHubAppInstallationEventModel.parse_raw(data_path.read_text()) - - assert data.action == "deleted" - assert data.repositories[0].name == "Hello-World" - assert data.repositories[0].owner_name == "octocat" - - -def test_installation_repositories_event() -> None: - data_path = Path(__file__).parent.joinpath( - "../data/github_webhooks/installation_repositories.json" - ) - data = GitHubAppInstallationRepositoriesEventModel.parse_raw( - data_path.read_text() - ) - - assert data.action == "added" - assert data.repositories_added[0].name == "Space" - assert data.repositories_added[0].owner_name == "Codertocat" - - -def test_pull_request_event() -> None: - data_path = Path(__file__).parent.joinpath( - "../data/github_webhooks/pull_request_event.json" - ) - data = GitHubPullRequestEventModel.parse_raw(data_path.read_text()) - - assert data.number == 2 - assert data.action == "opened" - assert data.pull_request.number == 2 - assert data.pull_request.title == "Update the README with new information." - - -def test_check_suite_completed_event() -> None: - data_path = Path(__file__).parent.joinpath( - "../data/github_webhooks/check_suite_completed.json" - ) - data = GitHubCheckSuiteEventModel.parse_raw(data_path.read_text()) - - assert data.action == "completed" - assert data.check_suite.id == "118578147" - assert data.check_suite.head_branch == "changes" - assert data.check_suite.head_sha == ( - "ec26c3e57ca3a959ca5aad62de7213c562f8c821" - ) - assert data.check_suite.status == GitHubCheckSuiteStatus.completed - assert data.check_suite.conclusion == GitHubCheckSuiteConclusion.success - - -def test_check_run_created_event() -> None: - data_path = Path(__file__).parent.joinpath( - "../data/github_webhooks/check_run_created.json" - ) - data = GitHubCheckRunEventModel.parse_raw(data_path.read_text()) - - assert data.action == "created" - assert data.check_run.id == "128620228" - assert data.check_run.external_id == "" - assert data.check_run.url == ( - "https://api.github.com/repos/Codertocat/Hello-World" - "/check-runs/128620228" - ) - assert data.check_run.html_url == ( - "https://github.com/Codertocat/Hello-World/runs/128620228" - ) - assert data.check_run.status == GitHubCheckRunStatus.queued - assert data.check_run.check_suite.id == "118578147" diff --git a/tests/handlers/v1/github_test.py b/tests/handlers/v1/github_test.py index 30ee30b5..db9bb16d 100644 --- a/tests/handlers/v1/github_test.py +++ b/tests/handlers/v1/github_test.py @@ -4,8 +4,8 @@ from pathlib import Path import pytest -from aioredis import Redis from httpx import AsyncClient +from redis.asyncio import Redis from safir.database import create_async_session, create_database_engine from structlog import get_logger diff --git a/tox.ini b/tox.ini index a2943985..5dcc40a7 100644 --- a/tox.ini +++ b/tox.ini @@ -71,7 +71,7 @@ commands = coverage report [testenv:typing] description = Run mypy. commands = - mypy src/timessquare tests setup.py + mypy src/timessquare tests [testenv:lint] description = Lint codebase by running pre-commit (Black, isort, Flake8).