From 2255fc26b54840521c9fea6289c2388db41c3f44 Mon Sep 17 00:00:00 2001 From: Thu Pham Date: Thu, 19 Sep 2024 09:53:37 -0700 Subject: [PATCH 01/29] Upgrade greatexpections v1.0.0 and fix unit tests --- poetry.lock | 1318 ++--------------------------- pyproject.toml | 2 +- tests/agent/conftest.py | 23 +- tests/agent/test_agent.py | 89 +- tests/agent/test_event_handler.py | 18 +- 5 files changed, 126 insertions(+), 1324 deletions(-) diff --git a/poetry.lock b/poetry.lock index 45deb9f8..9492ea08 100644 --- a/poetry.lock +++ b/poetry.lock @@ -36,28 +36,6 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} -[[package]] -name = "anyio" -version = "4.4.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] - [[package]] name = "appnope" version = "0.1.4" @@ -69,82 +47,6 @@ files = [ {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, ] -[[package]] -name = "argon2-cffi" -version = "23.1.0" -description = "Argon2 for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, - {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, -] - -[package.dependencies] -argon2-cffi-bindings = "*" - -[package.extras] -dev = ["argon2-cffi[tests,typing]", "tox (>4)"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] -tests = ["hypothesis", "pytest"] -typing = ["mypy"] - -[[package]] -name = "argon2-cffi-bindings" -version = "21.2.0" -description = "Low-level CFFI bindings for Argon2" -optional = false -python-versions = ">=3.6" -files = [ - {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, - {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, -] - -[package.dependencies] -cffi = ">=1.0.1" - -[package.extras] -dev = ["cogapp", "pre-commit", "pytest", "wheel"] -tests = ["pytest"] - -[[package]] -name = "arrow" -version = "1.3.0" -description = "Better dates & times for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, - {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, -] - -[package.dependencies] -python-dateutil = ">=2.7.0" -types-python-dateutil = ">=2.8.10" - -[package.extras] -doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] -test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] - [[package]] name = "asn1crypto" version = "1.5.1" @@ -174,20 +76,6 @@ six = ">=1.12.0" astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] -[[package]] -name = "async-lru" -version = "2.0.4" -description = "Simple LRU cache for asyncio" -optional = false -python-versions = ">=3.8" -files = [ - {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"}, - {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} - [[package]] name = "attrs" version = "24.2.0" @@ -207,23 +95,6 @@ docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphi tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] -[[package]] -name = "babel" -version = "2.16.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.8" -files = [ - {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, - {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, -] - -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} - -[package.extras] -dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] - [[package]] name = "backcall" version = "0.2.0" @@ -235,6 +106,17 @@ files = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + [[package]] name = "backports-zoneinfo" version = "0.2.1" @@ -263,45 +145,6 @@ files = [ [package.extras] tzdata = ["tzdata"] -[[package]] -name = "beautifulsoup4" -version = "4.12.3" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.6.0" -files = [ - {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, - {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "bleach" -version = "6.1.0" -description = "An easy safelist-based HTML-sanitizing tool." -optional = false -python-versions = ">=3.8" -files = [ - {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, - {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, -] - -[package.dependencies] -six = ">=1.9.0" -webencodings = "*" - -[package.extras] -css = ["tinycss2 (>=1.1.0,<1.3)"] - [[package]] name = "certifi" version = "2024.8.30" @@ -502,20 +345,6 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" @@ -710,37 +539,6 @@ urllib3 = ">=1.26" alembic = ["alembic (>=1.0.11,<2.0.0)", "sqlalchemy (>=2.0.21)"] sqlalchemy = ["sqlalchemy (>=2.0.21)"] -[[package]] -name = "debugpy" -version = "1.8.5" -description = "An implementation of the Debug Adapter Protocol for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "debugpy-1.8.5-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7e4d594367d6407a120b76bdaa03886e9eb652c05ba7f87e37418426ad2079f7"}, - {file = "debugpy-1.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4413b7a3ede757dc33a273a17d685ea2b0c09dbd312cc03f5534a0fd4d40750a"}, - {file = "debugpy-1.8.5-cp310-cp310-win32.whl", hash = "sha256:dd3811bd63632bb25eda6bd73bea8e0521794cda02be41fa3160eb26fc29e7ed"}, - {file = "debugpy-1.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:b78c1250441ce893cb5035dd6f5fc12db968cc07f91cc06996b2087f7cefdd8e"}, - {file = "debugpy-1.8.5-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:606bccba19f7188b6ea9579c8a4f5a5364ecd0bf5a0659c8a5d0e10dcee3032a"}, - {file = "debugpy-1.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db9fb642938a7a609a6c865c32ecd0d795d56c1aaa7a7a5722d77855d5e77f2b"}, - {file = "debugpy-1.8.5-cp311-cp311-win32.whl", hash = "sha256:4fbb3b39ae1aa3e5ad578f37a48a7a303dad9a3d018d369bc9ec629c1cfa7408"}, - {file = "debugpy-1.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:345d6a0206e81eb68b1493ce2fbffd57c3088e2ce4b46592077a943d2b968ca3"}, - {file = "debugpy-1.8.5-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:5b5c770977c8ec6c40c60d6f58cacc7f7fe5a45960363d6974ddb9b62dbee156"}, - {file = "debugpy-1.8.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0a65b00b7cdd2ee0c2cf4c7335fef31e15f1b7056c7fdbce9e90193e1a8c8cb"}, - {file = "debugpy-1.8.5-cp312-cp312-win32.whl", hash = "sha256:c9f7c15ea1da18d2fcc2709e9f3d6de98b69a5b0fff1807fb80bc55f906691f7"}, - {file = "debugpy-1.8.5-cp312-cp312-win_amd64.whl", hash = "sha256:28ced650c974aaf179231668a293ecd5c63c0a671ae6d56b8795ecc5d2f48d3c"}, - {file = "debugpy-1.8.5-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:3df6692351172a42af7558daa5019651f898fc67450bf091335aa8a18fbf6f3a"}, - {file = "debugpy-1.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cd04a73eb2769eb0bfe43f5bfde1215c5923d6924b9b90f94d15f207a402226"}, - {file = "debugpy-1.8.5-cp38-cp38-win32.whl", hash = "sha256:8f913ee8e9fcf9d38a751f56e6de12a297ae7832749d35de26d960f14280750a"}, - {file = "debugpy-1.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:a697beca97dad3780b89a7fb525d5e79f33821a8bc0c06faf1f1289e549743cf"}, - {file = "debugpy-1.8.5-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:0a1029a2869d01cb777216af8c53cda0476875ef02a2b6ff8b2f2c9a4b04176c"}, - {file = "debugpy-1.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84c276489e141ed0b93b0af648eef891546143d6a48f610945416453a8ad406"}, - {file = "debugpy-1.8.5-cp39-cp39-win32.whl", hash = "sha256:ad84b7cde7fd96cf6eea34ff6c4a1b7887e0fe2ea46e099e53234856f9d99a34"}, - {file = "debugpy-1.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:7b0fe36ed9d26cb6836b0a51453653f8f2e347ba7348f2bbfe76bfeb670bfb1c"}, - {file = "debugpy-1.8.5-py2.py3-none-any.whl", hash = "sha256:55919dce65b471eff25901acf82d328bbd5b833526b6c1364bd5133754777a44"}, - {file = "debugpy-1.8.5.zip", hash = "sha256:b2112cfeb34b4507399d298fe7023a16656fc553ed5246536060ca7bd0e668d0"}, -] - [[package]] name = "decorator" version = "5.1.1" @@ -752,17 +550,6 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - [[package]] name = "distlib" version = "0.3.8" @@ -824,20 +611,6 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] -[[package]] -name = "fastjsonschema" -version = "2.20.0" -description = "Fastest Python implementation of JSON schema" -optional = false -python-versions = "*" -files = [ - {file = "fastjsonschema-2.20.0-py3-none-any.whl", hash = "sha256:5875f0b0fa7a0043a91e93a9b8f793bcbbba9691e7fd83dca95c28ba26d21f0a"}, - {file = "fastjsonschema-2.20.0.tar.gz", hash = "sha256:3d48fc5300ee96f5d116f10fe6f28d938e6008f59a6a025c2649475b87f76a23"}, -] - -[package.extras] -devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] - [[package]] name = "filelock" version = "3.16.0" @@ -854,17 +627,6 @@ docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2. testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"] typing = ["typing-extensions (>=4.12.2)"] -[[package]] -name = "fqdn" -version = "1.5.1" -description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" -optional = false -python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" -files = [ - {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, - {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, -] - [[package]] name = "freezegun" version = "1.5.1" @@ -881,50 +643,46 @@ python-dateutil = ">=2.7" [[package]] name = "great-expectations" -version = "0.18.21" +version = "1.0.4" description = "Always know what to expect from your data." optional = false -python-versions = ">=3.8" +python-versions = "<3.12,>=3.8" files = [ - {file = "great_expectations-0.18.21-py3-none-any.whl", hash = "sha256:b4f1b6946966349d9d4cc7e1cd7c13284659cbcc16ba122138c867be18132c81"}, - {file = "great_expectations-0.18.21.tar.gz", hash = "sha256:6ba4a722109db3308c5f4fbea4cb26097d2372d35a28634be4d39d331aab0d72"}, + {file = "great_expectations-1.0.4-py3-none-any.whl", hash = "sha256:d70da936327dea8afca2c1b7610c8cc195b25251a9d2521b51619b7e9e146ff8"}, + {file = "great_expectations-1.0.4.tar.gz", hash = "sha256:4b8a8d2c026cb1df6d33b8840e8fbf5867e5c677e6f79f6fab073d26e42afe93"}, ] [package.dependencies] altair = ">=4.2.1,<5.0.0" -Click = ">=7.1.2" -colorama = ">=0.4.3" cryptography = ">=3.2" Ipython = ">=7.16.3" ipywidgets = ">=7.5.1" jinja2 = ">=2.10" -jsonpatch = ">=1.22" jsonschema = ">=2.5.1" makefun = ">=1.7.0,<2" marshmallow = ">=3.7.1,<4.0.0" mistune = ">=0.8.4" -nbformat = ">=5.0" -notebook = ">=6.4.10" numpy = [ - {version = ">=1.20.3,<2.0.0", markers = "python_version == \"3.8\""}, - {version = ">=1.21.6,<2.0.0", markers = "python_version == \"3.9\""}, - {version = ">=1.22.4,<2.0.0", markers = "python_version >= \"3.10\""}, + {version = ">=1.20.3", markers = "python_version == \"3.8\""}, + {version = ">=1.21.6", markers = "python_version == \"3.9\""}, + {version = ">=1.22.4", markers = "python_version >= \"3.10\""}, ] packaging = "*" pandas = [ - {version = ">=1.1.0", markers = "python_version <= \"3.8\""}, - {version = ">=1.1.3", markers = "python_version == \"3.9\""}, - {version = ">=1.3.0", markers = "python_version >= \"3.10\""}, + {version = ">=1.1.0,<2.2", markers = "python_version <= \"3.8\""}, + {version = ">=1.1.3,<2.2", markers = "python_version == \"3.9\""}, + {version = ">=1.3.0,<2.2", markers = "python_version >= \"3.10\""}, ] -pydantic = ">=1.9.2" +posthog = ">=2.1.0,<3" +pydantic = ">=1.10.7" pyparsing = ">=2.4" python-dateutil = ">=2.8.1" pytz = ">=2021.3" requests = ">=2.20" -"ruamel.yaml" = ">=0.16,<0.18" +"ruamel.yaml" = ">=0.16" scipy = ">=1.6.0" tqdm = ">=4.59.0" -typing-extensions = ">=3.10.0.0" +typing-extensions = ">=4.1.0" tzlocal = ">=1.2" urllib3 = ">=1.26" @@ -935,9 +693,9 @@ aws-secrets = ["boto3 (>=1.17.106)"] azure = ["azure-identity (>=1.10.0)", "azure-keyvault-secrets (>=4.0.0)", "azure-storage-blob (>=12.5.0)"] azure-secrets = ["azure-identity (>=1.10.0)", "azure-keyvault-secrets (>=4.0.0)", "azure-storage-blob (>=12.5.0)"] bigquery = ["gcsfs (>=0.5.1)", "google-cloud-bigquery (>=3.3.6)", "google-cloud-bigquery-storage (>=2.20.0)", "google-cloud-secret-manager (>=1.0.0)", "google-cloud-storage (>=1.28.0)", "google-cloud-storage (>=2.10.0)", "sqlalchemy (<2.0.0)", "sqlalchemy-bigquery (>=1.3.0)"] -clickhouse = ["clickhouse-sqlalchemy (>=0.2.2)", "pandas (<2.2.0)", "sqlalchemy (<2.0.0)"] +clickhouse = ["clickhouse-sqlalchemy (>=0.2.2)", "clickhouse-sqlalchemy (>=0.3.0)", "sqlalchemy (<2.0.0)"] cloud = ["orjson (>=3.9.7)"] -databricks = ["databricks-sql-connector (>=2.0.0)", "sqlalchemy (>=1.4.0)"] +databricks = ["databricks-sql-connector (>=2.0.0)", "databricks-sql-connector[sqlalchemy] (>=3.0.0)", "sqlalchemy (>=1.4.0)"] dremio = ["pyodbc (>=4.0.30)", "sqlalchemy (>=1.4.0)", "sqlalchemy-dremio (==1.2.1)"] excel = ["openpyxl (>=3.0.7)", "xlrd (>=1.1.0,<2.0.0)"] gcp = ["gcsfs (>=0.5.1)", "google-cloud-bigquery (>=3.3.6)", "google-cloud-bigquery-storage (>=2.20.0)", "google-cloud-secret-manager (>=1.0.0)", "google-cloud-storage (>=1.28.0)", "google-cloud-storage (>=2.10.0)", "sqlalchemy (<2.0.0)", "sqlalchemy-bigquery (>=1.3.0)"] @@ -948,10 +706,10 @@ pagerduty = ["pypd (==1.1.0)"] postgresql = ["psycopg2-binary (>=2.7.6)", "sqlalchemy (>=1.4.0)"] redshift = ["psycopg2-binary (>=2.7.6)", "sqlalchemy (<2.0.0)", "sqlalchemy-redshift (>=0.8.8)"] s3 = ["boto3 (>=1.17.106)"] -snowflake = ["pandas (<2.2.0)", "snowflake-connector-python (>2.9.0)", "snowflake-connector-python (>=2.5.0)", "snowflake-sqlalchemy (>=1.2.3)", "sqlalchemy (<2.0.0)"] +snowflake = ["pandas (<2.2.0)", "snowflake-connector-python (>2.9.0)", "snowflake-connector-python (>=2.5.0)", "snowflake-sqlalchemy (>=1.2.3,!=1.5.2)", "sqlalchemy (>=1.4.0)"] spark = ["pyspark (>=2.3.2)"] teradata = ["sqlalchemy (<2.0.0)", "teradatasqlalchemy (==17.0.0.5)"] -test = ["adr-tools-python (==1.0.3)", "black[jupyter] (==23.10.1)", "boto3 (>=1.17.106)", "docstring-parser (==0.15)", "feather-format (>=0.4.1)", "flaky (>=3.7.0)", "flask (>=1.0.0)", "freezegun (>=0.3.15)", "invoke (>=2.0.0)", "ipykernel (<=6.17.1)", "moto (>=2.0.0,<3.0.0)", "mypy (==1.10.1)", "nbconvert (>=5)", "pact-python (>=2.0.1)", "pre-commit (>=2.21.0)", "pyarrow", "pyfakefs (>=4.5.1)", "pytest (>=6.2.0)", "pytest-benchmark (>=3.4.1)", "pytest-cov (>=2.8.1)", "pytest-icdiff (>=0.6)", "pytest-mock (>=3.8.2)", "pytest-order (>=0.9.5)", "pytest-random-order (>=1.0.4)", "pytest-timeout (>=2.1.0)", "pytest-xdist (>=3.3.1)", "requirements-parser (>=0.2.0)", "responses (>=0.23.1)", "ruff (==0.5.7)", "snapshottest (==0.6.0)", "sqlalchemy (>=1.4.0)", "tomli (>=2.0.1)"] +test = ["adr-tools-python (==1.0.3)", "boto3 (>=1.17.106)", "coverage[toml] (>=7.5.1)", "docstring-parser (==0.15)", "feather-format (>=0.4.1)", "flaky (>=3.7.0)", "flask (>=1.0.0)", "freezegun (>=0.3.15)", "invoke (>=2.0.0)", "ipykernel (<=6.17.1)", "moto[s3,sns] (>=4.2.13,<5.0)", "mypy (==1.11.2)", "nbconvert (>=5)", "nbformat (>=5.0)", "pact-python (>=2.0.1)", "pre-commit (>=2.21.0)", "pyarrow", "pyfakefs (>=4.5.1)", "pytest (>=8.2.1)", "pytest-benchmark (>=3.4.1)", "pytest-cov (>=5.0.0)", "pytest-icdiff (>=0.9.0)", "pytest-mock (>=3.14.0)", "pytest-order (>=1.2.1)", "pytest-random-order (>=1.1.1)", "pytest-timeout (>=2.3.1)", "pytest-xdist (>=3.6.1)", "requirements-parser (>=0.9.0)", "responses (>=0.23.1)", "ruff (==0.5.3)", "setuptools (>=70.0.0)", "snapshottest (==0.6.0)", "sqlalchemy (>=1.4.0)", "tomli (>=2.0.1)"] trino = ["sqlalchemy (>=1.4.0)", "trino (>=0.310.0,!=0.316.0)"] vertica = ["sqlalchemy (>=1.4.0)", "sqlalchemy-vertica-python (>=0.5.10)"] @@ -1034,63 +792,6 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "httpcore" -version = "1.0.5" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] - -[[package]] -name = "httpx" -version = "0.27.2" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, - {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" -sniffio = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -zstd = ["zstandard (>=0.18.0)"] - [[package]] name = "icdiff" version = "2.0.7" @@ -1127,29 +828,6 @@ files = [ {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] -[[package]] -name = "importlib-metadata" -version = "8.5.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, - {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, -] - -[package.dependencies] -zipp = ">=3.20" - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] -type = ["pytest-mypy"] - [[package]] name = "importlib-resources" version = "6.4.5" @@ -1194,39 +872,6 @@ files = [ {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, ] -[[package]] -name = "ipykernel" -version = "6.29.5" -description = "IPython Kernel for Jupyter" -optional = false -python-versions = ">=3.8" -files = [ - {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, - {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, -] - -[package.dependencies] -appnope = {version = "*", markers = "platform_system == \"Darwin\""} -comm = ">=0.1.1" -debugpy = ">=1.6.5" -ipython = ">=7.23.1" -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -matplotlib-inline = ">=0.1" -nest-asyncio = "*" -packaging = "*" -psutil = "*" -pyzmq = ">=24" -tornado = ">=6.1" -traitlets = ">=5.4.0" - -[package.extras] -cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] -pyqt5 = ["pyqt5"] -pyside6 = ["pyside6"] -test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] - [[package]] name = "ipython" version = "8.12.3" @@ -1287,20 +932,6 @@ widgetsnbextension = ">=4.0.12,<4.1.0" [package.extras] test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] -[[package]] -name = "isoduration" -version = "20.11.0" -description = "Operations with ISO 8601 durations" -optional = false -python-versions = ">=3.7" -files = [ - {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, - {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, -] - -[package.dependencies] -arrow = ">=0.15.0" - [[package]] name = "jedi" version = "0.19.1" @@ -1337,42 +968,6 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "json5" -version = "0.9.25" -description = "A Python implementation of the JSON5 data format." -optional = false -python-versions = ">=3.8" -files = [ - {file = "json5-0.9.25-py3-none-any.whl", hash = "sha256:34ed7d834b1341a86987ed52f3f76cd8ee184394906b6e22a1e0deb9ab294e8f"}, - {file = "json5-0.9.25.tar.gz", hash = "sha256:548e41b9be043f9426776f05df8635a00fe06104ea51ed24b67f908856e151ae"}, -] - -[[package]] -name = "jsonpatch" -version = "1.33" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -files = [ - {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "3.0.0" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, - {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, -] - [[package]] name = "jsonschema" version = "4.23.0" @@ -1386,249 +981,30 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} jsonschema-specifications = ">=2023.03.6" -pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} -referencing = ">=0.28.4" -rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} -rpds-py = ">=0.7.1" -uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] - -[[package]] -name = "jsonschema-specifications" -version = "2023.12.1" -description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, - {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, -] - -[package.dependencies] -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -referencing = ">=0.31.0" - -[[package]] -name = "jupyter-client" -version = "8.6.2" -description = "Jupyter protocol implementation and client libraries" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_client-8.6.2-py3-none-any.whl", hash = "sha256:50cbc5c66fd1b8f65ecb66bc490ab73217993632809b6e505687de18e9dea39f"}, - {file = "jupyter_client-8.6.2.tar.gz", hash = "sha256:2bda14d55ee5ba58552a8c53ae43d215ad9868853489213f37da060ced54d8df"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -python-dateutil = ">=2.8.2" -pyzmq = ">=23.0" -tornado = ">=6.2" -traitlets = ">=5.3" - -[package.extras] -docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] - -[[package]] -name = "jupyter-core" -version = "5.7.2" -description = "Jupyter core package. A base package on which Jupyter projects rely." -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, - {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, -] - -[package.dependencies] -platformdirs = ">=2.5" -pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} -traitlets = ">=5.3" - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] -test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "jupyter-events" -version = "0.10.0" -description = "Jupyter Event System library" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_events-0.10.0-py3-none-any.whl", hash = "sha256:4b72130875e59d57716d327ea70d3ebc3af1944d3717e5a498b8a06c6c159960"}, - {file = "jupyter_events-0.10.0.tar.gz", hash = "sha256:670b8229d3cc882ec782144ed22e0d29e1c2d639263f92ca8383e66682845e22"}, -] - -[package.dependencies] -jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} -python-json-logger = ">=2.0.4" -pyyaml = ">=5.3" -referencing = "*" -rfc3339-validator = "*" -rfc3986-validator = ">=0.1.1" -traitlets = ">=5.3" - -[package.extras] -cli = ["click", "rich"] -docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] -test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] - -[[package]] -name = "jupyter-lsp" -version = "2.2.5" -description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter-lsp-2.2.5.tar.gz", hash = "sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001"}, - {file = "jupyter_lsp-2.2.5-py3-none-any.whl", hash = "sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -jupyter-server = ">=1.1.2" - -[[package]] -name = "jupyter-server" -version = "2.14.2" -description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_server-2.14.2-py3-none-any.whl", hash = "sha256:47ff506127c2f7851a17bf4713434208fc490955d0e8632e95014a9a9afbeefd"}, - {file = "jupyter_server-2.14.2.tar.gz", hash = "sha256:66095021aa9638ced276c248b1d81862e4c50f292d575920bbe960de1c56b12b"}, -] - -[package.dependencies] -anyio = ">=3.1.0" -argon2-cffi = ">=21.1" -jinja2 = ">=3.0.3" -jupyter-client = ">=7.4.4" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -jupyter-events = ">=0.9.0" -jupyter-server-terminals = ">=0.4.4" -nbconvert = ">=6.4.4" -nbformat = ">=5.3.0" -overrides = ">=5.0" -packaging = ">=22.0" -prometheus-client = ">=0.9" -pywinpty = {version = ">=2.0.1", markers = "os_name == \"nt\""} -pyzmq = ">=24" -send2trash = ">=1.8.2" -terminado = ">=0.8.3" -tornado = ">=6.2.0" -traitlets = ">=5.6.0" -websocket-client = ">=1.7" - -[package.extras] -docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] -test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] - -[[package]] -name = "jupyter-server-terminals" -version = "0.5.3" -description = "A Jupyter Server Extension Providing Terminals." -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_server_terminals-0.5.3-py3-none-any.whl", hash = "sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa"}, - {file = "jupyter_server_terminals-0.5.3.tar.gz", hash = "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269"}, -] - -[package.dependencies] -pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} -terminado = ">=0.8.3" - -[package.extras] -docs = ["jinja2", "jupyter-server", "mistune (<4.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] -test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] - -[[package]] -name = "jupyterlab" -version = "4.2.5" -description = "JupyterLab computational environment" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyterlab-4.2.5-py3-none-any.whl", hash = "sha256:73b6e0775d41a9fee7ee756c80f58a6bed4040869ccc21411dc559818874d321"}, - {file = "jupyterlab-4.2.5.tar.gz", hash = "sha256:ae7f3a1b8cb88b4f55009ce79fa7c06f99d70cd63601ee4aa91815d054f46f75"}, -] - -[package.dependencies] -async-lru = ">=1.0.0" -httpx = ">=0.25.0" -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -importlib-resources = {version = ">=1.4", markers = "python_version < \"3.9\""} -ipykernel = ">=6.5.0" -jinja2 = ">=3.0.3" -jupyter-core = "*" -jupyter-lsp = ">=2.0.0" -jupyter-server = ">=2.4.0,<3" -jupyterlab-server = ">=2.27.1,<3" -notebook-shim = ">=0.2" -packaging = "*" -setuptools = ">=40.1.0" -tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} -tornado = ">=6.2.0" -traitlets = "*" +pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" [package.extras] -dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.3.5)"] -docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"] -docs-screenshots = ["altair (==5.3.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.2)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.1.post2)", "matplotlib (==3.8.3)", "nbconvert (>=7.0.0)", "pandas (==2.2.1)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"] -test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] -upgrade-extension = ["copier (>=9,<10)", "jinja2-time (<0.3)", "pydantic (<3.0)", "pyyaml-include (<3.0)", "tomli-w (<2.0)"] - -[[package]] -name = "jupyterlab-pygments" -version = "0.3.0" -description = "Pygments theme using JupyterLab CSS variables" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, - {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, -] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] [[package]] -name = "jupyterlab-server" -version = "2.27.3" -description = "A set of server components for JupyterLab and JupyterLab like applications." +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab_server-2.27.3-py3-none-any.whl", hash = "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4"}, - {file = "jupyterlab_server-2.27.3.tar.gz", hash = "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4"}, + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, ] [package.dependencies] -babel = ">=2.10" -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -jinja2 = ">=3.0.3" -json5 = ">=0.9.0" -jsonschema = ">=4.18.0" -jupyter-server = ">=1.21,<3" -packaging = ">=21.3" -requests = ">=2.31" - -[package.extras] -docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinxcontrib-openapi (>0.8)"] -openapi = ["openapi-core (>=0.18.0,<0.19.0)", "ruamel-yaml"] -test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.8.0)", "pytest (>=7.0,<8)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] +importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} +referencing = ">=0.31.0" [[package]] name = "jupyterlab-widgets" @@ -1815,6 +1191,17 @@ files = [ {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] +[[package]] +name = "monotonic" +version = "1.6" +description = "An implementation of time.monotonic() for Python 2 & < 3.3" +optional = false +python-versions = "*" +files = [ + {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"}, + {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, +] + [[package]] name = "mypy" version = "1.11.2" @@ -1873,98 +1260,6 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -[[package]] -name = "nbclient" -version = "0.10.0" -description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "nbclient-0.10.0-py3-none-any.whl", hash = "sha256:f13e3529332a1f1f81d82a53210322476a168bb7090a0289c795fe9cc11c9d3f"}, - {file = "nbclient-0.10.0.tar.gz", hash = "sha256:4b3f1b7dba531e498449c4db4f53da339c91d449dc11e9af3a43b4eb5c5abb09"}, -] - -[package.dependencies] -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -nbformat = ">=5.1" -traitlets = ">=5.4" - -[package.extras] -dev = ["pre-commit"] -docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] -test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] - -[[package]] -name = "nbconvert" -version = "7.16.4" -description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." -optional = false -python-versions = ">=3.8" -files = [ - {file = "nbconvert-7.16.4-py3-none-any.whl", hash = "sha256:05873c620fe520b6322bf8a5ad562692343fe3452abda5765c7a34b7d1aa3eb3"}, - {file = "nbconvert-7.16.4.tar.gz", hash = "sha256:86ca91ba266b0a448dc96fa6c5b9d98affabde2867b363258703536807f9f7f4"}, -] - -[package.dependencies] -beautifulsoup4 = "*" -bleach = "!=5.0.0" -defusedxml = "*" -importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} -jinja2 = ">=3.0" -jupyter-core = ">=4.7" -jupyterlab-pygments = "*" -markupsafe = ">=2.0" -mistune = ">=2.0.3,<4" -nbclient = ">=0.5.0" -nbformat = ">=5.7" -packaging = "*" -pandocfilters = ">=1.4.1" -pygments = ">=2.4.1" -tinycss2 = "*" -traitlets = ">=5.1" - -[package.extras] -all = ["flaky", "ipykernel", "ipython", "ipywidgets (>=7.5)", "myst-parser", "nbsphinx (>=0.2.12)", "playwright", "pydata-sphinx-theme", "pyqtwebengine (>=5.15)", "pytest (>=7)", "sphinx (==5.0.2)", "sphinxcontrib-spelling", "tornado (>=6.1)"] -docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] -qtpdf = ["pyqtwebengine (>=5.15)"] -qtpng = ["pyqtwebengine (>=5.15)"] -serve = ["tornado (>=6.1)"] -test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest (>=7)"] -webpdf = ["playwright"] - -[[package]] -name = "nbformat" -version = "5.10.4" -description = "The Jupyter Notebook format" -optional = false -python-versions = ">=3.8" -files = [ - {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}, - {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}, -] - -[package.dependencies] -fastjsonschema = ">=2.15" -jsonschema = ">=2.6" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -traitlets = ">=5.1" - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["pep440", "pre-commit", "pytest", "testpath"] - -[[package]] -name = "nest-asyncio" -version = "1.6.0" -description = "Patch asyncio to allow nested event loops" -optional = false -python-versions = ">=3.5" -files = [ - {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, - {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, -] - [[package]] name = "nodeenv" version = "1.9.1" @@ -1976,46 +1271,6 @@ files = [ {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] -[[package]] -name = "notebook" -version = "7.2.2" -description = "Jupyter Notebook - A web-based notebook environment for interactive computing" -optional = false -python-versions = ">=3.8" -files = [ - {file = "notebook-7.2.2-py3-none-any.whl", hash = "sha256:c89264081f671bc02eec0ed470a627ed791b9156cad9285226b31611d3e9fe1c"}, - {file = "notebook-7.2.2.tar.gz", hash = "sha256:2ef07d4220421623ad3fe88118d687bc0450055570cdd160814a59cf3a1c516e"}, -] - -[package.dependencies] -jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.2.0,<4.3" -jupyterlab-server = ">=2.27.1,<3" -notebook-shim = ">=0.2,<0.3" -tornado = ">=6.2.0" - -[package.extras] -dev = ["hatch", "pre-commit"] -docs = ["myst-parser", "nbsphinx", "pydata-sphinx-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["importlib-resources (>=5.0)", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.27.1,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] - -[[package]] -name = "notebook-shim" -version = "0.2.4" -description = "A shim layer for notebook traits and config" -optional = false -python-versions = ">=3.7" -files = [ - {file = "notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef"}, - {file = "notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb"}, -] - -[package.dependencies] -jupyter-server = ">=1.8,<3" - -[package.extras] -test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] - [[package]] name = "numpy" version = "1.24.4" @@ -2194,17 +1449,6 @@ files = [ {file = "orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3"}, ] -[[package]] -name = "overrides" -version = "7.7.0" -description = "A decorator to automatically detect mismatch when overriding a method." -optional = false -python-versions = ">=3.6" -files = [ - {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, - {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, -] - [[package]] name = "packaging" version = "24.1" @@ -2283,17 +1527,6 @@ sql-other = ["SQLAlchemy (>=1.4.16)"] test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.6.3)"] -[[package]] -name = "pandocfilters" -version = "1.5.1" -description = "Utilities for writing pandoc filters in python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, - {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, -] - [[package]] name = "parso" version = "0.8.4" @@ -2392,6 +1625,29 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "posthog" +version = "2.5.0" +description = "Integrate PostHog into any python application." +optional = false +python-versions = "*" +files = [ + {file = "posthog-2.5.0-py2.py3-none-any.whl", hash = "sha256:3d3ece06c3fe4135497c239f211c82344962b93e4fd4ba5afd20bd4ad12d77be"}, + {file = "posthog-2.5.0.tar.gz", hash = "sha256:7601ef75b483eb67a6229cafec02da9624f6d46df61066771ca9e3f986284fc3"}, +] + +[package.dependencies] +backoff = ">=1.10.0" +monotonic = ">=1.5" +python-dateutil = ">2.1" +requests = ">=2.7,<3.0" +six = ">=1.5" + +[package.extras] +dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"] +sentry = ["django", "sentry-sdk"] +test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest"] + [[package]] name = "pprintpp" version = "0.4.0" @@ -2421,20 +1677,6 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" -[[package]] -name = "prometheus-client" -version = "0.20.0" -description = "Python client for the Prometheus monitoring system." -optional = false -python-versions = ">=3.8" -files = [ - {file = "prometheus_client-0.20.0-py3-none-any.whl", hash = "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7"}, - {file = "prometheus_client-0.20.0.tar.gz", hash = "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89"}, -] - -[package.extras] -twisted = ["twisted"] - [[package]] name = "prompt-toolkit" version = "3.0.47" @@ -2449,35 +1691,6 @@ files = [ [package.dependencies] wcwidth = "*" -[[package]] -name = "psutil" -version = "6.0.0" -description = "Cross-platform lib for process and system monitoring in Python." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -files = [ - {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, - {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, - {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, - {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, - {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, - {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, - {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, - {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, - {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, - {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, -] - -[package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] - [[package]] name = "psycopg2-binary" version = "2.9.9" @@ -2925,17 +2138,6 @@ files = [ [package.dependencies] six = ">=1.5" -[[package]] -name = "python-json-logger" -version = "2.0.7" -description = "A python library adding a json log formatter" -optional = false -python-versions = ">=3.6" -files = [ - {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"}, - {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, -] - [[package]] name = "pytz" version = "2024.2" @@ -2947,44 +2149,6 @@ files = [ {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, ] -[[package]] -name = "pywin32" -version = "306" -description = "Python for Window Extensions" -optional = false -python-versions = "*" -files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, -] - -[[package]] -name = "pywinpty" -version = "2.0.13" -description = "Pseudo terminal support for Windows from Python." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pywinpty-2.0.13-cp310-none-win_amd64.whl", hash = "sha256:697bff211fb5a6508fee2dc6ff174ce03f34a9a233df9d8b5fe9c8ce4d5eaf56"}, - {file = "pywinpty-2.0.13-cp311-none-win_amd64.whl", hash = "sha256:b96fb14698db1284db84ca38c79f15b4cfdc3172065b5137383910567591fa99"}, - {file = "pywinpty-2.0.13-cp312-none-win_amd64.whl", hash = "sha256:2fd876b82ca750bb1333236ce98488c1be96b08f4f7647cfdf4129dfad83c2d4"}, - {file = "pywinpty-2.0.13-cp38-none-win_amd64.whl", hash = "sha256:61d420c2116c0212808d31625611b51caf621fe67f8a6377e2e8b617ea1c1f7d"}, - {file = "pywinpty-2.0.13-cp39-none-win_amd64.whl", hash = "sha256:71cb613a9ee24174730ac7ae439fd179ca34ccb8c5349e8d7b72ab5dea2c6f4b"}, - {file = "pywinpty-2.0.13.tar.gz", hash = "sha256:c34e32351a3313ddd0d7da23d27f835c860d32fe4ac814d372a3ea9594f41dde"}, -] - [[package]] name = "pyyaml" version = "6.0.2" @@ -3047,127 +2211,6 @@ files = [ {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] -[[package]] -name = "pyzmq" -version = "26.2.0" -description = "Python bindings for 0MQ" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ddf33d97d2f52d89f6e6e7ae66ee35a4d9ca6f36eda89c24591b0c40205a3629"}, - {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dacd995031a01d16eec825bf30802fceb2c3791ef24bcce48fa98ce40918c27b"}, - {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89289a5ee32ef6c439086184529ae060c741334b8970a6855ec0b6ad3ff28764"}, - {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5506f06d7dc6ecf1efacb4a013b1f05071bb24b76350832c96449f4a2d95091c"}, - {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ea039387c10202ce304af74def5021e9adc6297067f3441d348d2b633e8166a"}, - {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a2224fa4a4c2ee872886ed00a571f5e967c85e078e8e8c2530a2fb01b3309b88"}, - {file = "pyzmq-26.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:28ad5233e9c3b52d76196c696e362508959741e1a005fb8fa03b51aea156088f"}, - {file = "pyzmq-26.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1c17211bc037c7d88e85ed8b7d8f7e52db6dc8eca5590d162717c654550f7282"}, - {file = "pyzmq-26.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b8f86dd868d41bea9a5f873ee13bf5551c94cf6bc51baebc6f85075971fe6eea"}, - {file = "pyzmq-26.2.0-cp310-cp310-win32.whl", hash = "sha256:46a446c212e58456b23af260f3d9fb785054f3e3653dbf7279d8f2b5546b21c2"}, - {file = "pyzmq-26.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:49d34ab71db5a9c292a7644ce74190b1dd5a3475612eefb1f8be1d6961441971"}, - {file = "pyzmq-26.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:bfa832bfa540e5b5c27dcf5de5d82ebc431b82c453a43d141afb1e5d2de025fa"}, - {file = "pyzmq-26.2.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218"}, - {file = "pyzmq-26.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3a495b30fc91db2db25120df5847d9833af237546fd59170701acd816ccc01c4"}, - {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef"}, - {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ace4f71f1900a548f48407fc9be59c6ba9d9aaf658c2eea6cf2779e72f9f317"}, - {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92a78853d7280bffb93df0a4a6a2498cba10ee793cc8076ef797ef2f74d107cf"}, - {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e"}, - {file = "pyzmq-26.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aca98bc423eb7d153214b2df397c6421ba6373d3397b26c057af3c904452e37"}, - {file = "pyzmq-26.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f3496d76b89d9429a656293744ceca4d2ac2a10ae59b84c1da9b5165f429ad3"}, - {file = "pyzmq-26.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5c2b3bfd4b9689919db068ac6c9911f3fcb231c39f7dd30e3138be94896d18e6"}, - {file = "pyzmq-26.2.0-cp311-cp311-win32.whl", hash = "sha256:eac5174677da084abf378739dbf4ad245661635f1600edd1221f150b165343f4"}, - {file = "pyzmq-26.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5"}, - {file = "pyzmq-26.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0e6091b157d48cbe37bd67233318dbb53e1e6327d6fc3bb284afd585d141003"}, - {file = "pyzmq-26.2.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9"}, - {file = "pyzmq-26.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52"}, - {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08"}, - {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5"}, - {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae"}, - {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711"}, - {file = "pyzmq-26.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6"}, - {file = "pyzmq-26.2.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3"}, - {file = "pyzmq-26.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b"}, - {file = "pyzmq-26.2.0-cp312-cp312-win32.whl", hash = "sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7"}, - {file = "pyzmq-26.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a"}, - {file = "pyzmq-26.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b"}, - {file = "pyzmq-26.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726"}, - {file = "pyzmq-26.2.0-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3"}, - {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50"}, - {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb"}, - {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187"}, - {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b"}, - {file = "pyzmq-26.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18"}, - {file = "pyzmq-26.2.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115"}, - {file = "pyzmq-26.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e"}, - {file = "pyzmq-26.2.0-cp313-cp313-win32.whl", hash = "sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5"}, - {file = "pyzmq-26.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad"}, - {file = "pyzmq-26.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797"}, - {file = "pyzmq-26.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a"}, - {file = "pyzmq-26.2.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc"}, - {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5"}, - {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672"}, - {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797"}, - {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386"}, - {file = "pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306"}, - {file = "pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6"}, - {file = "pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0"}, - {file = "pyzmq-26.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3b55a4229ce5da9497dd0452b914556ae58e96a4381bb6f59f1305dfd7e53fc8"}, - {file = "pyzmq-26.2.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9cb3a6460cdea8fe8194a76de8895707e61ded10ad0be97188cc8463ffa7e3a8"}, - {file = "pyzmq-26.2.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ab5cad923cc95c87bffee098a27856c859bd5d0af31bd346035aa816b081fe1"}, - {file = "pyzmq-26.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ed69074a610fad1c2fda66180e7b2edd4d31c53f2d1872bc2d1211563904cd9"}, - {file = "pyzmq-26.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cccba051221b916a4f5e538997c45d7d136a5646442b1231b916d0164067ea27"}, - {file = "pyzmq-26.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:0eaa83fc4c1e271c24eaf8fb083cbccef8fde77ec8cd45f3c35a9a123e6da097"}, - {file = "pyzmq-26.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9edda2df81daa129b25a39b86cb57dfdfe16f7ec15b42b19bfac503360d27a93"}, - {file = "pyzmq-26.2.0-cp37-cp37m-win32.whl", hash = "sha256:ea0eb6af8a17fa272f7b98d7bebfab7836a0d62738e16ba380f440fceca2d951"}, - {file = "pyzmq-26.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4ff9dc6bc1664bb9eec25cd17506ef6672d506115095411e237d571e92a58231"}, - {file = "pyzmq-26.2.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:2eb7735ee73ca1b0d71e0e67c3739c689067f055c764f73aac4cc8ecf958ee3f"}, - {file = "pyzmq-26.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a534f43bc738181aa7cbbaf48e3eca62c76453a40a746ab95d4b27b1111a7d2"}, - {file = "pyzmq-26.2.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:aedd5dd8692635813368e558a05266b995d3d020b23e49581ddd5bbe197a8ab6"}, - {file = "pyzmq-26.2.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8be4700cd8bb02cc454f630dcdf7cfa99de96788b80c51b60fe2fe1dac480289"}, - {file = "pyzmq-26.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fcc03fa4997c447dce58264e93b5aa2d57714fbe0f06c07b7785ae131512732"}, - {file = "pyzmq-26.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:402b190912935d3db15b03e8f7485812db350d271b284ded2b80d2e5704be780"}, - {file = "pyzmq-26.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8685fa9c25ff00f550c1fec650430c4b71e4e48e8d852f7ddcf2e48308038640"}, - {file = "pyzmq-26.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:76589c020680778f06b7e0b193f4b6dd66d470234a16e1df90329f5e14a171cd"}, - {file = "pyzmq-26.2.0-cp38-cp38-win32.whl", hash = "sha256:8423c1877d72c041f2c263b1ec6e34360448decfb323fa8b94e85883043ef988"}, - {file = "pyzmq-26.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:76589f2cd6b77b5bdea4fca5992dc1c23389d68b18ccc26a53680ba2dc80ff2f"}, - {file = "pyzmq-26.2.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:b1d464cb8d72bfc1a3adc53305a63a8e0cac6bc8c5a07e8ca190ab8d3faa43c2"}, - {file = "pyzmq-26.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4da04c48873a6abdd71811c5e163bd656ee1b957971db7f35140a2d573f6949c"}, - {file = "pyzmq-26.2.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d049df610ac811dcffdc147153b414147428567fbbc8be43bb8885f04db39d98"}, - {file = "pyzmq-26.2.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05590cdbc6b902101d0e65d6a4780af14dc22914cc6ab995d99b85af45362cc9"}, - {file = "pyzmq-26.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c811cfcd6a9bf680236c40c6f617187515269ab2912f3d7e8c0174898e2519db"}, - {file = "pyzmq-26.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6835dd60355593de10350394242b5757fbbd88b25287314316f266e24c61d073"}, - {file = "pyzmq-26.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc6bee759a6bddea5db78d7dcd609397449cb2d2d6587f48f3ca613b19410cfc"}, - {file = "pyzmq-26.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c530e1eecd036ecc83c3407f77bb86feb79916d4a33d11394b8234f3bd35b940"}, - {file = "pyzmq-26.2.0-cp39-cp39-win32.whl", hash = "sha256:367b4f689786fca726ef7a6c5ba606958b145b9340a5e4808132cc65759abd44"}, - {file = "pyzmq-26.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:e6fa2e3e683f34aea77de8112f6483803c96a44fd726d7358b9888ae5bb394ec"}, - {file = "pyzmq-26.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:7445be39143a8aa4faec43b076e06944b8f9d0701b669df4af200531b21e40bb"}, - {file = "pyzmq-26.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:706e794564bec25819d21a41c31d4df2d48e1cc4b061e8d345d7fb4dd3e94072"}, - {file = "pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b435f2753621cd36e7c1762156815e21c985c72b19135dac43a7f4f31d28dd1"}, - {file = "pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:160c7e0a5eb178011e72892f99f918c04a131f36056d10d9c1afb223fc952c2d"}, - {file = "pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4a71d5d6e7b28a47a394c0471b7e77a0661e2d651e7ae91e0cab0a587859ca"}, - {file = "pyzmq-26.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:90412f2db8c02a3864cbfc67db0e3dcdbda336acf1c469526d3e869394fe001c"}, - {file = "pyzmq-26.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2ea4ad4e6a12e454de05f2949d4beddb52460f3de7c8b9d5c46fbb7d7222e02c"}, - {file = "pyzmq-26.2.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fc4f7a173a5609631bb0c42c23d12c49df3966f89f496a51d3eb0ec81f4519d6"}, - {file = "pyzmq-26.2.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:878206a45202247781472a2d99df12a176fef806ca175799e1c6ad263510d57c"}, - {file = "pyzmq-26.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17c412bad2eb9468e876f556eb4ee910e62d721d2c7a53c7fa31e643d35352e6"}, - {file = "pyzmq-26.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:0d987a3ae5a71c6226b203cfd298720e0086c7fe7c74f35fa8edddfbd6597eed"}, - {file = "pyzmq-26.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:39887ac397ff35b7b775db7201095fc6310a35fdbae85bac4523f7eb3b840e20"}, - {file = "pyzmq-26.2.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fdb5b3e311d4d4b0eb8b3e8b4d1b0a512713ad7e6a68791d0923d1aec433d919"}, - {file = "pyzmq-26.2.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:226af7dcb51fdb0109f0016449b357e182ea0ceb6b47dfb5999d569e5db161d5"}, - {file = "pyzmq-26.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bed0e799e6120b9c32756203fb9dfe8ca2fb8467fed830c34c877e25638c3fc"}, - {file = "pyzmq-26.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:29c7947c594e105cb9e6c466bace8532dc1ca02d498684128b339799f5248277"}, - {file = "pyzmq-26.2.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cdeabcff45d1c219636ee2e54d852262e5c2e085d6cb476d938aee8d921356b3"}, - {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35cffef589bcdc587d06f9149f8d5e9e8859920a071df5a2671de2213bef592a"}, - {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18c8dc3b7468d8b4bdf60ce9d7141897da103c7a4690157b32b60acb45e333e6"}, - {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7133d0a1677aec369d67dd78520d3fa96dd7f3dcec99d66c1762870e5ea1a50a"}, - {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6a96179a24b14fa6428cbfc08641c779a53f8fcec43644030328f44034c7f1f4"}, - {file = "pyzmq-26.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4f78c88905461a9203eac9faac157a2a0dbba84a0fd09fd29315db27be40af9f"}, - {file = "pyzmq-26.2.0.tar.gz", hash = "sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f"}, -] - -[package.dependencies] -cffi = {version = "*", markers = "implementation_name == \"pypy\""} - [[package]] name = "referencing" version = "0.35.1" @@ -3223,31 +2266,6 @@ urllib3 = ">=1.25.10,<3.0" [package.extras] tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] -[[package]] -name = "rfc3339-validator" -version = "0.1.4" -description = "A pure python RFC3339 validator" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, - {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, -] - -[package.dependencies] -six = "*" - -[[package]] -name = "rfc3986-validator" -version = "0.1.1" -description = "Pure python rfc3986 validator" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, - {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, -] - [[package]] name = "rpds-py" version = "0.20.0" @@ -3502,42 +2520,6 @@ dev = ["click", "doit (>=0.36.0)", "flake8", "mypy", "pycodestyle", "pydevtool", doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] -[[package]] -name = "send2trash" -version = "1.8.3" -description = "Send file to trash natively under Mac OS X, Windows and Linux" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -files = [ - {file = "Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9"}, - {file = "Send2Trash-1.8.3.tar.gz", hash = "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf"}, -] - -[package.extras] -nativelib = ["pyobjc-framework-Cocoa", "pywin32"] -objc = ["pyobjc-framework-Cocoa"] -win32 = ["pywin32"] - -[[package]] -name = "setuptools" -version = "74.1.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, - {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] - [[package]] name = "six" version = "1.16.0" @@ -3549,17 +2531,6 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - [[package]] name = "snowflake-connector-python" version = "3.12.2" @@ -3649,17 +2620,6 @@ files = [ {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, ] -[[package]] -name = "soupsieve" -version = "2.6" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -files = [ - {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, - {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, -] - [[package]] name = "sqlalchemy" version = "2.0.35" @@ -3781,27 +2741,6 @@ files = [ doc = ["reno", "sphinx"] test = ["pytest", "tornado (>=4.5)", "typeguard"] -[[package]] -name = "terminado" -version = "0.18.1" -description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." -optional = false -python-versions = ">=3.8" -files = [ - {file = "terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0"}, - {file = "terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e"}, -] - -[package.dependencies] -ptyprocess = {version = "*", markers = "os_name != \"nt\""} -pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} -tornado = ">=6.1.0" - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] -typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] - [[package]] name = "thrift" version = "0.20.0" @@ -3820,24 +2759,6 @@ all = ["tornado (>=4.0)", "twisted"] tornado = ["tornado (>=4.0)"] twisted = ["twisted"] -[[package]] -name = "tinycss2" -version = "1.3.0" -description = "A tiny CSS parser" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7"}, - {file = "tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d"}, -] - -[package.dependencies] -webencodings = ">=0.4" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["pytest", "ruff"] - [[package]] name = "tomli" version = "2.0.1" @@ -3871,26 +2792,6 @@ files = [ {file = "toolz-0.12.1.tar.gz", hash = "sha256:ecca342664893f177a13dac0e6b41cbd8ac25a358e5f215316d43e2100224f4d"}, ] -[[package]] -name = "tornado" -version = "6.4.1" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -optional = false -python-versions = ">=3.8" -files = [ - {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"}, - {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"}, - {file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"}, - {file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"}, - {file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"}, -] - [[package]] name = "tqdm" version = "4.66.5" @@ -3926,17 +2827,6 @@ files = [ docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] -[[package]] -name = "types-python-dateutil" -version = "2.9.0.20240906" -description = "Typing stubs for python-dateutil" -optional = false -python-versions = ">=3.8" -files = [ - {file = "types-python-dateutil-2.9.0.20240906.tar.gz", hash = "sha256:9706c3b68284c25adffc47319ecc7947e5bb86b3773f843c73906fd598bc176e"}, - {file = "types_python_dateutil-2.9.0.20240906-py3-none-any.whl", hash = "sha256:27c8cc2d058ccb14946eebcaaa503088f4f6dbc4fb6093d3d456a49aef2753f6"}, -] - [[package]] name = "types-requests" version = "2.31.0.6" @@ -4002,20 +2892,6 @@ tzdata = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] -[[package]] -name = "uri-template" -version = "1.3.0" -description = "RFC 6570 URI Template Processor" -optional = false -python-versions = ">=3.7" -files = [ - {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, - {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, -] - -[package.extras] -dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] - [[package]] name = "urllib3" version = "1.26.20" @@ -4063,48 +2939,6 @@ files = [ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] -[[package]] -name = "webcolors" -version = "24.8.0" -description = "A library for working with the color formats defined by HTML and CSS." -optional = false -python-versions = ">=3.8" -files = [ - {file = "webcolors-24.8.0-py3-none-any.whl", hash = "sha256:fc4c3b59358ada164552084a8ebee637c221e4059267d0f8325b3b560f6c7f0a"}, - {file = "webcolors-24.8.0.tar.gz", hash = "sha256:08b07af286a01bcd30d583a7acadf629583d1f79bfef27dd2c2c5c263817277d"}, -] - -[package.extras] -docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] -tests = ["coverage[toml]"] - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -optional = false -python-versions = "*" -files = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] - -[[package]] -name = "websocket-client" -version = "1.8.0" -description = "WebSocket client for Python with low level API options" -optional = false -python-versions = ">=3.8" -files = [ - {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, - {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, -] - -[package.extras] -docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] -optional = ["python-socks", "wsaccel"] -test = ["websockets"] - [[package]] name = "widgetsnbextension" version = "4.0.13" @@ -4143,4 +2977,4 @@ snowflake = ["snowflake-connector-python", "snowflake-sqlalchemy"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "b42a5d211c27f207509d77fede99fb1aba95c5049cdb128e553c68d6d9af6490" +content-hash = "87cfab0a02a2e5be9a696a917ac4005f5c66049b9a8611c56b119fa4c8bb96eb" diff --git a/pyproject.toml b/pyproject.toml index 14626acd..aac7182a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ include = [ [tool.poetry.dependencies] python = ">=3.8,<3.12" -great-expectations = "^0.18.20,<0.19" # <0.19 instead of DataContextConfigTD: }, }, } + + +class DummyEvent(EventBase): + type: Literal["event_name.received"] = "event_name.received" + + +class DummyAction(AgentAction[Any]): + @override + def run(self, event: Event, id: str) -> ActionResult: + return ActionResult(id=id, type="DummyAction", created_resources=[]) + + +register_event_action("1", DummyEvent, DummyAction) # type: ignore[arg-type] diff --git a/tests/agent/test_agent.py b/tests/agent/test_agent.py index 625b33ab..62e9c605 100644 --- a/tests/agent/test_agent.py +++ b/tests/agent/test_agent.py @@ -29,14 +29,12 @@ SubscriberError, ) from great_expectations_cloud.agent.models import ( - DraftDatasourceConfigEvent, JobCompleted, JobStarted, - RunCheckpointEvent, RunOnboardingDataAssistantEvent, RunScheduledCheckpointEvent, ) -from tests.agent.conftest import FakeSubscriber +from tests.agent.conftest import DummyEvent, FakeMessagePayload, FakeSubscriber if TYPE_CHECKING: from tests.agent.conftest import DataContextConfigTD @@ -467,6 +465,7 @@ def test_custom_user_agent( mock_gx_version_check: None, set_required_env_vars: None, gx_agent_config: GXAgentConfig, + data_context_config: DataContextConfigTD, ): """Ensure custom User-Agent header is set on GX Cloud api calls.""" base_url = gx_agent_config.gx_cloud_base_url @@ -474,15 +473,21 @@ def test_custom_user_agent( with responses.RequestsMock() as rsps: rsps.add( responses.GET, - f"{base_url}/organizations/{org_id}/data-context-configuration", - json={ - "anonymous_usage_statistics": { - "data_context_id": str(uuid.uuid4()), - "enabled": False, - }, - "datasources": {}, - "stores": {}, - }, + f"{base_url}api/v1/organizations/{org_id}/data-context-configuration", + json=data_context_config, + # match will fail if the User-Agent header is not set + match=[ + responses.matchers.header_matcher( + { + HeaderName.USER_AGENT: f"{USER_AGENT_HEADER}/{GXAgent.get_current_gx_agent_version()}" + } + ) + ], + ) + rsps.add( + responses.GET, + f"{base_url}organizations/{org_id}/accounts/me", + json={"user_id": str(uuid.uuid4())}, # match will fail if the User-Agent header is not set match=[ responses.matchers.header_matcher( @@ -524,64 +529,22 @@ def test_correlation_id_header( ): """Ensure agent-job-id/correlation-id header is set on GX Cloud api calls and updated for every new job.""" agent_job_ids: list[str] = [str(uuid.uuid4()) for _ in range(3)] - datasource_config_id_1 = uuid.UUID("00000000-0000-0000-0000-000000000001") - datasource_config_id_2 = uuid.UUID("00000000-0000-0000-0000-000000000002") - checkpoint_id = uuid.UUID("00000000-0000-0000-0000-000000000003") # seed the fake queue with an event that will be consumed by the agent - fake_subscriber.test_queue.extendleft( - [ - ( - DraftDatasourceConfigEvent( - config_id=datasource_config_id_1, - organization_id=random_uuid, # type: ignore[arg-type] # str coerced to UUID - ), - agent_job_ids[0], - ), - ( - DraftDatasourceConfigEvent( - config_id=datasource_config_id_2, - organization_id=random_uuid, # type: ignore[arg-type] # str coerced to UUID - ), - agent_job_ids[1], - ), - ( - RunCheckpointEvent( - checkpoint_id=checkpoint_id, - datasource_names_to_asset_names={}, - organization_id=random_uuid, # type: ignore[arg-type] # str coerced to UUID - ), - agent_job_ids[2], - ), - ] - ) + fake_subscriber.test_queue.extendleft([FakeMessagePayload(DummyEvent(), agent_job_ids[0])]) base_url = gx_agent_config.gx_cloud_base_url org_id = gx_agent_config.gx_cloud_organization_id with responses.RequestsMock() as rsps: - rsps.add( - responses.GET, - f"{base_url}/organizations/{org_id}/data-context-configuration", - json=data_context_config, - ) - rsps.add( - responses.GET, - f"{base_url}/organizations/{org_id}/datasources/drafts/{datasource_config_id_1}", - json={"data": {"attributes": {"draft_config": ds_config_factory("test-ds-1")}}}, - # match will fail if correlation-id header is not set - match=[responses.matchers.header_matcher({HeaderName.AGENT_JOB_ID: agent_job_ids[0]})], - ) - rsps.add( - responses.GET, - f"{base_url}/organizations/{org_id}/datasources/drafts/{datasource_config_id_2}", - json={"data": {"attributes": {"draft_config": ds_config_factory("test-ds-2")}}}, - # match will fail if correlation-id header is not set - match=[responses.matchers.header_matcher({HeaderName.AGENT_JOB_ID: agent_job_ids[1]})], + ( + rsps.add( + responses.GET, + f"{base_url}organizations/{org_id}/accounts/me", + json={"user_id": str(uuid.uuid4())}, + ), ) rsps.add( responses.GET, - f"{base_url}organizations/{org_id}/checkpoints/{checkpoint_id}", - json={"data": {}}, - # match will fail if correlation-id header is not set - match=[responses.matchers.header_matcher({HeaderName.AGENT_JOB_ID: agent_job_ids[2]})], + f"{base_url}api/v1/organizations/{org_id}/data-context-configuration", + json=data_context_config, ) agent = GXAgent() agent.run() diff --git a/tests/agent/test_event_handler.py b/tests/agent/test_event_handler.py index cb923b6b..daefba1d 100644 --- a/tests/agent/test_event_handler.py +++ b/tests/agent/test_event_handler.py @@ -1,7 +1,7 @@ from __future__ import annotations import uuid -from typing import TYPE_CHECKING, Any, Literal +from typing import TYPE_CHECKING, Any from uuid import UUID, uuid4 import orjson @@ -10,10 +10,8 @@ from great_expectations.experimental.metric_repository.metrics import ( MetricTypes, ) -from typing_extensions import override from great_expectations_cloud.agent.actions import ( - ActionResult, AgentAction, DraftDatasourceConfigAction, ListTableNamesAction, @@ -33,13 +31,13 @@ from great_expectations_cloud.agent.models import ( DraftDatasourceConfigEvent, Event, - EventBase, ListTableNamesEvent, RunCheckpointEvent, RunMetricsListEvent, RunOnboardingDataAssistantEvent, UnknownEvent, ) +from tests.agent.conftest import DummyAction, DummyEvent if TYPE_CHECKING: from pytest_mock import MockerFixture @@ -218,16 +216,6 @@ def test_event_handler_raises_on_no_version_implementation( handler.get_event_action(DummyEvent, base_url="", auth_key="", organization_id=uuid4()) # type: ignore[arg-type] # Dummy event only used in testing -class DummyEvent(EventBase): - type: Literal["event_name.received"] = "event_name.received" - - -class DummyAction(AgentAction[Any]): - @override - def run(self, event: Event, id: str) -> ActionResult: - return ActionResult(id=id, type="DummyAction", created_resources=[]) - - class TestEventHandlerRegistry: @pytest.mark.parametrize( "version", @@ -250,7 +238,7 @@ def test_register_event_action_already_registered(self, mocker: MockerFixture): def test_event_handler_gets_correct_event_action(self, mocker: MockerFixture, mock_context): mocker.patch.dict(_EVENT_ACTION_MAP, {}, clear=True) DummyEvent.organization_id = uuid.UUID("00000000-0000-0000-0000-000000000000") - register_event_action("0", DummyEvent, DummyAction) # type: ignore[arg-type] + register_event_action("1", DummyEvent, DummyAction) # type: ignore[arg-type] handler = EventHandler(context=mock_context) assert isinstance( handler.get_event_action( From 0b19d11084dac73af63ad819a1a822b48f309665 Mon Sep 17 00:00:00 2001 From: Thu Pham Date: Thu, 19 Sep 2024 10:04:06 -0700 Subject: [PATCH 02/29] Skip integration tests and update to alpha version --- pyproject.toml | 14 +++-- tests/integration/actions/conftest.py | 61 ++++++++++--------- .../actions/test_checkpoint_action.py | 1 + .../test_draft_datasource_config_action.py | 2 + .../actions/test_list_table_names.py | 2 + .../actions/test_metric_list_action.py | 1 + .../actions/test_run_scheduled_checkpoint.py | 1 + 7 files changed, 46 insertions(+), 36 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index aac7182a..5f1dd1ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "great_expectations_cloud" -version = "20240918.0" +version = "20240918.0.a0" description = "Great Expectations Cloud" authors = ["The Great Expectations Team "] repository = "https://github.com/great-expectations/cloud" @@ -36,7 +36,9 @@ sqlalchemy = { version = ">=2.0", optional = false } snowflake-sqlalchemy = { version = ">=1.6", optional = true } snowflake-connector-python = { version = ">=3.3.1", optional = true } psycopg2-binary = { version = "*", optional = true } -databricks-sql-connector = { version = ">=3.1.1", extras = ["sqlalchemy"], optional = true } +databricks-sql-connector = { version = ">=3.1.1", extras = [ + "sqlalchemy", +], optional = true } [tool.poetry.extras] # https://python-poetry.org/docs/pyproject#extras @@ -46,11 +48,11 @@ postgres = ["sqlalchemy", "psycopg2-binary"] databricks = ["databricks-sql-connector"] [tool.poetry.group.sql.dependencies] -great-expectations = { version = ">=0.18.19"} +great-expectations = { version = ">=0.18.19" } snowflake-sqlalchemy = ">=1.6" snowflake-connector-python = ">=3.3.1" psycopg2-binary = "^2.9.9" -databricks-sql-connector = { version = ">=3.1.1", extras = ["sqlalchemy"]} +databricks-sql-connector = { version = ">=3.1.1", extras = ["sqlalchemy"] } [tool.poetry.group.dev.dependencies] coverage = { extras = ["toml"], version = "^7.5.1" } @@ -87,7 +89,7 @@ ignore_missing_imports = true follow_imports = 'normal' warn_redundant_casts = true show_error_codes = true -implicit_reexport = true # enabled due to strict mode +implicit_reexport = true # enabled due to strict mode enable_error_code = [ 'ignore-without-code', 'explicit-override', @@ -252,7 +254,7 @@ filterwarnings = [ # this is apparently a known issue with snowflake connector 1.6 "module: The GenericFunction 'flatten' is already registered and is going to be overridden:sqlalchemy.exc.SAWarning", # RuntimeWarning: coroutine 'FastStream.run' was never awaited. We are already handling FastStream.run() as part of asyncio - "ignore: coroutine 'FastStream.run' was never awaited" + "ignore: coroutine 'FastStream.run' was never awaited", ] [tool.coverage.report] diff --git a/tests/integration/actions/conftest.py b/tests/integration/actions/conftest.py index 3ba8f1ff..82be6bcb 100644 --- a/tests/integration/actions/conftest.py +++ b/tests/integration/actions/conftest.py @@ -6,10 +6,11 @@ import great_expectations.exceptions as gx_exceptions import pandas as pd import pytest -from great_expectations.core import ExpectationConfiguration + +# TODO: ExpectationConfiguration is removed from gx core v1.0 and needs to be replaced +# from great_expectations.core import ExpectationConfiguration if TYPE_CHECKING: - from great_expectations.core import ExpectationSuite from great_expectations.data_context import CloudDataContext from great_expectations.datasource.fluent import PandasDatasource from great_expectations.datasource.fluent.pandas_datasource import DataFrameAsset @@ -110,31 +111,31 @@ def datasource_names_to_asset_names(datasource, data_asset): return {datasource.name: {data_asset.name}} -@pytest.fixture(scope="module") -def expectation_suite( - context: CloudDataContext, - data_asset: DataFrameAsset, - get_missing_expectation_suite_error_type: type[Exception], -) -> Iterator[ExpectationSuite]: - expectation_suite_name = f"{data_asset.datasource.name} | {data_asset.name}" - expectation_suite = context.add_expectation_suite( - expectation_suite_name=expectation_suite_name, - ) - expectation_suite.add_expectation( - expectation_configuration=ExpectationConfiguration( - expectation_type="expect_column_values_to_not_be_null", - kwargs={ - "column": "string", - "mostly": 1, - }, - ) - ) - _ = context.add_or_update_expectation_suite(expectation_suite=expectation_suite) - expectation_suite = context.get_expectation_suite(expectation_suite_name=expectation_suite_name) - assert ( - len(expectation_suite.expectations) == 1 - ), "Expectation Suite was not updated in the previous method call." - yield expectation_suite - context.delete_expectation_suite(expectation_suite_name=expectation_suite_name) - with pytest.raises(get_missing_expectation_suite_error_type): - context.get_expectation_suite(expectation_suite_name=expectation_suite_name) +# @pytest.fixture(scope="module") +# def expectation_suite( +# context: CloudDataContext, +# data_asset: DataFrameAsset, +# get_missing_expectation_suite_error_type: type[Exception], +# ) -> Iterator[ExpectationSuite]: +# expectation_suite_name = f"{data_asset.datasource.name} | {data_asset.name}" +# expectation_suite = context.add_expectation_suite( +# expectation_suite_name=expectation_suite_name, +# ) +# expectation_suite.add_expectation( +# expectation_configuration=ExpectationConfiguration( +# expectation_type="expect_column_values_to_not_be_null", +# kwargs={ +# "column": "string", +# "mostly": 1, +# }, +# ) +# ) +# _ = context.add_or_update_expectation_suite(expectation_suite=expectation_suite) +# expectation_suite = context.get_expectation_suite(expectation_suite_name=expectation_suite_name) +# assert ( +# len(expectation_suite.expectations) == 1 +# ), "Expectation Suite was not updated in the previous method call." +# yield expectation_suite +# context.delete_expectation_suite(expectation_suite_name=expectation_suite_name) +# with pytest.raises(get_missing_expectation_suite_error_type): +# context.get_expectation_suite(expectation_suite_name=expectation_suite_name) diff --git a/tests/integration/actions/test_checkpoint_action.py b/tests/integration/actions/test_checkpoint_action.py index cd5206ad..20eb391e 100644 --- a/tests/integration/actions/test_checkpoint_action.py +++ b/tests/integration/actions/test_checkpoint_action.py @@ -80,6 +80,7 @@ def checkpoint_event(checkpoint, datasource_names_to_asset_names, org_id_env_var ) +@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_checkpoint_action( context, checkpoint_event, cloud_base_url: str, org_id_env_var: str, token_env_var: str ): diff --git a/tests/integration/actions/test_draft_datasource_config_action.py b/tests/integration/actions/test_draft_datasource_config_action.py index f9aa46d7..4fafbde5 100644 --- a/tests/integration/actions/test_draft_datasource_config_action.py +++ b/tests/integration/actions/test_draft_datasource_config_action.py @@ -16,6 +16,7 @@ pytestmark = pytest.mark.integration +@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_draft_datasource_config_action( context: CloudDataContext, cloud_base_url: str, @@ -99,6 +100,7 @@ def test_running_draft_datasource_config_action( ) +@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_draft_datasource_config_action_fails_for_unreachable_datasource( context: CloudDataContext, cloud_base_url: str, org_id_env_var: str, token_env_var: str ): diff --git a/tests/integration/actions/test_list_table_names.py b/tests/integration/actions/test_list_table_names.py index f071e699..3f9c618d 100644 --- a/tests/integration/actions/test_list_table_names.py +++ b/tests/integration/actions/test_list_table_names.py @@ -15,6 +15,7 @@ pytestmark = pytest.mark.integration +@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_list_table_names_action( context: CloudDataContext, cloud_base_url: str, @@ -89,6 +90,7 @@ def test_running_list_table_names_action( ) +@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_list_table_names_action_fails_for_unreachable_datasource( context: CloudDataContext, cloud_base_url: str, org_id_env_var: str, token_env_var: str ): diff --git a/tests/integration/actions/test_metric_list_action.py b/tests/integration/actions/test_metric_list_action.py index cdcf345f..3383e4f9 100644 --- a/tests/integration/actions/test_metric_list_action.py +++ b/tests/integration/actions/test_metric_list_action.py @@ -108,6 +108,7 @@ def local_mercury_db_organizations_table_asset( yield data_asset +@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_metric_list_action( context: CloudDataContext, graphql_test_client, diff --git a/tests/integration/actions/test_run_scheduled_checkpoint.py b/tests/integration/actions/test_run_scheduled_checkpoint.py index 2efdc143..22f8e824 100644 --- a/tests/integration/actions/test_run_scheduled_checkpoint.py +++ b/tests/integration/actions/test_run_scheduled_checkpoint.py @@ -83,6 +83,7 @@ def checkpoint_event(scheduled_checkpoint, datasource_names_to_asset_names, org_ ) +@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_checkpoint_action( context, checkpoint_event, cloud_base_url: str, org_id_env_var: str, token_env_var: str ): From c1a92911d6b9d713e1d68dbe771c118ddb75879f Mon Sep 17 00:00:00 2001 From: Thu Pham Date: Fri, 20 Sep 2024 13:23:00 -0700 Subject: [PATCH 03/29] Update other gx version --- poetry.lock | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9492ea08..c16525a8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2977,4 +2977,4 @@ snowflake = ["snowflake-connector-python", "snowflake-sqlalchemy"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "87cfab0a02a2e5be9a696a917ac4005f5c66049b9a8611c56b119fa4c8bb96eb" +content-hash = "0a63f0f72ab8dd62fc92f30707f9af49c61178f329fdc92d2b31e6089dd36852" diff --git a/pyproject.toml b/pyproject.toml index 5f1dd1ce..67ebae50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ postgres = ["sqlalchemy", "psycopg2-binary"] databricks = ["databricks-sql-connector"] [tool.poetry.group.sql.dependencies] -great-expectations = { version = ">=0.18.19" } +great-expectations = { version = ">=1.0.0" } snowflake-sqlalchemy = ">=1.6" snowflake-connector-python = ">=3.3.1" psycopg2-binary = "^2.9.9" From 93302fdf72acb2cc817cab8d96ce1c80b970a560 Mon Sep 17 00:00:00 2001 From: Thu Pham Date: Fri, 20 Sep 2024 13:30:11 -0700 Subject: [PATCH 04/29] Updated for type check --- great_expectations_cloud/agent/agent.py | 10 +++++----- great_expectations_cloud/agent/config.py | 2 +- great_expectations_cloud/agent/event_handler.py | 2 +- tests/agent/conftest.py | 6 +++--- tests/integration/conftest.py | 2 +- tests/test_project.py | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/great_expectations_cloud/agent/agent.py b/great_expectations_cloud/agent/agent.py index b841ff56..ef8c0d93 100644 --- a/great_expectations_cloud/agent/agent.py +++ b/great_expectations_cloud/agent/agent.py @@ -73,7 +73,7 @@ class GXAgentConfig(AgentBaseExtraForbid): queue: str connection_string: AmqpDsn # pydantic will coerce this string to AnyUrl type - gx_cloud_base_url: AnyUrl = CLOUD_DEFAULT_BASE_URL # type: ignore[assignment] # pydantic will coerce + gx_cloud_base_url: AnyUrl = CLOUD_DEFAULT_BASE_URL gx_cloud_organization_id: str gx_cloud_access_token: str @@ -326,9 +326,9 @@ def _handle_event_as_thread_exit( extra={ "event_type": event_context.event.type, "correlation_id": event_context.correlation_id, - "job_duration": result.job_duration.total_seconds() - if result.job_duration - else None, + "job_duration": ( + result.job_duration.total_seconds() if result.job_duration else None + ), "organization_id": str(org_id), }, ) @@ -492,7 +492,7 @@ def _set_http_session_headers( Note: the Agent-Job-Id header value will be set for all GX Cloud request until this method is called again. """ - from great_expectations import __version__ # type: ignore[attr-defined] # TODO: fix this + from great_expectations import __version__ from great_expectations.core import http from great_expectations.data_context.store.gx_cloud_store_backend import GXCloudStoreBackend diff --git a/great_expectations_cloud/agent/config.py b/great_expectations_cloud/agent/config.py index e4d43464..b3f8b3dc 100644 --- a/great_expectations_cloud/agent/config.py +++ b/great_expectations_cloud/agent/config.py @@ -6,7 +6,7 @@ class GxAgentEnvVars(BaseSettings): # pydantic will coerce this string to AnyUrl type - gx_cloud_base_url: AnyUrl = CLOUD_DEFAULT_BASE_URL # type: ignore[assignment] + gx_cloud_base_url: AnyUrl = CLOUD_DEFAULT_BASE_URL gx_cloud_organization_id: str gx_cloud_access_token: str diff --git a/great_expectations_cloud/agent/event_handler.py b/great_expectations_cloud/agent/event_handler.py index 478e5495..3eec8402 100644 --- a/great_expectations_cloud/agent/event_handler.py +++ b/great_expectations_cloud/agent/event_handler.py @@ -154,7 +154,7 @@ def _get_major_version(version: str) -> str: return str(parsed.major) -version = gx.__version__ # type: ignore[attr-defined] # TODO: fix this +version = gx.__version__ _GX_MAJOR_VERSION = _get_major_version(str(version)) diff --git a/tests/agent/conftest.py b/tests/agent/conftest.py index e6524e6a..01e95b60 100644 --- a/tests/agent/conftest.py +++ b/tests/agent/conftest.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Any, Iterable, Literal, NamedTuple, TypedDict import pytest -from great_expectations import ( # type: ignore[attr-defined] # TODO: fix this +from great_expectations import ( __version__ as gx_version, ) from great_expectations.data_context import CloudDataContext @@ -50,7 +50,7 @@ def _mock_get_lastest_version_from_pypi(self) -> Version: @pytest.fixture def mock_context(mocker: MockerFixture) -> CloudDataContext: """Returns a `MagicMock` of a `CloudDataContext` for testing purposes.""" - return mocker.MagicMock(autospec=CloudDataContext) # type: ignore[no-any-return] #TODO: fix this + return mocker.MagicMock(autospec=CloudDataContext) class FakeMessagePayload(NamedTuple): @@ -90,7 +90,7 @@ def consume(self, queue: str, on_message: OnMessageCallback) -> None: event, correlation_id = self.test_queue.pop() LOGGER.info(f"FakeSubscriber.consume() received -> {event!r}") event_context = EventContext( - event=event, + event=event, # type: ignore[arg-type] # In tests, could be a DummyEvent correlation_id=correlation_id, processed_successfully=lambda: None, processed_with_failures=lambda: None, diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 97b1e4fe..e8116b85 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -32,7 +32,7 @@ def token_env_var() -> str: @pytest.fixture(scope="module") def context(org_id_env_var: str, token_env_var: str) -> CloudDataContext: - context = gx.get_context( # type: ignore[attr-defined] # TODO: fix this + context = gx.get_context( mode="cloud", cloud_base_url=os.environ.get("GX_CLOUD_BASE_URL"), cloud_organization_id=org_id_env_var, diff --git a/tests/test_project.py b/tests/test_project.py index ab5fae21..4873a31f 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -48,7 +48,7 @@ def min_gx_version() -> Version: def test_great_expectations_is_installed(min_gx_version): import great_expectations - assert Version(great_expectations.__version__) >= min_gx_version # type: ignore[attr-defined] # TODO: fix this + assert Version(great_expectations.__version__) >= min_gx_version @pytest.fixture From c1db7c5d08474f9bcd805cf60ded6a71f6f7f02e Mon Sep 17 00:00:00 2001 From: Anthony Burdi Date: Wed, 2 Oct 2024 17:46:02 -0400 Subject: [PATCH 05/29] WIP v0 version (no tests) --- .../agent/actions/run_checkpoint.py | 9 ++++-- .../agent/actions/run_scheduled_checkpoint.py | 4 +-- .../agent/actions/run_window_checkpoint.py | 31 ++++++++++++++++--- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_checkpoint.py b/great_expectations_cloud/agent/actions/run_checkpoint.py index 9cef2155..b4b19d0b 100644 --- a/great_expectations_cloud/agent/actions/run_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_checkpoint.py @@ -26,13 +26,14 @@ class RunCheckpointAction(AgentAction[RunCheckpointEvent]): @override def run(self, event: RunCheckpointEvent, id: str) -> ActionResult: - return run_checkpoint(self._context, event, id) + return run_checkpoint_v0(self._context, event, id) -def run_checkpoint( +def run_checkpoint_v0( context: CloudDataContext, event: RunCheckpointEvent | RunScheduledCheckpointEvent | RunWindowCheckpointEvent, id: str, + evaluation_parameters: dict | None = None, ) -> ActionResult: """Note: the logic for this action is broken out into this function so that the same logic can be used for both RunCheckpointEvent and RunScheduledCheckpointEvent.""" @@ -45,9 +46,13 @@ def run_checkpoint( ) in data_asset_names: # only test connection for assets that are validated in checkpoint asset = datasource.get_asset(data_asset_name) asset.test_connection() # raises `TestConnectionError` on failure + + if evaluation_parameters is None: + evaluation_parameters = {} checkpoint_run_result = context.run_checkpoint( ge_cloud_id=event.checkpoint_id, batch_request={"options": event.splitter_options} if event.splitter_options else None, + evaluation_parameters=evaluation_parameters, ) validation_results = checkpoint_run_result.run_results diff --git a/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py b/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py index 343923af..759751be 100644 --- a/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py @@ -6,7 +6,7 @@ ActionResult, AgentAction, ) -from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint +from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint_v0 from great_expectations_cloud.agent.event_handler import register_event_action from great_expectations_cloud.agent.models import ( RunScheduledCheckpointEvent, @@ -19,7 +19,7 @@ class RunScheduledCheckpointAction(AgentAction[RunScheduledCheckpointEvent]): @override def run(self, event: RunScheduledCheckpointEvent, id: str) -> ActionResult: - return run_checkpoint(self._context, event, id) + return run_checkpoint_v0(self._context, event, id) register_event_action("0", RunScheduledCheckpointEvent, RunScheduledCheckpointAction) diff --git a/great_expectations_cloud/agent/actions/run_window_checkpoint.py b/great_expectations_cloud/agent/actions/run_window_checkpoint.py index 3636b965..9b5775c3 100644 --- a/great_expectations_cloud/agent/actions/run_window_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_window_checkpoint.py @@ -1,12 +1,14 @@ from __future__ import annotations +from great_expectations.core.http import create_session +from great_expectations.exceptions import GXCloudError from typing_extensions import override from great_expectations_cloud.agent.actions.agent_action import ( ActionResult, AgentAction, ) -from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint +from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint_v0 from great_expectations_cloud.agent.event_handler import register_event_action from great_expectations_cloud.agent.models import ( RunWindowCheckpointEvent, @@ -19,9 +21,30 @@ class RunWindowCheckpointAction(AgentAction[RunWindowCheckpointEvent]): @override def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: - # TODO: https://greatexpectations.atlassian.net/browse/ZELDA-922 - # This currently only runs a normal checkpoint. Logic for window checkpoints needs to be added (e.g. call the backend to get the params and then construct the evaluation_parameters before passing them into context.run_checkpoint()) One way we can do this via a param in `run_checkpoint()` that takes a function to build the evaluation_parameters, defaulting to a noop for the other checkpoint action types. - return run_checkpoint(self._context, event, id) + with create_session(access_token=self._auth_key) as session: + expectation_parameters_for_checkpoint_url = f"{self._base_url}api/v1/organizations/" + f"{self._organization_id}/checkpoints/{event.checkpoint_id}/expectation-parameters" + response = session.get(url=expectation_parameters_for_checkpoint_url) + + if not response.ok: + raise GXCloudError( + message=f"RunWindowCheckpointAction encountered an error while connecting to GX Cloud. " + f"Unable to retrieve expectation_parameters for Checkpoint with ID={event.checkpoint_id}.", + response=response, + ) + data = response.json() + try: + expectation_parameters = data["data"]["expectation_parameters"] + except KeyError as e: + raise GXCloudError( + message="Malformed response received from GX Cloud", + response=response, + ) from e + + # Note: In v0 expectation_parameters are called evaluation_parameters. + return run_checkpoint_v0( + self._context, event, id, evaluation_parameters=expectation_parameters + ) register_event_action("0", RunWindowCheckpointEvent, RunWindowCheckpointAction) From d200de21d9ab0d006d8015e13c04fd5ac49351ee Mon Sep 17 00:00:00 2001 From: Great Expectations Date: Wed, 2 Oct 2024 21:59:50 +0000 Subject: [PATCH 06/29] Pre-release version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 097d0eda..83f1c8e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "great_expectations_cloud" -version = "20241002.0.dev0" +version = "20241002.0.dev1" description = "Great Expectations Cloud" authors = ["The Great Expectations Team "] repository = "https://github.com/great-expectations/cloud" From b5e51f80bc3d12d03ecbca790ffae4a607673004 Mon Sep 17 00:00:00 2001 From: T Pham Date: Thu, 3 Oct 2024 09:27:30 -0700 Subject: [PATCH 07/29] Update integration tests (#452) Co-authored-by: Great Expectations Co-authored-by: Tyler Hoffman Co-authored-by: rreinoldsc <85508632+rreinoldsc@users.noreply.github.com> Co-authored-by: Jessica Saavedra Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/containerize-agent.yaml | 8 ++- README.md | 2 +- docker-compose.yml | 6 +- .../agent/actions/run_metric_list_action.py | 1 + pyproject.toml | 2 +- tests/integration/actions/conftest.py | 64 +++++++++---------- .../actions/test_metric_list_action.py | 4 +- 7 files changed, 45 insertions(+), 42 deletions(-) diff --git a/.github/workflows/containerize-agent.yaml b/.github/workflows/containerize-agent.yaml index 105304cd..41a089d7 100644 --- a/.github/workflows/containerize-agent.yaml +++ b/.github/workflows/containerize-agent.yaml @@ -117,13 +117,17 @@ jobs: id: get_version run: echo "POETRY_VERSION=$(poetry version -s)" >> $GITHUB_OUTPUT + - name: Get is_dev from pyproject.toml + id: get_is_dev + run: echo "IS_DEV=$(poetry version -s | grep -q 'dev' && echo true || echo false)" >> $GITHUB_OUTPUT + - name: Get is_release from pyproject.toml id: get_is_release - run: echo "IS_RELEASE=$(poetry version -s | grep -q 'dev' && echo false || echo true)" >> $GITHUB_OUTPUT + run: echo "IS_RELEASE=$(poetry version -s | grep -q '[A-Za-z ]*' && echo false || echo true)" >> $GITHUB_OUTPUT # Uses the version from pyproject.toml for the tag - name: Push Pre-Release to Docker Hub and Internal ECR - if: ${{ steps.get_is_release.outputs.IS_RELEASE == 'false' }} + if: ${{ steps.get_is_dev.outputs.IS_DEV == 'true' }} uses: docker/build-push-action@v5 with: context: . diff --git a/README.md b/README.md index 1c5bf25c..04b4b245 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ To use the GX Agent, you will need to have a Great Expectations Cloud account. You can sign up for free at [https://app.greatexpectations.io](https://app.greatexpectations.io). -Deployment instructions for the GX Agent can be found in the [GX Cloud documentation](https://docs.greatexpectations.io/docs/cloud/deploy_gx_agent). +Deployment instructions for the GX Agent can be found in the [GX Cloud documentation](https://docs.greatexpectations.io/docs/cloud/deploy/deploy_gx_agent). ## Dev Setup diff --git a/docker-compose.yml b/docker-compose.yml index dadef8f1..017bc828 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,12 +43,14 @@ services: - mq mercury-service-api: - image: 258143015559.dkr.ecr.us-east-1.amazonaws.com/mercury/api + platform: linux/amd64 + image: 258143015559.dkr.ecr.us-east-1.amazonaws.com/mercury/api:v1api-latest restart: always volumes: - ./services/ge_cloud/:/code ports: - - 5000:5000 + # V1 runs on external port 7000 + - 5000:7000 environment: LOGGING_LEVEL: ${LOGGING_LEVEL} ENVIRONMENT: ${ENVIRONMENT} diff --git a/great_expectations_cloud/agent/actions/run_metric_list_action.py b/great_expectations_cloud/agent/actions/run_metric_list_action.py index e6c43d0c..7f898ba6 100644 --- a/great_expectations_cloud/agent/actions/run_metric_list_action.py +++ b/great_expectations_cloud/agent/actions/run_metric_list_action.py @@ -88,3 +88,4 @@ def _raise_on_any_metric_exception(self, metric_run: MetricRun) -> None: register_event_action("0", RunMetricsListEvent, MetricListAction) +register_event_action("1", RunMetricsListEvent, MetricListAction) diff --git a/pyproject.toml b/pyproject.toml index 03b5085a..43abf004 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "great_expectations_cloud" -version = "20240922.0.a0" +version = "20240930.0.a0" description = "Great Expectations Cloud" authors = ["The Great Expectations Team "] repository = "https://github.com/great-expectations/cloud" diff --git a/tests/integration/actions/conftest.py b/tests/integration/actions/conftest.py index 82be6bcb..5ad4dfd5 100644 --- a/tests/integration/actions/conftest.py +++ b/tests/integration/actions/conftest.py @@ -3,13 +3,11 @@ import uuid from typing import TYPE_CHECKING, Iterator +import great_expectations as gx import great_expectations.exceptions as gx_exceptions import pandas as pd import pytest -# TODO: ExpectationConfiguration is removed from gx core v1.0 and needs to be replaced -# from great_expectations.core import ExpectationConfiguration - if TYPE_CHECKING: from great_expectations.data_context import CloudDataContext from great_expectations.datasource.fluent import PandasDatasource @@ -88,11 +86,11 @@ def data_asset( _ = datasource.add_dataframe_asset( name=asset_name, ) - data_asset = datasource.get_asset(asset_name=asset_name) + data_asset = datasource.get_asset(name=asset_name) yield data_asset - datasource.delete_asset(asset_name=asset_name) + datasource.delete_asset(name=asset_name) with pytest.raises(get_missing_data_asset_error_type): - datasource.get_asset(asset_name=asset_name) + datasource.get_asset(name=asset_name) @pytest.fixture(scope="module") @@ -111,31 +109,29 @@ def datasource_names_to_asset_names(datasource, data_asset): return {datasource.name: {data_asset.name}} -# @pytest.fixture(scope="module") -# def expectation_suite( -# context: CloudDataContext, -# data_asset: DataFrameAsset, -# get_missing_expectation_suite_error_type: type[Exception], -# ) -> Iterator[ExpectationSuite]: -# expectation_suite_name = f"{data_asset.datasource.name} | {data_asset.name}" -# expectation_suite = context.add_expectation_suite( -# expectation_suite_name=expectation_suite_name, -# ) -# expectation_suite.add_expectation( -# expectation_configuration=ExpectationConfiguration( -# expectation_type="expect_column_values_to_not_be_null", -# kwargs={ -# "column": "string", -# "mostly": 1, -# }, -# ) -# ) -# _ = context.add_or_update_expectation_suite(expectation_suite=expectation_suite) -# expectation_suite = context.get_expectation_suite(expectation_suite_name=expectation_suite_name) -# assert ( -# len(expectation_suite.expectations) == 1 -# ), "Expectation Suite was not updated in the previous method call." -# yield expectation_suite -# context.delete_expectation_suite(expectation_suite_name=expectation_suite_name) -# with pytest.raises(get_missing_expectation_suite_error_type): -# context.get_expectation_suite(expectation_suite_name=expectation_suite_name) +@pytest.fixture(scope="module") +def expectation_suite( + context: CloudDataContext, + data_asset: DataFrameAsset, + get_missing_expectation_suite_error_type: type[Exception], +) -> Iterator[gx.ExpectationSuite]: + expectation_suite_name = f"{data_asset.datasource.name} | {data_asset.name}" + expectation_suite = gx.ExpectationSuite(name=expectation_suite_name) + context.suites.add(expectation_suite) + + expectation = gx.expectations.ExpectColumnValuesToNotBeNullExpectation( + column="string", + mostly=1, + ) + expectation_suite.add_expectation( + expectation=expectation, + ) + + expectation_suite = context.suites.get(name=expectation_suite_name) + assert ( + len(expectation_suite.expectations) == 1 + ), "Expectation Suite was not updated in the previous method call." + yield expectation_suite + context.suites.delete(name=expectation_suite_name) + with pytest.raises(get_missing_expectation_suite_error_type): + context.suites.get(name=expectation_suite_name) diff --git a/tests/integration/actions/test_metric_list_action.py b/tests/integration/actions/test_metric_list_action.py index 3383e4f9..270eb57d 100644 --- a/tests/integration/actions/test_metric_list_action.py +++ b/tests/integration/actions/test_metric_list_action.py @@ -95,7 +95,7 @@ def local_mercury_db_datasource( context: CloudDataContext, ) -> PostgresDatasource: datasource_name = "local_mercury_db" - datasource = context.get_datasource(datasource_name=datasource_name) + datasource = context.get_datasource(name=datasource_name) yield datasource @@ -104,7 +104,7 @@ def local_mercury_db_organizations_table_asset( local_mercury_db_datasource: PostgresDatasource, ) -> TableAsset: data_asset_name = "local-mercury-db-organizations-table" - data_asset = local_mercury_db_datasource.get_asset(asset_name=data_asset_name) + data_asset = local_mercury_db_datasource.get_asset(name=data_asset_name) yield data_asset From 57963929118da9f62f719e2975db8473880f4af5 Mon Sep 17 00:00:00 2001 From: rreinoldsc <85508632+rreinoldsc@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:18:15 -0400 Subject: [PATCH 08/29] Upgrade draft data source config action for v1 (#455) Co-authored-by: T Pham Co-authored-by: Thu Pham Co-authored-by: Great Expectations Co-authored-by: Tyler Hoffman Co-authored-by: Jessica Saavedra Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../actions/draft_datasource_config_action.py | 18 ++--- .../actions/test_draft_datasource_config.py | 68 +++++++++++-------- .../test_draft_datasource_config_action.py | 1 - 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/great_expectations_cloud/agent/actions/draft_datasource_config_action.py b/great_expectations_cloud/agent/actions/draft_datasource_config_action.py index 5c34ceee..50449094 100644 --- a/great_expectations_cloud/agent/actions/draft_datasource_config_action.py +++ b/great_expectations_cloud/agent/actions/draft_datasource_config_action.py @@ -50,7 +50,7 @@ def check_draft_datasource_config( "fluent-style Data Source." ) try: - datasource_cls = self._context.sources.type_lookup[datasource_type] + datasource_cls = self._context.data_sources.type_lookup[datasource_type] except LookupError as exc: raise TypeError( # noqa: TRY003 # one off error "DraftDatasourceConfigAction received an unknown Data Source type." @@ -75,10 +75,10 @@ def _get_table_names(self, datasource: Datasource) -> list[str]: def _update_table_names_list(self, config_id: UUID, table_names: list[str]) -> None: with create_session(access_token=self._auth_key) as session: - response = session.patch( - url=f"{self._base_url}/organizations/" - f"{self._organization_id}/datasources/drafts/{config_id}", - json={"table_names": table_names}, + url = f"{self._base_url}/api/v1/organizations/{self._organization_id}/draft-table-names/{config_id}" + response = session.put( + url=url, + json={"data": {"table_names": table_names}}, ) if not response.ok: raise RuntimeError( # noqa: TRY003 # one off error @@ -90,8 +90,8 @@ def _update_table_names_list(self, config_id: UUID, table_names: list[str]) -> N def get_draft_config(self, config_id: UUID) -> dict[str, Any]: resource_url = ( - f"{self._base_url}/organizations/" - f"{self._organization_id}/datasources/drafts/{config_id}" + f"{self._base_url}/api/v1/organizations/" + f"{self._organization_id}/draft-datasources/{config_id}" ) with create_session(access_token=self._auth_key) as session: response = session.get(resource_url) @@ -102,11 +102,11 @@ def get_draft_config(self, config_id: UUID) -> dict[str, Any]: ) data = response.json() try: - return data["data"]["attributes"]["draft_config"] # type: ignore[no-any-return] + return data["data"]["config"] # type: ignore[no-any-return] except KeyError as e: raise RuntimeError( # noqa: TRY003 # one off error "Malformed response received from GX Cloud" ) from e -register_event_action("0", DraftDatasourceConfigEvent, DraftDatasourceConfigAction) +register_event_action("1", DraftDatasourceConfigEvent, DraftDatasourceConfigAction) diff --git a/tests/agent/actions/test_draft_datasource_config.py b/tests/agent/actions/test_draft_datasource_config.py index 0cf4dcb7..bc22164e 100644 --- a/tests/agent/actions/test_draft_datasource_config.py +++ b/tests/agent/actions/test_draft_datasource_config.py @@ -48,7 +48,7 @@ def build_get_draft_config_payload( "data": { "type": "draft_config", "id": str(id), - "attributes": {"draft_config": config}, + "config": config, } } @@ -74,8 +74,8 @@ def test_test_draft_datasource_config_success_non_sql_ds( job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") event = DraftDatasourceConfigEvent(config_id=config_id, organization_id=uuid.uuid4()) expected_url: str = ( - f"{env_vars.gx_cloud_base_url}/organizations/{env_vars.gx_cloud_organization_id}" - f"/datasources/drafts/{config_id}" + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-datasources/{config_id}" ) responses.get( @@ -107,7 +107,7 @@ def test_test_draft_datasource_config_success_sql_ds( datasource_cls = mocker.Mock( spec=SnowflakeDatasource, return_value=mocker.Mock(spec=SnowflakeDatasource) ) - mock_context.sources.type_lookup = {ds_type: datasource_cls} + mock_context.data_sources.type_lookup = {ds_type: datasource_cls} datasource_config = { "name": "test_snowflake_ds", @@ -142,20 +142,25 @@ def test_test_draft_datasource_config_success_sql_ds( job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") event = DraftDatasourceConfigEvent(config_id=config_id, organization_id=uuid.uuid4()) - expected_url: str = ( - f"{env_vars.gx_cloud_base_url}/organizations/{env_vars.gx_cloud_organization_id}" - f"/datasources/drafts/{config_id}" + expected_url_get: str = ( + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-datasources/{config_id}" + ) + + expected_url_put: str = ( + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-table-names/{config_id}" ) responses.get( - url=expected_url, + url=expected_url_get, json=build_get_draft_config_payload(config=datasource_config, id=config_id), ) # match will fail if patch not called with correct json data - responses.patch( - url=expected_url, + responses.put( + url=expected_url_put, status=204, - match=[responses.matchers.json_params_matcher({"table_names": table_names})], + match=[responses.matchers.json_params_matcher({"data": {"table_names": table_names}})], ) action_result = action.run(event=event, id=str(job_id)) @@ -181,7 +186,7 @@ def test_test_draft_datasource_config_sql_ds_raises_on_patch_failure( datasource_cls = mocker.Mock( spec=SnowflakeDatasource, return_value=mocker.Mock(spec=SnowflakeDatasource) ) - mock_context.sources.type_lookup = {ds_type: datasource_cls} + mock_context.data_sources.type_lookup = {ds_type: datasource_cls} datasource_config = { "name": "test_snowflake_ds", @@ -212,20 +217,25 @@ def test_test_draft_datasource_config_sql_ds_raises_on_patch_failure( job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") event = DraftDatasourceConfigEvent(config_id=config_id, organization_id=uuid.uuid4()) - expected_url: str = ( - f"{env_vars.gx_cloud_base_url}/organizations/{env_vars.gx_cloud_organization_id}" - f"/datasources/drafts/{config_id}" + + expected_url_get: str = ( + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-datasources/{config_id}" ) + expected_url_put: str = ( + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-table-names/{config_id}" + ) responses.get( - url=expected_url, + url=expected_url_get, json=build_get_draft_config_payload(config=datasource_config, id=config_id), ) # match will fail if patch not called with correct json data - responses.patch( - url=expected_url, + responses.put( + url=expected_url_put, status=404, - match=[responses.matchers.json_params_matcher({"table_names": table_names})], + match=[responses.matchers.json_params_matcher({"data": {"table_names": table_names}})], ) with pytest.raises(RuntimeError, match="Unable to update table_names for Draft Config with ID"): @@ -252,11 +262,11 @@ def test_test_draft_datasource_config_failure( job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") event = DraftDatasourceConfigEvent(config_id=config_id, organization_id=uuid.uuid4()) expected_url = ( - f"{env_vars.gx_cloud_base_url}/organizations/{env_vars.gx_cloud_organization_id}" - f"/datasources/drafts/{config_id}" + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-datasources/{config_id}" ) datasource_cls = mocker.Mock(autospec=SQLDatasource) - mock_context.sources.type_lookup = {ds_type: datasource_cls} + mock_context.data_sources.type_lookup = {ds_type: datasource_cls} datasource_cls.return_value.test_connection.side_effect = TestConnectionError responses.get( @@ -285,8 +295,8 @@ def test_test_draft_datasource_config_raises_for_non_fds(mock_context, set_requi job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") event = DraftDatasourceConfigEvent(config_id=config_id, organization_id=uuid.uuid4()) expected_url = ( - f"{env_vars.gx_cloud_base_url}/organizations/{env_vars.gx_cloud_organization_id}" - f"/datasources/drafts/{config_id}" + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-datasources/{config_id}" ) responses.get( url=expected_url, @@ -352,11 +362,11 @@ def test_test_draft_datasource_config_raises_for_unknown_type( job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") event = DraftDatasourceConfigEvent(config_id=config_id, organization_id=uuid.uuid4()) expected_url = ( - f"{env_vars.gx_cloud_base_url}/organizations/{env_vars.gx_cloud_organization_id}" - f"/datasources/drafts/{config_id}" + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-datasources/{config_id}" ) - mock_context.sources.type_lookup = {} + mock_context.data_sources.type_lookup = {} responses.get( url=expected_url, @@ -386,8 +396,8 @@ def test_test_draft_datasource_config_raises_for_cloud_backend_error( job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") event = DraftDatasourceConfigEvent(config_id=config_id, organization_id=uuid.uuid4()) expected_url = ( - f"{env_vars.gx_cloud_base_url}/organizations/{env_vars.gx_cloud_organization_id}" - f"/datasources/drafts/{config_id}" + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/draft-datasources/{config_id}" ) responses.get( diff --git a/tests/integration/actions/test_draft_datasource_config_action.py b/tests/integration/actions/test_draft_datasource_config_action.py index 4fafbde5..a4257e72 100644 --- a/tests/integration/actions/test_draft_datasource_config_action.py +++ b/tests/integration/actions/test_draft_datasource_config_action.py @@ -16,7 +16,6 @@ pytestmark = pytest.mark.integration -@pytest.mark.skip("Skipping integration tests until they are updated for v1.0") def test_running_draft_datasource_config_action( context: CloudDataContext, cloud_base_url: str, From 71984e554065b199d6be7261086950695fe2017a Mon Sep 17 00:00:00 2001 From: Ship Date: Thu, 3 Oct 2024 15:29:00 -0600 Subject: [PATCH 09/29] add RunWindowCheckpointAction to available actions __init__ --- great_expectations_cloud/agent/actions/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/great_expectations_cloud/agent/actions/__init__.py b/great_expectations_cloud/agent/actions/__init__.py index 2cbf1601..e8a7cb4e 100644 --- a/great_expectations_cloud/agent/actions/__init__.py +++ b/great_expectations_cloud/agent/actions/__init__.py @@ -16,3 +16,4 @@ from great_expectations_cloud.agent.actions.run_scheduled_checkpoint import ( RunScheduledCheckpointAction, ) +from great_expectations_cloud.agent.actions.run_window_checkpoint import RunWindowCheckpointAction From 726969fe8934ef76c7125cb404064153c2d0767e Mon Sep 17 00:00:00 2001 From: Ship Date: Thu, 3 Oct 2024 16:27:18 -0600 Subject: [PATCH 10/29] add leading slash to api url --- great_expectations_cloud/agent/actions/run_window_checkpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/great_expectations_cloud/agent/actions/run_window_checkpoint.py b/great_expectations_cloud/agent/actions/run_window_checkpoint.py index 9b5775c3..eb03e491 100644 --- a/great_expectations_cloud/agent/actions/run_window_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_window_checkpoint.py @@ -22,7 +22,7 @@ class RunWindowCheckpointAction(AgentAction[RunWindowCheckpointEvent]): @override def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: with create_session(access_token=self._auth_key) as session: - expectation_parameters_for_checkpoint_url = f"{self._base_url}api/v1/organizations/" + expectation_parameters_for_checkpoint_url = f"{self._base_url}/api/v1/organizations/" f"{self._organization_id}/checkpoints/{event.checkpoint_id}/expectation-parameters" response = session.get(url=expectation_parameters_for_checkpoint_url) From d0f4c998cf854fb91260d97e6591a899d6cb1a21 Mon Sep 17 00:00:00 2001 From: Josh Stauffer <66793731+joshua-stauffer@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:30:12 +0200 Subject: [PATCH 11/29] update url to retrieve cloud config --- great_expectations_cloud/agent/agent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/great_expectations_cloud/agent/agent.py b/great_expectations_cloud/agent/agent.py index ef8c0d93..5c5e1ea5 100644 --- a/great_expectations_cloud/agent/agent.py +++ b/great_expectations_cloud/agent/agent.py @@ -388,7 +388,7 @@ def _get_config(cls) -> GXAgentConfig: # obtain the broker url and queue name from Cloud agent_sessions_url = ( - f"{env_vars.gx_cloud_base_url}/organizations/" + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/" f"{env_vars.gx_cloud_organization_id}/agent-sessions" ) From ce44e6214808b6ec45a6cfcbae1f6b501861a08e Mon Sep 17 00:00:00 2001 From: Josh Stauffer <66793731+joshua-stauffer@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:19:55 +0200 Subject: [PATCH 12/29] update core a gent requests to use v1 endpoints --- great_expectations_cloud/agent/agent.py | 8 +++++--- great_expectations_cloud/agent/models.py | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/great_expectations_cloud/agent/agent.py b/great_expectations_cloud/agent/agent.py index 5c5e1ea5..02a05780 100644 --- a/great_expectations_cloud/agent/agent.py +++ b/great_expectations_cloud/agent/agent.py @@ -47,6 +47,7 @@ JobStatus, ScheduledEventBase, UnknownEvent, + UpdateJobStatusRequest, build_failed_job_completed_status, ) @@ -430,10 +431,11 @@ def _update_status(self, job_id: str, status: JobStatus, org_id: UUID) -> None: extra={"job_id": job_id, "status": str(status), "organization_id": str(org_id)}, ) agent_sessions_url = ( - f"{self._config.gx_cloud_base_url}/organizations/{org_id}" + f"/agent-jobs/{job_id}" + f"{self._config.gx_cloud_base_url}/api/v1/organizations/{org_id}" + + f"/agent-jobs/{job_id}" ) with create_session(access_token=self.get_auth_key()) as session: - data = status.json() + data = UpdateJobStatusRequest(data=status).json() session.patch(agent_sessions_url, data=data) LOGGER.info( "Status updated", @@ -462,7 +464,7 @@ def _create_scheduled_job_and_set_started( ) agent_sessions_url = ( - f"{self._config.gx_cloud_base_url}/organizations/{org_id}" + "/agent-jobs" + f"{self._config.gx_cloud_base_url}/api/v1/organizations/{org_id}" + "/agent-jobs" ) with create_session(access_token=self.get_auth_key()) as session: payload = Payload(data=data) diff --git a/great_expectations_cloud/agent/models.py b/great_expectations_cloud/agent/models.py index 388b7f80..05bf0832 100644 --- a/great_expectations_cloud/agent/models.py +++ b/great_expectations_cloud/agent/models.py @@ -146,6 +146,10 @@ class JobCompleted(AgentBaseExtraForbid): JobStatus = Union[JobStarted, JobCompleted] +class UpdateJobStatusRequest(AgentBaseExtraForbid): + data: JobStatus + + def build_failed_job_completed_status(error: BaseException) -> JobCompleted: if isinstance(error, GXCoreError): status = JobCompleted( From e6f757447b770d7702175bc5cdbb669508b245c3 Mon Sep 17 00:00:00 2001 From: Josh Stauffer <66793731+joshua-stauffer@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:24:30 +0200 Subject: [PATCH 13/29] update tests --- tests/agent/test_agent.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/agent/test_agent.py b/tests/agent/test_agent.py index 62e9c605..870977d6 100644 --- a/tests/agent/test_agent.py +++ b/tests/agent/test_agent.py @@ -33,6 +33,7 @@ JobStarted, RunOnboardingDataAssistantEvent, RunScheduledCheckpointEvent, + UpdateJobStatusRequest, ) from tests.agent.conftest import DummyEvent, FakeMessagePayload, FakeSubscriber @@ -281,11 +282,13 @@ def test_gx_agent_updates_cloud_on_job_status( ): correlation_id = "4ae63677-4dd5-4fb0-b511-870e7a286e77" url = ( - f"{gx_agent_config.gx_cloud_base_url}/organizations/" + f"{gx_agent_config.gx_cloud_base_url}/api/v1/organizations/" f"{gx_agent_config.gx_cloud_organization_id}/agent-jobs/{correlation_id}" ) - job_started_data = JobStarted().json() - job_completed = JobCompleted(success=True, created_resources=[], processed_by="agent") + job_started_data = UpdateJobStatusRequest(data=JobStarted()).json() + job_completed = UpdateJobStatusRequest( + data=JobCompleted(success=True, created_resources=[], processed_by="agent") + ) job_completed_data = job_completed.json() async def redeliver_message(): @@ -356,7 +359,7 @@ def test_gx_agent_sends_request_to_create_scheduled_job( """ correlation_id = "4ae63677-4dd5-4fb0-b511-870e7a286e77" post_url = ( - f"{gx_agent_config.gx_cloud_base_url}/organizations/" + f"{gx_agent_config.gx_cloud_base_url}/api/v1/organizations/" f"{gx_agent_config.gx_cloud_organization_id}/agent-jobs" ) From 522d108149fb4f2ff17d9a7cdd53621bad1d0c22 Mon Sep 17 00:00:00 2001 From: Josh Stauffer <66793731+joshua-stauffer@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:29:17 +0200 Subject: [PATCH 14/29] update checkpoint action for v1 --- .../agent/actions/run_checkpoint.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_checkpoint.py b/great_expectations_cloud/agent/actions/run_checkpoint.py index 9cef2155..9370c22b 100644 --- a/great_expectations_cloud/agent/actions/run_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_checkpoint.py @@ -29,6 +29,10 @@ def run(self, event: RunCheckpointEvent, id: str) -> ActionResult: return run_checkpoint(self._context, event, id) +class MissingCheckpointNameError(ValueError): + """Property checkpoint_name is required but not present.""" + + def run_checkpoint( context: CloudDataContext, event: RunCheckpointEvent | RunScheduledCheckpointEvent | RunWindowCheckpointEvent, @@ -36,7 +40,13 @@ def run_checkpoint( ) -> ActionResult: """Note: the logic for this action is broken out into this function so that the same logic can be used for both RunCheckpointEvent and RunScheduledCheckpointEvent.""" - # TODO: move connection testing into OSS; there isn't really a reason it can't be done there + + # the checkpoint_name property on events is optional for backwards compatibility, + # but this action requires it in order to run: + if not event.checkpoint_name: + raise MissingCheckpointNameError + + # test connection to data source and any assets used by checkpoint for datasource_name, data_asset_names in event.datasource_names_to_asset_names.items(): datasource = context.get_datasource(datasource_name) datasource.test_connection(test_assets=False) # raises `TestConnectionError` on failure @@ -45,10 +55,10 @@ def run_checkpoint( ) in data_asset_names: # only test connection for assets that are validated in checkpoint asset = datasource.get_asset(data_asset_name) asset.test_connection() # raises `TestConnectionError` on failure - checkpoint_run_result = context.run_checkpoint( - ge_cloud_id=event.checkpoint_id, - batch_request={"options": event.splitter_options} if event.splitter_options else None, - ) + + # run checkpoint + checkpoint = context.checkpoints.get(name=event.checkpoint_name) + checkpoint_run_result = checkpoint.run(batch_parameters=event.splitter_options) validation_results = checkpoint_run_result.run_results created_resources = [] @@ -66,4 +76,4 @@ def run_checkpoint( ) -register_event_action("0", RunCheckpointEvent, RunCheckpointAction) +register_event_action("1", RunCheckpointEvent, RunCheckpointAction) From 24817660d7ad2aa75a201e2d0919e512424b9021 Mon Sep 17 00:00:00 2001 From: Josh Stauffer <66793731+joshua-stauffer@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:36:17 +0200 Subject: [PATCH 15/29] fix tests & tweak --- .../agent/actions/run_checkpoint.py | 4 ++-- .../checkpoints/test_run_checkpoint_action.py | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_checkpoint.py b/great_expectations_cloud/agent/actions/run_checkpoint.py index 9370c22b..b4546289 100644 --- a/great_expectations_cloud/agent/actions/run_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_checkpoint.py @@ -41,14 +41,14 @@ def run_checkpoint( """Note: the logic for this action is broken out into this function so that the same logic can be used for both RunCheckpointEvent and RunScheduledCheckpointEvent.""" - # the checkpoint_name property on events is optional for backwards compatibility, + # the checkpoint_name property on possible events is optional for backwards compatibility, # but this action requires it in order to run: if not event.checkpoint_name: raise MissingCheckpointNameError # test connection to data source and any assets used by checkpoint for datasource_name, data_asset_names in event.datasource_names_to_asset_names.items(): - datasource = context.get_datasource(datasource_name) + datasource = context.data_sources.get(name=datasource_name) datasource.test_connection(test_assets=False) # raises `TestConnectionError` on failure for ( data_asset_name diff --git a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py index 86bf1763..908becbc 100644 --- a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py +++ b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py @@ -32,6 +32,7 @@ type="run_checkpoint_request", datasource_names_to_asset_names={"Data Source 1": {"Data Asset A", "Data Asset B"}}, checkpoint_id=UUID("5f3814d6-a2e2-40f9-ba75-87ddf485c3a8"), + checkpoint_name="Checkpoint Z", organization_id=uuid.uuid4(), ), ) @@ -41,6 +42,7 @@ type="run_scheduled_checkpoint.received", datasource_names_to_asset_names={"Data Source 1": {"Data Asset A", "Data Asset B"}}, checkpoint_id=UUID("5f3814d6-a2e2-40f9-ba75-87ddf485c3a8"), + checkpoint_name="Checkpoint Z", schedule_id=UUID("5f3814d6-a2e2-40f9-ba75-87ddf485c3a8"), organization_id=uuid.uuid4(), ), @@ -51,6 +53,7 @@ type="run_window_checkpoint.received", datasource_names_to_asset_names={"Data Source 1": {"Data Asset A", "Data Asset B"}}, checkpoint_id=UUID("5f3814d6-a2e2-40f9-ba75-87ddf485c3a8"), + checkpoint_name="Checkpoint Z", organization_id=uuid.uuid4(), ), ) @@ -82,10 +85,8 @@ def test_run_checkpoint_action_with_and_without_splitter_options_returns_action_ context=mock_context, base_url="", organization_id=uuid.uuid4(), auth_key="" ) id = "096ce840-7aa8-45d1-9e64-2833948f4ae8" - checkpoint = mock_context.run_checkpoint.return_value - checkpoint_id_str = "5f3814d6-a2e2-40f9-ba75-87ddf485c3a8" - checkpoint.ge_cloud_id = checkpoint_id_str - checkpoint.run_results = { + checkpoint = mock_context.checkpoints.get.return_value + checkpoint.run.return_value.run_results = { "GXCloudIdentifier::validation_result::78ebf58e-bdb5-4d79-88d5-79bae19bf7d0": { "actions_results": { "store_validation_result": {"id": "78ebf58e-bdb5-4d79-88d5-79bae19bf7d0"} @@ -95,9 +96,7 @@ def test_run_checkpoint_action_with_and_without_splitter_options_returns_action_ event.splitter_options = splitter_options action_result = action.run(event=event, id=id) - mock_context.run_checkpoint.assert_called_with( - ge_cloud_id=UUID(checkpoint_id_str), batch_request=batch_request - ) + checkpoint.run.assert_called_with(batch_parameters=splitter_options) assert action_result.type == event.type assert action_result.id == id assert action_result.created_resources == [ @@ -123,7 +122,7 @@ def test_run_checkpoint_action_raises_on_test_connection_failure( event, ): mock_datasource = mocker.Mock(spec=Datasource) - mock_context.get_datasource.return_value = mock_datasource + mock_context.data_sources.get.return_value = mock_datasource mock_datasource.test_connection.side_effect = TestConnectionError() action = action_class( From 1eb0946ab37dff230df9a40d6864ae1c77a7d75a Mon Sep 17 00:00:00 2001 From: Josh Stauffer <66793731+joshua-stauffer@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:39:03 +0200 Subject: [PATCH 16/29] register all checkpoint events as v1, remove outdated todos --- great_expectations_cloud/agent/actions/run_checkpoint.py | 3 --- .../agent/actions/run_scheduled_checkpoint.py | 5 +---- .../agent/actions/run_window_checkpoint.py | 5 +---- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_checkpoint.py b/great_expectations_cloud/agent/actions/run_checkpoint.py index b4546289..af4c9ad8 100644 --- a/great_expectations_cloud/agent/actions/run_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_checkpoint.py @@ -21,9 +21,6 @@ class RunCheckpointAction(AgentAction[RunCheckpointEvent]): - # TODO: New actions need to be created that are compatible with GX v1 and registered for v1. - # This action is registered for v0, see register_event_action() - @override def run(self, event: RunCheckpointEvent, id: str) -> ActionResult: return run_checkpoint(self._context, event, id) diff --git a/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py b/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py index 343923af..bb27282f 100644 --- a/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py @@ -14,12 +14,9 @@ class RunScheduledCheckpointAction(AgentAction[RunScheduledCheckpointEvent]): - # TODO: New actions need to be created that are compatible with GX v1 and registered for v1. - # This action is registered for v0, see register_event_action() - @override def run(self, event: RunScheduledCheckpointEvent, id: str) -> ActionResult: return run_checkpoint(self._context, event, id) -register_event_action("0", RunScheduledCheckpointEvent, RunScheduledCheckpointAction) +register_event_action("1", RunScheduledCheckpointEvent, RunScheduledCheckpointAction) diff --git a/great_expectations_cloud/agent/actions/run_window_checkpoint.py b/great_expectations_cloud/agent/actions/run_window_checkpoint.py index 3636b965..38e84b60 100644 --- a/great_expectations_cloud/agent/actions/run_window_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_window_checkpoint.py @@ -14,9 +14,6 @@ class RunWindowCheckpointAction(AgentAction[RunWindowCheckpointEvent]): - # TODO: New actions need to be created that are compatible with GX v1 and registered for v1. - # This action is registered for v0, see register_event_action() - @override def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: # TODO: https://greatexpectations.atlassian.net/browse/ZELDA-922 @@ -24,4 +21,4 @@ def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: return run_checkpoint(self._context, event, id) -register_event_action("0", RunWindowCheckpointEvent, RunWindowCheckpointAction) +register_event_action("1", RunWindowCheckpointEvent, RunWindowCheckpointAction) From e377381a317d7fb917b9b4e4246450290864146c Mon Sep 17 00:00:00 2001 From: Josh Stauffer <66793731+joshua-stauffer@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:52:33 +0200 Subject: [PATCH 17/29] update create scheduled event payload --- great_expectations_cloud/agent/agent.py | 2 +- tests/agent/test_agent.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/great_expectations_cloud/agent/agent.py b/great_expectations_cloud/agent/agent.py index 02a05780..c251764f 100644 --- a/great_expectations_cloud/agent/agent.py +++ b/great_expectations_cloud/agent/agent.py @@ -455,8 +455,8 @@ def _create_scheduled_job_and_set_started( event_context: event with related properties and actions. """ data = { + **event_context.event.dict(), "correlation_id": event_context.correlation_id, - "event": event_context.event.dict(), } LOGGER.info( "Creating scheduled job and setting started", diff --git a/tests/agent/test_agent.py b/tests/agent/test_agent.py index 870977d6..1e2daf59 100644 --- a/tests/agent/test_agent.py +++ b/tests/agent/test_agent.py @@ -374,8 +374,8 @@ def test_gx_agent_sends_request_to_create_scheduled_job( ) payload = Payload( data={ + **event.dict(), "correlation_id": correlation_id, - "event": event.dict(), } ) data = payload.json() From a1624b5c6607495c0b13969f961c38642cf83ed9 Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 12:22:40 -0400 Subject: [PATCH 18/29] rename action, and fix url --- .../agent/actions/run_scheduled_checkpoint.py | 4 ++-- .../agent/actions/run_window_checkpoint.py | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py b/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py index 57c7b546..bb27282f 100644 --- a/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py @@ -6,7 +6,7 @@ ActionResult, AgentAction, ) -from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint_v0 +from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint from great_expectations_cloud.agent.event_handler import register_event_action from great_expectations_cloud.agent.models import ( RunScheduledCheckpointEvent, @@ -16,7 +16,7 @@ class RunScheduledCheckpointAction(AgentAction[RunScheduledCheckpointEvent]): @override def run(self, event: RunScheduledCheckpointEvent, id: str) -> ActionResult: - return run_checkpoint_v0(self._context, event, id) + return run_checkpoint(self._context, event, id) register_event_action("1", RunScheduledCheckpointEvent, RunScheduledCheckpointAction) diff --git a/great_expectations_cloud/agent/actions/run_window_checkpoint.py b/great_expectations_cloud/agent/actions/run_window_checkpoint.py index 24d09702..f2532d3a 100644 --- a/great_expectations_cloud/agent/actions/run_window_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_window_checkpoint.py @@ -8,7 +8,7 @@ ActionResult, AgentAction, ) -from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint_v0 +from great_expectations_cloud.agent.actions.run_checkpoint import run_checkpoint from great_expectations_cloud.agent.event_handler import register_event_action from great_expectations_cloud.agent.models import ( RunWindowCheckpointEvent, @@ -19,8 +19,7 @@ class RunWindowCheckpointAction(AgentAction[RunWindowCheckpointEvent]): @override def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: with create_session(access_token=self._auth_key) as session: - expectation_parameters_for_checkpoint_url = f"{self._base_url}/api/v1/organizations/" - f"{self._organization_id}/checkpoints/{event.checkpoint_id}/expectation-parameters" + expectation_parameters_for_checkpoint_url = f"{self._base_url}/api/v1/organizations/{self._organization_id}/checkpoints/{event.checkpoint_id}/expectation-parameters" response = session.get(url=expectation_parameters_for_checkpoint_url) if not response.ok: @@ -39,7 +38,7 @@ def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: ) from e # Note: In v0 expectation_parameters are called evaluation_parameters. - return run_checkpoint_v0( + return run_checkpoint( self._context, event, id, evaluation_parameters=expectation_parameters ) From 71f566dc16fb86f63fe3222247a3ba526baa5e48 Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 12:26:28 -0400 Subject: [PATCH 19/29] add unit test --- .../actions/test_run_window_checkpoint.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 tests/agent/actions/test_run_window_checkpoint.py diff --git a/tests/agent/actions/test_run_window_checkpoint.py b/tests/agent/actions/test_run_window_checkpoint.py new file mode 100644 index 00000000..8a762adc --- /dev/null +++ b/tests/agent/actions/test_run_window_checkpoint.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +import uuid +from typing import TYPE_CHECKING, Any, Literal +from unittest.mock import ANY +from uuid import UUID + +import pytest +import responses + +from great_expectations_cloud.agent.actions import RunWindowCheckpointAction +from great_expectations_cloud.agent.config import GxAgentEnvVars +from great_expectations_cloud.agent.models import ( + RunWindowCheckpointEvent, +) + +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + +@pytest.fixture +def org_id(): + return "81f4e105-e37d-4168-85a0-2526943f9956" + + +@pytest.fixture +def token(): + return "MTg0NDkyYmYtNTBiOS00ZDc1LTk3MmMtYjQ0M2NhZDA2NjJk" + + +@pytest.fixture +def set_required_env_vars(monkeypatch, org_id, token) -> None: + env_vars = { + "GX_CLOUD_BASE_URL": "https://test-base-url", + "GX_CLOUD_ORGANIZATION_ID": org_id, + "GX_CLOUD_ACCESS_TOKEN": token, + } + for key, val in env_vars.items(): + monkeypatch.setenv(name=key, value=val) + + +def build_get_draft_config_payload( + config: dict[str, Any], id: UUID +) -> dict[Literal["data"], dict[str, str | UUID | dict[str, Any]]]: + return { + "data": { + "type": "draft_config", + "id": str(id), + "config": config, + } + } + + +@responses.activate +def test_run_window_checkpoint( + mock_context, mocker: MockerFixture, set_required_env_vars: None, org_id +): + config_id = UUID("df02b47c-e1b8-48a8-9aaa-b6ed9c49ffa5") + org_id = UUID("81f4e105-e37d-4168-85a0-2526943f9956") + env_vars = GxAgentEnvVars() + action = RunWindowCheckpointAction( + context=mock_context, + base_url="https://test-base-url", + auth_key="", + organization_id=org_id, + ) + + job_id = UUID("87657a8e-f65e-4e64-b21f-e83a54738b75") + checkpoint_id = uuid.uuid4() + event = RunWindowCheckpointEvent( + datasource_names_to_asset_names={"Data Source 1": {"Data Asset A", "Data Asset B"}}, + config_id=config_id, + organization_id=env_vars.gx_cloud_organization_id, + checkpoint_id=checkpoint_id, + ) + expected_url: str = ( + f"{env_vars.gx_cloud_base_url}/api/v1/organizations/{env_vars.gx_cloud_organization_id}" + f"/checkpoints/{checkpoint_id}/expectation-parameters" + ) + # 'https://test-base-url/api/v1/organizations/81f4e105-e37d-4168-85a0-2526943f9956/checkpoints/120ba4c5-2004-4222-9d34-c59e6059a6f7/expectation-parameters' + expectation_parameters = {"param_name_min": 4.0, "param_name_max": 6.0} + responses.get( + url=expected_url, + json={"data": {"expectation_parameters": expectation_parameters}}, + ) + mock_run_checkpoint = mocker.patch( + "great_expectations_cloud.agent.actions.run_window_checkpoint.run_checkpoint", + ) + _ = action.run(event=event, id=str(job_id)) + + mock_run_checkpoint.assert_called_with( + ANY, event, ANY, evaluation_parameters=expectation_parameters + ) From 28e2d381e133e3f8bd58eab2aa6d594872dec2e4 Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 13:02:33 -0400 Subject: [PATCH 20/29] lint --- great_expectations_cloud/agent/actions/run_checkpoint.py | 4 ++-- tests/agent/actions/test_run_window_checkpoint.py | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_checkpoint.py b/great_expectations_cloud/agent/actions/run_checkpoint.py index 8effc467..9133d99e 100644 --- a/great_expectations_cloud/agent/actions/run_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_checkpoint.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from typing_extensions import override @@ -34,7 +34,7 @@ def run_checkpoint( context: CloudDataContext, event: RunCheckpointEvent | RunScheduledCheckpointEvent | RunWindowCheckpointEvent, id: str, - evaluation_parameters: dict | None = None, + evaluation_parameters: dict[str, Any] | None = None, ) -> ActionResult: """Note: the logic for this action is broken out into this function so that the same logic can be used for both RunCheckpointEvent and RunScheduledCheckpointEvent.""" diff --git a/tests/agent/actions/test_run_window_checkpoint.py b/tests/agent/actions/test_run_window_checkpoint.py index 8a762adc..95642ebc 100644 --- a/tests/agent/actions/test_run_window_checkpoint.py +++ b/tests/agent/actions/test_run_window_checkpoint.py @@ -55,7 +55,6 @@ def build_get_draft_config_payload( def test_run_window_checkpoint( mock_context, mocker: MockerFixture, set_required_env_vars: None, org_id ): - config_id = UUID("df02b47c-e1b8-48a8-9aaa-b6ed9c49ffa5") org_id = UUID("81f4e105-e37d-4168-85a0-2526943f9956") env_vars = GxAgentEnvVars() action = RunWindowCheckpointAction( @@ -69,8 +68,7 @@ def test_run_window_checkpoint( checkpoint_id = uuid.uuid4() event = RunWindowCheckpointEvent( datasource_names_to_asset_names={"Data Source 1": {"Data Asset A", "Data Asset B"}}, - config_id=config_id, - organization_id=env_vars.gx_cloud_organization_id, + organization_id=UUID(env_vars.gx_cloud_organization_id), checkpoint_id=checkpoint_id, ) expected_url: str = ( From 91f66eff78612e64032c49c6da3072c006e0a7ce Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 13:13:30 -0400 Subject: [PATCH 21/29] remove window from parametrization, needs diff test setup --- .../checkpoints/test_run_checkpoint_action.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py index 908becbc..2dfbe876 100644 --- a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py +++ b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py @@ -12,12 +12,10 @@ from great_expectations_cloud.agent.actions.run_scheduled_checkpoint import ( RunScheduledCheckpointAction, ) -from great_expectations_cloud.agent.actions.run_window_checkpoint import RunWindowCheckpointAction from great_expectations_cloud.agent.models import ( CreatedResource, RunCheckpointEvent, RunScheduledCheckpointEvent, - RunWindowCheckpointEvent, ) if TYPE_CHECKING: @@ -47,16 +45,6 @@ organization_id=uuid.uuid4(), ), ) -run_window_checkpoint_action_class_and_event = ( - RunWindowCheckpointAction, - RunWindowCheckpointEvent( - type="run_window_checkpoint.received", - datasource_names_to_asset_names={"Data Source 1": {"Data Asset A", "Data Asset B"}}, - checkpoint_id=UUID("5f3814d6-a2e2-40f9-ba75-87ddf485c3a8"), - checkpoint_name="Checkpoint Z", - organization_id=uuid.uuid4(), - ), -) @pytest.mark.parametrize( @@ -75,7 +63,6 @@ [ run_checkpoint_action_class_and_event, run_scheduled_checkpoint_action_class_and_event, - run_window_checkpoint_action_class_and_event, ], ) def test_run_checkpoint_action_with_and_without_splitter_options_returns_action_result( @@ -112,7 +99,6 @@ def test_run_checkpoint_action_with_and_without_splitter_options_returns_action_ [ run_checkpoint_action_class_and_event, run_scheduled_checkpoint_action_class_and_event, - run_window_checkpoint_action_class_and_event, ], ) def test_run_checkpoint_action_raises_on_test_connection_failure( From b4b73673bf7568cbb6426731a1f5acbb531d0bed Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 13:15:04 -0400 Subject: [PATCH 22/29] update sig --- great_expectations_cloud/agent/actions/run_checkpoint.py | 2 -- tests/agent/actions/checkpoints/test_run_checkpoint_action.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_checkpoint.py b/great_expectations_cloud/agent/actions/run_checkpoint.py index 9133d99e..1f89abaf 100644 --- a/great_expectations_cloud/agent/actions/run_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_checkpoint.py @@ -53,8 +53,6 @@ def run_checkpoint( ) in data_asset_names: # only test connection for assets that are validated in checkpoint asset = datasource.get_asset(data_asset_name) asset.test_connection() # raises `TestConnectionError` on failure - if evaluation_parameters is None: - evaluation_parameters = {} # run checkpoint checkpoint = context.checkpoints.get(name=event.checkpoint_name) diff --git a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py index 2dfbe876..beb8d868 100644 --- a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py +++ b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py @@ -83,7 +83,7 @@ def test_run_checkpoint_action_with_and_without_splitter_options_returns_action_ event.splitter_options = splitter_options action_result = action.run(event=event, id=id) - checkpoint.run.assert_called_with(batch_parameters=splitter_options) + checkpoint.run.assert_called_with(batch_parameters=splitter_options, evaluation_parameters=None) assert action_result.type == event.type assert action_result.id == id assert action_result.created_resources == [ From 9fb5d7da0a52c36448a809d38e966547bafd0f63 Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 14:08:45 -0400 Subject: [PATCH 23/29] fix kwarg --- great_expectations_cloud/agent/actions/run_checkpoint.py | 5 ++--- .../agent/actions/run_window_checkpoint.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/great_expectations_cloud/agent/actions/run_checkpoint.py b/great_expectations_cloud/agent/actions/run_checkpoint.py index 1f89abaf..0a2ff1fe 100644 --- a/great_expectations_cloud/agent/actions/run_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_checkpoint.py @@ -34,7 +34,7 @@ def run_checkpoint( context: CloudDataContext, event: RunCheckpointEvent | RunScheduledCheckpointEvent | RunWindowCheckpointEvent, id: str, - evaluation_parameters: dict[str, Any] | None = None, + expectation_parameters: dict[str, Any] | None = None, ) -> ActionResult: """Note: the logic for this action is broken out into this function so that the same logic can be used for both RunCheckpointEvent and RunScheduledCheckpointEvent.""" @@ -57,8 +57,7 @@ def run_checkpoint( # run checkpoint checkpoint = context.checkpoints.get(name=event.checkpoint_name) checkpoint_run_result = checkpoint.run( - batch_parameters=event.splitter_options, - evaluation_parameters=evaluation_parameters, + batch_parameters=event.splitter_options, expectation_parameters=expectation_parameters ) validation_results = checkpoint_run_result.run_results diff --git a/great_expectations_cloud/agent/actions/run_window_checkpoint.py b/great_expectations_cloud/agent/actions/run_window_checkpoint.py index f2532d3a..7b86a5bd 100644 --- a/great_expectations_cloud/agent/actions/run_window_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_window_checkpoint.py @@ -39,7 +39,7 @@ def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: # Note: In v0 expectation_parameters are called evaluation_parameters. return run_checkpoint( - self._context, event, id, evaluation_parameters=expectation_parameters + self._context, event, id, expectation_parameters=expectation_parameters ) From 1f110470936a00999828f500a616b034a15de186 Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 14:09:01 -0400 Subject: [PATCH 24/29] fix test kwarg --- tests/agent/actions/checkpoints/test_run_checkpoint_action.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py index beb8d868..35aa7117 100644 --- a/tests/agent/actions/checkpoints/test_run_checkpoint_action.py +++ b/tests/agent/actions/checkpoints/test_run_checkpoint_action.py @@ -83,7 +83,9 @@ def test_run_checkpoint_action_with_and_without_splitter_options_returns_action_ event.splitter_options = splitter_options action_result = action.run(event=event, id=id) - checkpoint.run.assert_called_with(batch_parameters=splitter_options, evaluation_parameters=None) + checkpoint.run.assert_called_with( + batch_parameters=splitter_options, expectation_parameters=None + ) assert action_result.type == event.type assert action_result.id == id assert action_result.created_resources == [ From 9ce4f2ac27e1e4568817d1f08b89d313b3b7fcba Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 14:14:22 -0400 Subject: [PATCH 25/29] fix unit assert --- tests/agent/actions/test_run_window_checkpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/agent/actions/test_run_window_checkpoint.py b/tests/agent/actions/test_run_window_checkpoint.py index 95642ebc..8fdbb9cc 100644 --- a/tests/agent/actions/test_run_window_checkpoint.py +++ b/tests/agent/actions/test_run_window_checkpoint.py @@ -87,5 +87,5 @@ def test_run_window_checkpoint( _ = action.run(event=event, id=str(job_id)) mock_run_checkpoint.assert_called_with( - ANY, event, ANY, evaluation_parameters=expectation_parameters + ANY, event, ANY, expectation_parameters=expectation_parameters ) From d7989f2db1e94820e9ca934984cae4d87736335a Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 14:17:41 -0400 Subject: [PATCH 26/29] rm note --- great_expectations_cloud/agent/actions/run_window_checkpoint.py | 1 - 1 file changed, 1 deletion(-) diff --git a/great_expectations_cloud/agent/actions/run_window_checkpoint.py b/great_expectations_cloud/agent/actions/run_window_checkpoint.py index 7b86a5bd..d12ec76f 100644 --- a/great_expectations_cloud/agent/actions/run_window_checkpoint.py +++ b/great_expectations_cloud/agent/actions/run_window_checkpoint.py @@ -37,7 +37,6 @@ def run(self, event: RunWindowCheckpointEvent, id: str) -> ActionResult: response=response, ) from e - # Note: In v0 expectation_parameters are called evaluation_parameters. return run_checkpoint( self._context, event, id, expectation_parameters=expectation_parameters ) From df42c28f9e7aba4042f1d580d37eb5177b4fe0c0 Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 16:46:17 -0400 Subject: [PATCH 27/29] api updates --- tests/integration/actions/conftest.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/integration/actions/conftest.py b/tests/integration/actions/conftest.py index 5ad4dfd5..549733a8 100644 --- a/tests/integration/actions/conftest.py +++ b/tests/integration/actions/conftest.py @@ -59,22 +59,24 @@ def datasource( get_missing_datasource_error_type: type[Exception], ) -> Iterator[PandasDatasource]: datasource_name = f"i{uuid.uuid4().hex}" - datasource = context.sources.add_pandas( + # TODO Bad config + context.data_sources.delete(name="david_datasource") + datasource = context.data_sources.add_pandas( name=datasource_name, ) assert datasource.name == datasource_name datasource_name = f"i{uuid.uuid4().hex}" datasource.name = datasource_name - datasource = context.sources.add_or_update_pandas( + datasource = context.data_sources.add_or_update_pandas( datasource=datasource, ) assert ( datasource.name == datasource_name ), "The datasource was not updated in the previous method call." yield datasource - context.delete_datasource(datasource_name=datasource_name) + context.data_sources.delete_pandas(name=datasource_name) with pytest.raises(get_missing_datasource_error_type): - context.get_datasource(datasource_name=datasource_name) + context.data_sources.get(name=datasource_name) @pytest.fixture(scope="module") @@ -99,9 +101,7 @@ def batch_request( pandas_test_df: pd.DataFrame, in_memory_batch_request_missing_dataframe_error_type: type[Exception], ): - with pytest.raises(in_memory_batch_request_missing_dataframe_error_type): - data_asset.build_batch_request() - return data_asset.build_batch_request(dataframe=pandas_test_df) + return data_asset.build_batch_request(options={"dataframe": pandas_test_df}) @pytest.fixture @@ -119,7 +119,7 @@ def expectation_suite( expectation_suite = gx.ExpectationSuite(name=expectation_suite_name) context.suites.add(expectation_suite) - expectation = gx.expectations.ExpectColumnValuesToNotBeNullExpectation( + expectation = gx.expectations.ExpectColumnValuesToBeNull( column="string", mostly=1, ) From 1a714f8bea2ef5b68c3c7a200a9c24262d910d6c Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 16:48:44 -0400 Subject: [PATCH 28/29] include WIP integration test --- .../actions/test_run_window_checkpoint.py | 108 +++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/tests/integration/actions/test_run_window_checkpoint.py b/tests/integration/actions/test_run_window_checkpoint.py index 2c1192bb..bdff29a3 100644 --- a/tests/integration/actions/test_run_window_checkpoint.py +++ b/tests/integration/actions/test_run_window_checkpoint.py @@ -1,6 +1,108 @@ -# this is currently a stub as we continue the work on Window Checkpoints from __future__ import annotations +import uuid +from typing import TYPE_CHECKING, Iterator -def test_running_window_checkpoint_action(): - pass +import pytest + +from great_expectations_cloud.agent.models import ( + RunCheckpointEvent, +) + +if TYPE_CHECKING: + from great_expectations.checkpoint import Checkpoint + from great_expectations.core import ExpectationSuite + from great_expectations.data_context import CloudDataContext + from great_expectations.datasource.fluent import BatchRequest + from great_expectations.datasource.fluent.pandas_datasource import DataFrameAsset + +from great_expectations.core.http import create_session + +from great_expectations_cloud.agent.actions.run_checkpoint import RunCheckpointAction + +pytestmark = pytest.mark.integration + + +@pytest.fixture(scope="module") +def checkpoint( + context: CloudDataContext, + data_asset: DataFrameAsset, + batch_request: BatchRequest, + expectation_suite: ExpectationSuite, + get_missing_checkpoint_error_type: type[Exception], +) -> Iterator[Checkpoint]: + yield context.checkpoints.all()[0] + # + # checkpoint_name = f"{data_asset.datasource.name} | {data_asset.name}" + # batch_definition = data_asset.add_batch_definition(name="my_batch_def") + # validation_definition = context.validation_definitions.add( + # ValidationDefinition(name=f"v{checkpoint_name}", suite=expectation_suite, data=batch_definition) + # ) + # validation_definition.save() + # for v in context.validation_definitions.all(): + # v.save() + # + # checkpoint = Checkpoint( + # name=checkpoint_name, + # validation_definitions=[validation_definition], + # result_format={"result_format": "COMPLETE"}, + # ) + # validation_definition.save() + # + # _ = context.checkpoints.add(checkpoint) + # checkpoint = context.checkpoints.get(name=checkpoint_name) + # assert ( + # len(checkpoint.validations) == 1 + # ), "Checkpoint was not updated in the previous method call." + # yield checkpoint + # PP-691: this is a bug + # you should only have to pass name + # context.checkpoints.delete( + # # name=checkpoint_name, + # id=checkpoint.ge_cloud_id, + # ) + # with pytest.raises(get_missing_checkpoint_error_type): + # context.checkpoints.get(name=checkpoint_name) + + +@pytest.fixture +def checkpoint_event(checkpoint, datasource_names_to_asset_names, org_id_env_var: str): + return RunCheckpointEvent( + type="run_checkpoint_request", + checkpoint_id=checkpoint.id, + datasource_names_to_asset_names=datasource_names_to_asset_names, + organization_id=uuid.UUID(org_id_env_var), + ) + + +def test_running_window_checkpoint_action( + context, checkpoint_event, cloud_base_url: str, org_id_env_var: str, token_env_var: str +): + action = RunCheckpointAction( + context=context, + base_url=cloud_base_url, + organization_id=uuid.UUID(org_id_env_var), + auth_key=token_env_var, + ) + event_id = "096ce840-7aa8-45d1-9e64-2833948f4ae8" + + # Act + action_result = action.run(event=checkpoint_event, id=event_id) + + # Assert + # Check that the action was successful, and we have received correct checkpoint event. + assert action_result.type == checkpoint_event.type + assert action_result.id == event_id + + # Check that the checkpoint was successful by querying the DB. + validation_result_id = action_result.created_resources[0].resource_id + resource_url = ( + f"{cloud_base_url}/organizations/" + f"{org_id_env_var}/validation-results/{validation_result_id}" + ) + with create_session(access_token=token_env_var) as session: + response = session.get(resource_url) + data = response.json() + + validation_result = data["data"]["attributes"]["validation_result"] + assert validation_result["success"] From c2e3f4525640be8f410c830fe4881e2225088d5b Mon Sep 17 00:00:00 2001 From: Robby Reinold Date: Mon, 7 Oct 2024 18:07:25 -0400 Subject: [PATCH 29/29] cleanup --- .../actions/test_run_window_checkpoint.py | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/tests/integration/actions/test_run_window_checkpoint.py b/tests/integration/actions/test_run_window_checkpoint.py index bdff29a3..f4eab313 100644 --- a/tests/integration/actions/test_run_window_checkpoint.py +++ b/tests/integration/actions/test_run_window_checkpoint.py @@ -4,18 +4,19 @@ from typing import TYPE_CHECKING, Iterator import pytest +from great_expectations import ValidationDefinition from great_expectations_cloud.agent.models import ( RunCheckpointEvent, ) if TYPE_CHECKING: - from great_expectations.checkpoint import Checkpoint from great_expectations.core import ExpectationSuite from great_expectations.data_context import CloudDataContext from great_expectations.datasource.fluent import BatchRequest from great_expectations.datasource.fluent.pandas_datasource import DataFrameAsset +from great_expectations.checkpoint import Checkpoint from great_expectations.core.http import create_session from great_expectations_cloud.agent.actions.run_checkpoint import RunCheckpointAction @@ -31,38 +32,38 @@ def checkpoint( expectation_suite: ExpectationSuite, get_missing_checkpoint_error_type: type[Exception], ) -> Iterator[Checkpoint]: - yield context.checkpoints.all()[0] - # - # checkpoint_name = f"{data_asset.datasource.name} | {data_asset.name}" - # batch_definition = data_asset.add_batch_definition(name="my_batch_def") - # validation_definition = context.validation_definitions.add( - # ValidationDefinition(name=f"v{checkpoint_name}", suite=expectation_suite, data=batch_definition) - # ) - # validation_definition.save() - # for v in context.validation_definitions.all(): - # v.save() - # - # checkpoint = Checkpoint( - # name=checkpoint_name, - # validation_definitions=[validation_definition], - # result_format={"result_format": "COMPLETE"}, - # ) - # validation_definition.save() - # - # _ = context.checkpoints.add(checkpoint) - # checkpoint = context.checkpoints.get(name=checkpoint_name) - # assert ( - # len(checkpoint.validations) == 1 - # ), "Checkpoint was not updated in the previous method call." - # yield checkpoint + checkpoint_name = f"{data_asset.datasource.name} | {data_asset.name}" + batch_definition = data_asset.add_batch_definition(name="my_batch_def") + validation_definition = context.validation_definitions.add( + ValidationDefinition( + name=f"v{checkpoint_name}", suite=expectation_suite, data=batch_definition + ) + ) + validation_definition.save() + for v in context.validation_definitions.all(): + v.save() + + checkpoint = Checkpoint( + name=checkpoint_name, + validation_definitions=[validation_definition], + result_format={"result_format": "COMPLETE"}, + ) + validation_definition.save() + + _ = context.checkpoints.add(checkpoint) + checkpoint = context.checkpoints.get(name=checkpoint_name) + assert ( + len(checkpoint.validations) == 1 + ), "Checkpoint was not updated in the previous method call." + yield checkpoint # PP-691: this is a bug # you should only have to pass name - # context.checkpoints.delete( - # # name=checkpoint_name, - # id=checkpoint.ge_cloud_id, - # ) - # with pytest.raises(get_missing_checkpoint_error_type): - # context.checkpoints.get(name=checkpoint_name) + context.checkpoints.delete( + # name=checkpoint_name, + id=checkpoint.ge_cloud_id, + ) + with pytest.raises(get_missing_checkpoint_error_type): + context.checkpoints.get(name=checkpoint_name) @pytest.fixture