From 89782d50e6b8a204d515049b8afaebc4da8cc859 Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Mon, 9 Mar 2026 13:35:47 +0000 Subject: [PATCH 01/20] creation daimanod_project --- comments.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 comments.txt diff --git a/comments.txt b/comments.txt new file mode 100644 index 0000000..e69de29 From 225d4aa2e3c9bb15c821bd71e4e397772c8eed6a Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Mon, 9 Mar 2026 14:08:17 +0000 Subject: [PATCH 02/20] add commment in comments.txt --- comments.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/comments.txt b/comments.txt index e69de29..9f3f2ab 100644 --- a/comments.txt +++ b/comments.txt @@ -0,0 +1 @@ +hello, this is yufo \ No newline at end of file From 4bf6e3277d5b81d660f2844cc3bfbcbed6fa8a1c Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Mon, 9 Mar 2026 14:12:08 +0000 Subject: [PATCH 03/20] comment --- comments.txt | 3 ++- src/diamonds/train.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/comments.txt b/comments.txt index 9f3f2ab..996c25b 100644 --- a/comments.txt +++ b/comments.txt @@ -1 +1,2 @@ -hello, this is yufo \ No newline at end of file +hello, this is yufo +great jcc \ No newline at end of file diff --git a/src/diamonds/train.py b/src/diamonds/train.py index 024d31a..df2c9af 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -15,7 +15,7 @@ def train( - train, evaluate, and save the trained model """ # 1) Data - + # 2) Model + preprocessing # 3) Evaluation From 34cc29a5912fc922af240b60932e68d065b3a192 Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Mon, 9 Mar 2026 15:28:12 +0000 Subject: [PATCH 04/20] definitions --- poetry.lock | 541 ++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 3 +- src/diamonds/data.py | 41 +++- 3 files changed, 573 insertions(+), 12 deletions(-) diff --git a/poetry.lock b/poetry.lock index c991753..f47064a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. [[package]] name = "anyio" @@ -466,6 +466,114 @@ files = [ [package.extras] test = ["pytest"] +[[package]] +name = "contourpy" +version = "1.3.3" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, + {file = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f"}, + {file = "contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff"}, + {file = "contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42"}, + {file = "contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411"}, + {file = "contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69"}, + {file = "contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b"}, + {file = "contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc"}, + {file = "contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5"}, + {file = "contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9"}, + {file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659"}, + {file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7"}, + {file = "contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d"}, + {file = "contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263"}, + {file = "contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9"}, + {file = "contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d"}, + {file = "contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b"}, + {file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a"}, + {file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e"}, + {file = "contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3"}, + {file = "contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8"}, + {file = "contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301"}, + {file = "contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a"}, + {file = "contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3"}, + {file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b"}, + {file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36"}, + {file = "contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d"}, + {file = "contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd"}, + {file = "contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339"}, + {file = "contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772"}, + {file = "contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0"}, + {file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4"}, + {file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f"}, + {file = "contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae"}, + {file = "contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc"}, + {file = "contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77"}, + {file = "contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880"}, +] + +[package.dependencies] +numpy = ">=1.25" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["bokeh", "contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.17.0)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] + +[[package]] +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + [[package]] name = "debugpy" version = "1.8.20" @@ -560,6 +668,79 @@ files = [ [package.extras] devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] +[[package]] +name = "fonttools" +version = "4.61.1" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c7db70d57e5e1089a274cbb2b1fd635c9a24de809a231b154965d415d6c6d24"}, + {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5fe9fd43882620017add5eabb781ebfbc6998ee49b35bd7f8f79af1f9f99a958"}, + {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8db08051fc9e7d8bc622f2112511b8107d8f27cd89e2f64ec45e9825e8288da"}, + {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a76d4cb80f41ba94a6691264be76435e5f72f2cb3cab0b092a6212855f71c2f6"}, + {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a13fc8aeb24bad755eea8f7f9d409438eb94e82cf86b08fe77a03fbc8f6a96b1"}, + {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b846a1fcf8beadeb9ea4f44ec5bdde393e2f1569e17d700bfc49cd69bde75881"}, + {file = "fonttools-4.61.1-cp310-cp310-win32.whl", hash = "sha256:78a7d3ab09dc47ac1a363a493e6112d8cabed7ba7caad5f54dbe2f08676d1b47"}, + {file = "fonttools-4.61.1-cp310-cp310-win_amd64.whl", hash = "sha256:eff1ac3cc66c2ac7cda1e64b4e2f3ffef474b7335f92fc3833fc632d595fcee6"}, + {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6604b735bb12fef8e0efd5578c9fb5d3d8532d5001ea13a19cddf295673ee09"}, + {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ce02f38a754f207f2f06557523cd39a06438ba3aafc0639c477ac409fc64e37"}, + {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77efb033d8d7ff233385f30c62c7c79271c8885d5c9657d967ede124671bbdfb"}, + {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:75c1a6dfac6abd407634420c93864a1e274ebc1c7531346d9254c0d8f6ca00f9"}, + {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0de30bfe7745c0d1ffa2b0b7048fb7123ad0d71107e10ee090fa0b16b9452e87"}, + {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58b0ee0ab5b1fc9921eccfe11d1435added19d6494dde14e323f25ad2bc30c56"}, + {file = "fonttools-4.61.1-cp311-cp311-win32.whl", hash = "sha256:f79b168428351d11e10c5aeb61a74e1851ec221081299f4cf56036a95431c43a"}, + {file = "fonttools-4.61.1-cp311-cp311-win_amd64.whl", hash = "sha256:fe2efccb324948a11dd09d22136fe2ac8a97d6c1347cf0b58a911dcd529f66b7"}, + {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e"}, + {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2"}, + {file = "fonttools-4.61.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10d88e55330e092940584774ee5e8a6971b01fc2f4d3466a1d6c158230880796"}, + {file = "fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d"}, + {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8"}, + {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0"}, + {file = "fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261"}, + {file = "fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9"}, + {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c"}, + {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e"}, + {file = "fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5"}, + {file = "fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd"}, + {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3"}, + {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d"}, + {file = "fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c"}, + {file = "fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b"}, + {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd"}, + {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e"}, + {file = "fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c"}, + {file = "fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75"}, + {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063"}, + {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2"}, + {file = "fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c"}, + {file = "fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c"}, + {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa"}, + {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91"}, + {file = "fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19"}, + {file = "fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba"}, + {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7"}, + {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118"}, + {file = "fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5"}, + {file = "fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b"}, + {file = "fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371"}, + {file = "fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69"}, +] + +[package.extras] +all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.45.0)", "unicodedata2 (>=17.0.0) ; python_version <= \"3.14\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] +lxml = ["lxml (>=4.0)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.45.0)"] +symfont = ["sympy"] +type1 = ["xattr ; sys_platform == \"darwin\""] +unicode = ["unicodedata2 (>=17.0.0) ; python_version <= \"3.14\""] +woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] + [[package]] name = "fqdn" version = "1.4.0" @@ -883,7 +1064,7 @@ fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} -jsonschema-specifications = ">=2023.03.6" +jsonschema-specifications = ">=2023.3.6" 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\""} @@ -1126,6 +1307,133 @@ docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pyd 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"] +[[package]] +name = "kiwisolver" +version = "1.5.0" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374"}, + {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd"}, + {file = "kiwisolver-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86e0287879f75621ae85197b0877ed2f8b7aa57b511c7331dce2eb6f4de7d476"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:62f59da443c4f4849f73a51a193b1d9d258dcad0c41bc4d1b8fb2bcc04bfeb22"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9190426b7aa26c5229501fa297b8d0653cfd3f5a36f7990c264e157cbf886b3b"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c8277104ded0a51e699c8c3aff63ce2c56d4ed5519a5f73e0fd7057f959a2b9e"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8f9baf6f0a6e7571c45c8863010b45e837c3ee1c2c77fcd6ef423be91b21fedb"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cff8e5383db4989311f99e814feeb90c4723eb4edca425b9d5d9c3fefcdd9537"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ebae99ed6764f2b5771c522477b311be313e8841d2e0376db2b10922daebbba4"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:d5cd5189fc2b6a538b75ae45433140c4823463918f7b1617c31e68b085c0022c"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f42c23db5d1521218a3276bb08666dcb662896a0be7347cba864eca45ff64ede"}, + {file = "kiwisolver-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:94eff26096eb5395136634622515b234ecb6c9979824c1f5004c6e3c3c85ccd2"}, + {file = "kiwisolver-1.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:dd952e03bfbb096cfe2dd35cd9e00f269969b67536cb4370994afc20ff2d0875"}, + {file = "kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c"}, + {file = "kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb"}, + {file = "kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4"}, + {file = "kiwisolver-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b"}, + {file = "kiwisolver-1.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac"}, + {file = "kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9"}, + {file = "kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588"}, + {file = "kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9"}, + {file = "kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384"}, + {file = "kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7"}, + {file = "kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09"}, + {file = "kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3"}, + {file = "kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0"}, + {file = "kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276"}, + {file = "kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53"}, + {file = "kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615"}, + {file = "kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02"}, + {file = "kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796"}, + {file = "kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e"}, + {file = "kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:295d9ffe712caa9f8a3081de8d32fc60191b4b51c76f02f951fd8407253528f4"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:51e8c4084897de9f05898c2c2a39af6318044ae969d46ff7a34ed3f96274adca"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b83af57bdddef03c01a9138034c6ff03181a3028d9a1003b301eb1a55e161a3f"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf4679a3d71012a7c2bf360e5cd878fbd5e4fcac0896b56393dec239d81529ed"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:41024ed50e44ab1a60d3fe0a9d15a4ccc9f5f2b1d814ff283c8d01134d5b81bc"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1"}, + {file = "kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a"}, +] + [[package]] name = "lark" version = "1.3.1" @@ -1243,6 +1551,85 @@ files = [ {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] +[[package]] +name = "matplotlib" +version = "3.10.8" +description = "Python plotting package" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "matplotlib-3.10.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:00270d217d6b20d14b584c521f810d60c5c78406dc289859776550df837dcda7"}, + {file = "matplotlib-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b3c1cc42aa184b3f738cfa18c1c1d72fd496d85467a6cf7b807936d39aa656"}, + {file = "matplotlib-3.10.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee40c27c795bda6a5292e9cff9890189d32f7e3a0bf04e0e3c9430c4a00c37df"}, + {file = "matplotlib-3.10.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a48f2b74020919552ea25d222d5cc6af9ca3f4eb43a93e14d068457f545c2a17"}, + {file = "matplotlib-3.10.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f254d118d14a7f99d616271d6c3c27922c092dac11112670b157798b89bf4933"}, + {file = "matplotlib-3.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:f9b587c9c7274c1613a30afabf65a272114cd6cdbe67b3406f818c79d7ab2e2a"}, + {file = "matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160"}, + {file = "matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78"}, + {file = "matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4"}, + {file = "matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2"}, + {file = "matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6"}, + {file = "matplotlib-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9"}, + {file = "matplotlib-3.10.8-cp311-cp311-win_arm64.whl", hash = "sha256:bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2"}, + {file = "matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a"}, + {file = "matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58"}, + {file = "matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04"}, + {file = "matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f"}, + {file = "matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466"}, + {file = "matplotlib-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf"}, + {file = "matplotlib-3.10.8-cp312-cp312-win_arm64.whl", hash = "sha256:3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b"}, + {file = "matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6"}, + {file = "matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1"}, + {file = "matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486"}, + {file = "matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce"}, + {file = "matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6"}, + {file = "matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149"}, + {file = "matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645"}, + {file = "matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077"}, + {file = "matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22"}, + {file = "matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39"}, + {file = "matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565"}, + {file = "matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a"}, + {file = "matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958"}, + {file = "matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5"}, + {file = "matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f"}, + {file = "matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b"}, + {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d"}, + {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008"}, + {file = "matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c"}, + {file = "matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11"}, + {file = "matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8"}, + {file = "matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50"}, + {file = "matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908"}, + {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a"}, + {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1"}, + {file = "matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c"}, + {file = "matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b"}, + {file = "matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f"}, + {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f97aeb209c3d2511443f8797e3e5a569aebb040d4f8bc79aa3ee78a8fb9e3dd8"}, + {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fb061f596dad3a0f52b60dc6a5dec4a0c300dec41e058a7efe09256188d170b7"}, + {file = "matplotlib-3.10.8-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12d90df9183093fcd479f4172ac26b322b1248b15729cb57f42f71f24c7e37a3"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2"}, + {file = "matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +kiwisolver = ">=1.3.1" +numpy = ">=1.23" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=3" +python-dateutil = ">=2.7" + +[package.extras] +dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7)"] + [[package]] name = "matplotlib-inline" version = "0.2.1" @@ -1510,7 +1897,7 @@ version = "26.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, @@ -1652,6 +2039,115 @@ files = [ [package.dependencies] ptyprocess = ">=0.5" +[[package]] +name = "pillow" +version = "12.1.1" +description = "Python Imaging Library (fork)" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "pillow-12.1.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f1625b72740fdda5d77b4def688eb8fd6490975d06b909fd19f13f391e077e0"}, + {file = "pillow-12.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:178aa072084bd88ec759052feca8e56cbb14a60b39322b99a049e58090479713"}, + {file = "pillow-12.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b66e95d05ba806247aaa1561f080abc7975daf715c30780ff92a20e4ec546e1b"}, + {file = "pillow-12.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:89c7e895002bbe49cdc5426150377cbbc04767d7547ed145473f496dfa40408b"}, + {file = "pillow-12.1.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a5cbdcddad0af3da87cb16b60d23648bc3b51967eb07223e9fed77a82b457c4"}, + {file = "pillow-12.1.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9f51079765661884a486727f0729d29054242f74b46186026582b4e4769918e4"}, + {file = "pillow-12.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:99c1506ea77c11531d75e3a412832a13a71c7ebc8192ab9e4b2e355555920e3e"}, + {file = "pillow-12.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36341d06738a9f66c8287cf8b876d24b18db9bd8740fa0672c74e259ad408cff"}, + {file = "pillow-12.1.1-cp310-cp310-win32.whl", hash = "sha256:6c52f062424c523d6c4db85518774cc3d50f5539dd6eed32b8f6229b26f24d40"}, + {file = "pillow-12.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6008de247150668a705a6338156efb92334113421ceecf7438a12c9a12dab23"}, + {file = "pillow-12.1.1-cp310-cp310-win_arm64.whl", hash = "sha256:1a9b0ee305220b392e1124a764ee4265bd063e54a751a6b62eff69992f457fa9"}, + {file = "pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e879bb6cd5c73848ef3b2b48b8af9ff08c5b71ecda8048b7dd22d8a33f60be32"}, + {file = "pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:365b10bb9417dd4498c0e3b128018c4a624dc11c7b97d8cc54effe3b096f4c38"}, + {file = "pillow-12.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4ce8e329c93845720cd2014659ca67eac35f6433fd3050393d85f3ecef0dad5"}, + {file = "pillow-12.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc354a04072b765eccf2204f588a7a532c9511e8b9c7f900e1b64e3e33487090"}, + {file = "pillow-12.1.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e7976bf1910a8116b523b9f9f58bf410f3e8aa330cd9a2bb2953f9266ab49af"}, + {file = "pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:597bd9c8419bc7c6af5604e55847789b69123bbe25d65cc6ad3012b4f3c98d8b"}, + {file = "pillow-12.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c1fc0f2ca5f96a3c8407e41cca26a16e46b21060fe6d5b099d2cb01412222f5"}, + {file = "pillow-12.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:578510d88c6229d735855e1f278aa305270438d36a05031dfaae5067cc8eb04d"}, + {file = "pillow-12.1.1-cp311-cp311-win32.whl", hash = "sha256:7311c0a0dcadb89b36b7025dfd8326ecfa36964e29913074d47382706e516a7c"}, + {file = "pillow-12.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:fbfa2a7c10cc2623f412753cddf391c7f971c52ca40a3f65dc5039b2939e8563"}, + {file = "pillow-12.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:b81b5e3511211631b3f672a595e3221252c90af017e399056d0faabb9538aa80"}, + {file = "pillow-12.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab323b787d6e18b3d91a72fc99b1a2c28651e4358749842b8f8dfacd28ef2052"}, + {file = "pillow-12.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:adebb5bee0f0af4909c30db0d890c773d1a92ffe83da908e2e9e720f8edf3984"}, + {file = "pillow-12.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb66b7cc26f50977108790e2456b7921e773f23db5630261102233eb355a3b79"}, + {file = "pillow-12.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee2810642b2898bb187ced9b349e95d2a7272930796e022efaf12e99dccd293"}, + {file = "pillow-12.1.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0b1cd6232e2b618adcc54d9882e4e662a089d5768cd188f7c245b4c8c44a397"}, + {file = "pillow-12.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7aac39bcf8d4770d089588a2e1dd111cbaa42df5a94be3114222057d68336bd0"}, + {file = "pillow-12.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ab174cd7d29a62dd139c44bf74b698039328f45cb03b4596c43473a46656b2f3"}, + {file = "pillow-12.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:339ffdcb7cbeaa08221cd401d517d4b1fe7a9ed5d400e4a8039719238620ca35"}, + {file = "pillow-12.1.1-cp312-cp312-win32.whl", hash = "sha256:5d1f9575a12bed9e9eedd9a4972834b08c97a352bd17955ccdebfeca5913fa0a"}, + {file = "pillow-12.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:21329ec8c96c6e979cd0dfd29406c40c1d52521a90544463057d2aaa937d66a6"}, + {file = "pillow-12.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:af9a332e572978f0218686636610555ae3defd1633597be015ed50289a03c523"}, + {file = "pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d242e8ac078781f1de88bf823d70c1a9b3c7950a44cdf4b7c012e22ccbcd8e4e"}, + {file = "pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:02f84dfad02693676692746df05b89cf25597560db2857363a208e393429f5e9"}, + {file = "pillow-12.1.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e65498daf4b583091ccbb2556c7000abf0f3349fcd57ef7adc9a84a394ed29f6"}, + {file = "pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c6db3b84c87d48d0088943bf33440e0c42370b99b1c2a7989216f7b42eede60"}, + {file = "pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b7e5304e34942bf62e15184219a7b5ad4ff7f3bb5cca4d984f37df1a0e1aee2"}, + {file = "pillow-12.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5bddd742a44b7e6b1e773ab5db102bd7a94c32555ba656e76d319d19c3850"}, + {file = "pillow-12.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc44ef1f3de4f45b50ccf9136999d71abb99dca7706bc75d222ed350b9fd2289"}, + {file = "pillow-12.1.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a8eb7ed8d4198bccbd07058416eeec51686b498e784eda166395a23eb99138e"}, + {file = "pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47b94983da0c642de92ced1702c5b6c292a84bd3a8e1d1702ff923f183594717"}, + {file = "pillow-12.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:518a48c2aab7ce596d3bf79d0e275661b846e86e4d0e7dec34712c30fe07f02a"}, + {file = "pillow-12.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a550ae29b95c6dc13cf69e2c9dc5747f814c54eeb2e32d683e5e93af56caa029"}, + {file = "pillow-12.1.1-cp313-cp313-win32.whl", hash = "sha256:a003d7422449f6d1e3a34e3dd4110c22148336918ddbfc6a32581cd54b2e0b2b"}, + {file = "pillow-12.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:344cf1e3dab3be4b1fa08e449323d98a2a3f819ad20f4b22e77a0ede31f0faa1"}, + {file = "pillow-12.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c0dd1636633e7e6a0afe7bf6a51a14992b7f8e60de5789018ebbdfae55b040a"}, + {file = "pillow-12.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0330d233c1a0ead844fc097a7d16c0abff4c12e856c0b325f231820fee1f39da"}, + {file = "pillow-12.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dae5f21afb91322f2ff791895ddd8889e5e947ff59f71b46041c8ce6db790bc"}, + {file = "pillow-12.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e0c664be47252947d870ac0d327fea7e63985a08794758aa8af5b6cb6ec0c9c"}, + {file = "pillow-12.1.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:691ab2ac363b8217f7d31b3497108fb1f50faab2f75dfb03284ec2f217e87bf8"}, + {file = "pillow-12.1.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9e8064fb1cc019296958595f6db671fba95209e3ceb0c4734c9baf97de04b20"}, + {file = "pillow-12.1.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:472a8d7ded663e6162dafdf20015c486a7009483ca671cece7a9279b512fcb13"}, + {file = "pillow-12.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:89b54027a766529136a06cfebeecb3a04900397a3590fd252160b888479517bf"}, + {file = "pillow-12.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:86172b0831b82ce4f7877f280055892b31179e1576aa00d0df3bb1bbf8c3e524"}, + {file = "pillow-12.1.1-cp313-cp313t-win32.whl", hash = "sha256:44ce27545b6efcf0fdbdceb31c9a5bdea9333e664cda58a7e674bb74608b3986"}, + {file = "pillow-12.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a285e3eb7a5a45a2ff504e31f4a8d1b12ef62e84e5411c6804a42197c1cf586c"}, + {file = "pillow-12.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cc7d296b5ea4d29e6570dabeaed58d31c3fea35a633a69679fb03d7664f43fb3"}, + {file = "pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:417423db963cb4be8bac3fc1204fe61610f6abeed1580a7a2cbb2fbda20f12af"}, + {file = "pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:b957b71c6b2387610f556a7eb0828afbe40b4a98036fc0d2acfa5a44a0c2036f"}, + {file = "pillow-12.1.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:097690ba1f2efdeb165a20469d59d8bb03c55fb6621eb2041a060ae8ea3e9642"}, + {file = "pillow-12.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2815a87ab27848db0321fb78c7f0b2c8649dee134b7f2b80c6a45c6831d75ccd"}, + {file = "pillow-12.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7ed2c6543bad5a7d5530eb9e78c53132f93dfa44a28492db88b41cdab885202"}, + {file = "pillow-12.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:652a2c9ccfb556235b2b501a3a7cf3742148cd22e04b5625c5fe057ea3e3191f"}, + {file = "pillow-12.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6e4571eedf43af33d0fc233a382a76e849badbccdf1ac438841308652a08e1f"}, + {file = "pillow-12.1.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b574c51cf7d5d62e9be37ba446224b59a2da26dc4c1bb2ecbe936a4fb1a7cb7f"}, + {file = "pillow-12.1.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a37691702ed687799de29a518d63d4682d9016932db66d4e90c345831b02fb4e"}, + {file = "pillow-12.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f95c00d5d6700b2b890479664a06e754974848afaae5e21beb4d83c106923fd0"}, + {file = "pillow-12.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:559b38da23606e68681337ad74622c4dbba02254fc9cb4488a305dd5975c7eeb"}, + {file = "pillow-12.1.1-cp314-cp314-win32.whl", hash = "sha256:03edcc34d688572014ff223c125a3f77fb08091e4607e7745002fc214070b35f"}, + {file = "pillow-12.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:50480dcd74fa63b8e78235957d302d98d98d82ccbfac4c7e12108ba9ecbdba15"}, + {file = "pillow-12.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:5cb1785d97b0c3d1d1a16bc1d710c4a0049daefc4935f3a8f31f827f4d3d2e7f"}, + {file = "pillow-12.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1f90cff8aa76835cba5769f0b3121a22bd4eb9e6884cfe338216e557a9a548b8"}, + {file = "pillow-12.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f1be78ce9466a7ee64bfda57bdba0f7cc499d9794d518b854816c41bf0aa4e9"}, + {file = "pillow-12.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:42fc1f4677106188ad9a55562bbade416f8b55456f522430fadab3cef7cd4e60"}, + {file = "pillow-12.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98edb152429ab62a1818039744d8fbb3ccab98a7c29fc3d5fcef158f3f1f68b7"}, + {file = "pillow-12.1.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d470ab1178551dd17fdba0fef463359c41aaa613cdcd7ff8373f54be629f9f8f"}, + {file = "pillow-12.1.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6408a7b064595afcab0a49393a413732a35788f2a5092fdc6266952ed67de586"}, + {file = "pillow-12.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5d8c41325b382c07799a3682c1c258469ea2ff97103c53717b7893862d0c98ce"}, + {file = "pillow-12.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7697918b5be27424e9ce568193efd13d925c4481dd364e43f5dff72d33e10f8"}, + {file = "pillow-12.1.1-cp314-cp314t-win32.whl", hash = "sha256:d2912fd8114fc5545aa3a4b5576512f64c55a03f3ebcca4c10194d593d43ea36"}, + {file = "pillow-12.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4ceb838d4bd9dab43e06c363cab2eebf63846d6a4aeaea283bbdfd8f1a8ed58b"}, + {file = "pillow-12.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7b03048319bfc6170e93bd60728a1af51d3dd7704935feb228c4d4faab35d334"}, + {file = "pillow-12.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:600fd103672b925fe62ed08e0d874ea34d692474df6f4bf7ebe148b30f89f39f"}, + {file = "pillow-12.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:665e1b916b043cef294bc54d47bf02d87e13f769bc4bc5fa225a24b3a6c5aca9"}, + {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:495c302af3aad1ca67420ddd5c7bd480c8867ad173528767d906428057a11f0e"}, + {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fd420ef0c52c88b5a035a0886f367748c72147b2b8f384c9d12656678dfdfa9"}, + {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f975aa7ef9684ce7e2c18a3aa8f8e2106ce1e46b94ab713d156b2898811651d3"}, + {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8089c852a56c2966cf18835db62d9b34fef7ba74c726ad943928d494fa7f4735"}, + {file = "pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e"}, + {file = "pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"] +tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma (>=5)", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] +xmp = ["defusedxml"] + [[package]] name = "platformdirs" version = "4.9.4" @@ -1787,6 +2283,21 @@ files = [ [package.extras] windows-terminal = ["colorama (>=0.4.6)"] +[[package]] +name = "pyparsing" +version = "3.3.2" +description = "pyparsing - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"}, + {file = "pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -2382,6 +2893,28 @@ dev = ["click (<8.3.0)", "cython-lint (>=0.12.2)", "mypy (==1.10.0)", "pycodesty doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)", "tabulate"] test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "seaborn" +version = "0.13.2" +description = "Statistical data visualization" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987"}, + {file = "seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7"}, +] + +[package.dependencies] +matplotlib = ">=3.4,<3.6.1 || >3.6.1" +numpy = ">=1.20,<1.24.0 || >1.24.0" +pandas = ">=1.2" + +[package.extras] +dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] +docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx (<6.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] +stats = ["scipy (>=1.7)", "statsmodels (>=0.12)"] + [[package]] name = "send2trash" version = "2.1.0" @@ -2668,4 +3201,4 @@ test = ["pytest", "websockets"] [metadata] lock-version = "2.1" python-versions = ">=3.11" -content-hash = "89febdab18f2cc18794068b6fc2adfe59389ca912e976b3f8f6cffc2463ad7da" +content-hash = "dfb5e761522323802ddc653bb61de697436ad55d50ade1c3b86e9ef318ca35f2" diff --git a/pyproject.toml b/pyproject.toml index 38a3f2f..006462e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,8 @@ readme = "README.md" requires-python = ">=3.11" dependencies = [ "scikit-learn (>=1.8.0,<2.0.0)", - "pandas (>=3.0.1,<4.0.0)" + "pandas (>=3.0.1,<4.0.0)", + "seaborn (>=0.13.2,<0.14.0)" ] [tool.poetry] diff --git a/src/diamonds/data.py b/src/diamonds/data.py index 7bc5d2e..8f11c85 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -1,8 +1,17 @@ -import pandas as pd # Import other necessary libraries here +import pandas as pd +import seaborn as sns +from sklearn.pipeline import Pipeline +from sklearn.compose import ColumnTransformer , make_column_selector +from sklearn.compose import ColumnTransformer +from sklearn.impute import SimpleImputer +from sklearn.preprocessing import OneHotEncoder +from src.diamonds.model import create_preproc +df_diamonds = sns.load_dataset("diamonds") def load_data(cache = True) -> pd.DataFrame: + df_diamonds = sns.load_dataset("diamonds") """ Load the diamonds dataset. @@ -16,9 +25,16 @@ def load_data(cache = True) -> pd.DataFrame: pd.DataFrame The diamonds dataset """ - pass + + return df_diamonds def clean_data(df: pd.DataFrame) -> pd.DataFrame: + + def keep_not_allow(row): + if 0 in row: return False + return True + df_diamonds = df[df.apply(keep_not_allow, axis=1)] + df_diamonds[df_diamonds["x"] == 0] """ Clean the diamonds dataset. @@ -32,9 +48,11 @@ def clean_data(df: pd.DataFrame) -> pd.DataFrame: pd.DataFrame The cleaned diamonds dataset """ - pass + + return df def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: + df_diamonds = df.select_dtypes(include=["category"]) """ Preprocess the diamonds dataset. @@ -48,9 +66,17 @@ def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: pd.DataFrame The preprocessed diamonds dataset """ - pass + + return df def create_X_y(df: pd.DataFrame) ->tuple[pd.DataFrame, pd.Series]: + # cat_pipe = Pipeline( + # [("cat_imp",SimpleImputer(strategy="most_frequent")), + # ("onehot", OneHotEncoder(dropt="first"), sparsde_output=True)] + # ) + num_cols = df.select_dtypes(include="number").columns.tolist() + cat_cols = df.select_dtypes(include="category").columns.tolist() + preprocessor = create_preproc() """ Create the feature matrix X and target vector y from the diamonds dataset. @@ -64,12 +90,13 @@ def create_X_y(df: pd.DataFrame) ->tuple[pd.DataFrame, pd.Series]: (pd.DataFrame, pd.Series) The feature matrix X and target vector y """ - pass + return preprocessor + if __name__ == "__main__": df = load_data() - # df_clean = clean_data(df) - # df_preprocessed = preprocess_data(df_clean) + df_clean = clean_data(df) + df_preprocessed = preprocess_data(df_clean) # X, y = create_X_y(df_preprocessed) \ No newline at end of file From 22b26a59c2c75c05c146c2dbdb255c5b4916dfad Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Mon, 9 Mar 2026 15:37:33 +0000 Subject: [PATCH 05/20] modifications --- .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 259 bytes src/diamonds/__pycache__/model.cpython-311.pyc | Bin 0 -> 1660 bytes src/diamonds/data.py | 7 +------ src/diamonds/model.py | 3 ++- 4 files changed, 3 insertions(+), 7 deletions(-) create mode 100644 src/diamonds/__pycache__/__init__.cpython-311.pyc create mode 100644 src/diamonds/__pycache__/model.cpython-311.pyc diff --git a/src/diamonds/__pycache__/__init__.cpython-311.pyc b/src/diamonds/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d7ffdbe39d9b3be549b82c7bac955f3cdcd59bf GIT binary patch literal 259 zcmZ3^%ge<81h)>Y%k%@%k3k$5V1zP0gOp5XNMVR#NMQ_S&}1rg2MV}kCg$enr4%dp z`Y046CTAz6rz$*Zn4(aWnwFScl3%1ynO|C@ke6SQnv|cPt&p6blB$rISCX$#l95`R zs*szXQks)mtmmi6c#AzgJ|#anK7J*`XONY@?DRA8b5r%Rl9MwMi<0sU^+B5TQy>AmS6t{Di%XeD|AwGqyRv=Q*M67%bP}ry{(xHlkBKPcTjwW}J?W0Pk4E-Nq zWP>iK;xFmIP~FN>5JRMHop|=$rA>Ww(|#DRY?VzZ-1Ch=XbgsN)in|B z7=h5WWi*$78KLoQlrN1|Pho>xO|tRNtnDou`?8dgf#3rXx?D<~gh5&njl>C21YHTK zXifvhbEz@uOHl*iRhTk0r)bO(`hly9CL6QnpcXp7YeswBiu1;|xUktV6%-eS2_v-% zNNs{$F^6d!uE5DHn6dz5gpTdvX!TOCVjdo(z+wUT*a285hS&jASf@ef_&et73!f*gl0l`eK;!FJrH5&9b4iTxrqt2N zQdvl!h?^i>f+_XKWn_LPi);02T$MXLPDRkzf^V15r4TPH2Dq4*uoeeqkBiw|6_FbX!<{P=5Xm_ zYm8v|^wuo1gxGMSI7YC{k}B4+32`i3`m%AjbQm2je_wezMzEhH<#`Oc{w5}Be*k9) Bky`)& literal 0 HcmV?d00001 diff --git a/src/diamonds/data.py b/src/diamonds/data.py index 8f11c85..b800de1 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -1,12 +1,7 @@ # Import other necessary libraries here import pandas as pd import seaborn as sns -from sklearn.pipeline import Pipeline -from sklearn.compose import ColumnTransformer , make_column_selector -from sklearn.compose import ColumnTransformer -from sklearn.impute import SimpleImputer -from sklearn.preprocessing import OneHotEncoder -from src.diamonds.model import create_preproc +from diamonds.model import create_preproc df_diamonds = sns.load_dataset("diamonds") diff --git a/src/diamonds/model.py b/src/diamonds/model.py index cd3ebcc..0c2a73b 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -1,4 +1,5 @@ -from sklearn.base import BaseEstimator, Pipeline +from sklearn.base import BaseEstimator +from sklearn.pipeline import Pipeline def create_model(model_name: str) -> BaseEstimator: From 5162b4e7025dc33661a1c62442237f06b69d3d62 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Mon, 9 Mar 2026 16:13:09 +0000 Subject: [PATCH 06/20] add model functions --- src/diamonds/model.py | 75 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/src/diamonds/model.py b/src/diamonds/model.py index cd3ebcc..095dddf 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -1,4 +1,14 @@ from sklearn.base import BaseEstimator, Pipeline +from sklearn.compose import ColumnTransformer +from sklearn.preprocessing import OneHotEncoder, StandardScaler +from sklearn.impute import SimpleImputer +from sklearn.impute import KNNImputer +from sklearn.linear_model import Ridge +from sklearn.ensemble import RandomForestRegressor +from sklearn.neighbors import KNeighborsRegressor +from sklearn.linear_model import LinearRegression +from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, mean_absolute_percentage_error +import pandas as pd def create_model(model_name: str) -> BaseEstimator: @@ -15,23 +25,73 @@ def create_model(model_name: str) -> BaseEstimator: BaseEstimator The model ready to be fitted """ - pass -def create_preproc() -> Pipeline: + models = { + "ridge": Ridge(alpha=1.0), + "random_forest": RandomForestRegressor( + n_estimators=200, + max_depth=10, + random_state=42 + ), + "knn": KNeighborsRegressor(n_neighbors=5), + "linear": LinearRegression(fit_intercept=True), + } + + if model_name not in models: + raise ValueError(f"Unknown model: {model_name}") + + return models[model_name] + +def create_preproc(num_cols: list[str], cat_cols: list[str]) -> Pipeline: """ Create a preprocessing pipeline. """ - pass + + # pipeline numérique + num_pipeline = Pipeline([ + ("imputer", KNNImputer(n_neighbors=5)), + ("scaler", StandardScaler()) + ]) + + # pipeline catégorique + cat_pipeline = Pipeline([ + ("imputer", SimpleImputer(strategy="most_frequent")), + ("encoder", OneHotEncoder(handle_unknown="ignore")) + ]) + + # combiner les deux + preprocessing = ColumnTransformer([ + ("num", num_pipeline, num_cols), + ("cat", cat_pipeline, cat_cols) + ]) + + return preprocessing def train_model(model, X_train, y_train): - pass + model.fit(X_train, y_train) + return model def evaluate_model(model, X_test, y_test) -> dict[str, float]: # NB : mae, mse, r2_score, mape # Only print the metrics for now - pass + y_pred = model.predict(X_test) + + mae = mean_absolute_error(y_test, y_pred) + mse = mean_squared_error(y_test, y_pred) + r2 = r2_score(y_test, y_pred) + mape = mean_absolute_percentage_error(y_test, y_pred) + + metrics = { + "mae": mae, + "mse": mse, + "r2": r2, + "mape": mape + } -def predict(model, X): + for name, value in metrics.items(): + print(f"{name}: {value:.4f}") + +def predict(model, X: pd.DataFrame) -> pd.Series: """ Make predictions using the trained model. @@ -47,4 +107,7 @@ def predict(model, X): pd.Series The predicted values """ + y_pred = model.predict(X) + + return pd.Series(y_pred, index=X.index, name="prediction") From 3dd7b00eed36d2ecf954dd4e8f771f7b65f36961 Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Mon, 9 Mar 2026 16:54:45 +0000 Subject: [PATCH 07/20] traitements --- .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 248 bytes .../__pycache__/model.cpython-311.pyc | Bin 1660 -> 4513 bytes .../__pycache__/model.cpython-313.pyc | Bin 0 -> 3771 bytes src/diamonds/data.py | 30 +++++++++++------- src/diamonds/model.py | 3 +- 5 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 src/diamonds/__pycache__/__init__.cpython-313.pyc create mode 100644 src/diamonds/__pycache__/model.cpython-313.pyc diff --git a/src/diamonds/__pycache__/__init__.cpython-313.pyc b/src/diamonds/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9340a8b26275285870dee0d373f1f38473ec141 GIT binary patch literal 248 zcmYL^K@I^i7=>E|k+{RZwb9titRyzrI6zZvnPTRbwzIHv2o7Q65RTC$7m&;av_ZVh z`@hBiUS8er_efN@-^?QVGr>>vd(_={T*#7GvY~@UHH|niqQFu)n9txKer$Guw`FX@pAyUQJ4AAamP_@CLEvNZX<3QL&c#<lOi`76~lC38076QDC9aL;ip~_VEbtfmlF5fuaxY69YRakf+WrKg5&N zv|TLcW@l$-zkV~b{4x>=A}GuM`b)kRLg??T(JsCg^XjO8&{L!#P0*1cqy>TT9^GSz zX_51yE*ajmm-CYDGyG}4A*W^D_UZv6m=1E@2Ye_U;=ErE8i|=Viv6%B|3D6zZdOt+zH(>M#K8%%|XLnT2qa{IORO`co_s81CKy&c^c)JBN z_Jht*ExdqIhh8#qN}!R8s)esucHU6!0s(>iPQHlsyorI2Un=M&!@NyY)5;Zyfl10k zBfl{5&kFVxGh5Iwq0t3fH8quJ3t3eM1u(ggH;OvGW)w>{7X+`*&+oRpxANK&v)*?L z1{RE~1%fU67G8pn#h1`~eIDnRmKO`e>K6ChfK{oaCCV4fltgtRVHSZm2-awcPCVJiBDdq@$JEH-U*sWp0@1`XJlo-tJeQy;;0iI`cyRi`kt ziST>%4UnhE?&{NoEzfgkzv#$prr9c*s7ac4%l8~)FFJDD+wMn5^KZ#}#{0W^16x6N zuNL}DS{2HuEW9g_gdOP84VTd~^!c9Ed?1uTdlxr=goru-iw!DJE)lHSSW!)-WZFc9 z)7BJz7RsZ%y{y>FSXqRtQkGZX(26R71A+^-lw6@?YKm4Od2>mzOD24#g52Ue9VOnJ z>=fSIJ!fS`v24PHY$3N{CU*QvA;)KJF5(29TAEVE2!qeqDPTB!G5}0i)L5!H<1Kz) zR`+zAcfs5>QPVhVU0YG?0_;%9VaM50-;noT*8;+fya@-Hg+TymFW(@I zxVA^d2c}7V%r8~)IQA>^fmwKDHg9J}NqGrd5P`UeNSKib5E{Ir>Lq-I`9#V?5=`Xd zyR|G2G!*6g+0)Af1E0R1%`U5Cu`qp_`SfWmuNnnYYk#fN7Rl~5xP__W3JqsDUNT%j zj)TP*{H)&ssi5x^lsL4$;KWC(@zGj*bZ2m?J~&kGAE*x=Y51kX!EX_e*Nl7@L_Oo1 z51rU_H8x#~P46Vewv$fcY&CJVmN?sp2co_P0#do!=tpv5z2EVVK;4NBID>C)&H#a0 zjh?GT&pGnBzlGv!Cu^Z$M;d+wD?wB?OGYMJ&@C!wRhx5Jw*7Wt4#wU2H86YK+2y{T zEz#|M5O$?*_k9i)UbO9^oM&l|`>lH1!NTr#ZWb6^p#!Y@T`nze1@>y}n?bZ02wFu8 zmOW*Z6SYuTEDJetpSDz%AOwUTpX6X~`@d2oxJU|Fh{w#Mi>-t(#g(WZqB{%hWC&&< z!$7Fd;<2AbjDlrnas)ptK}ZE~%iz_3{iPM^$E|$f%P*PWvCtV^1_#!0rql#872%?& z2zQk75sBGm;f$~&A~GW^?h@uj0QVH*ng4KSZlVEOQ69{j>Gv3Fi%k#ZNPVbfjr=O4sP(G z;|c=k0vLpOxEc|H5=1sHcWvswo8jqz`d6Ba#U|*SV~BUQ!oVE#ybV9=2#^Y@OM%~A z`{3G>rL{*@X{08NIMPTx)Kj^!f8p$+`ND_53w~(fZXZ|`yL}Y!F1ok1>hjP7`n}y= zctF3e+XoNm_m`!zx9ltXH35>bT$VQ&&h`~|Y`Bc>9sUg*{c2z}XtQA5D&@d4c(9g( zn)pomd{49y&__o!c16-WqzTbbF%Sz=4>?06LoMRRo*Ct_IQ64k%1`}(YAv6&Nfay- z7MMv7BXJLR4sT4nt}M*#QH=vFj@t;Z7eXivQ-*$8-JkUM}>-fl$Ez{u0pKdt`p{ZHO+Ai+Dq$?ro?q$hYs zj;tk}=uxQaea$b>s(h>_A9HwZi0u&^xm398N+RsaIe0Z-{txhay1{$DI2LIHoI(i6I)7&2W|FPbG_mI_ZJyF##D2K8)sL^9%C*` zyyq@x6}73$s;ypS4?&kYQ6DK9^!)IX42CaYlE=-*T6?P2R^aK`1Qj<-gS$I~zaZYc zsp0nsgHcK%m*GP_MUDEJ=EyIZT;!-G^T3m9KwL44kKrW4x>(c)C@O6zPFEwtwa73) zF%$RVPg^g zmND0)@%D($1GMY0*jZo8wGRv&z9RdtXOUaXoCwLCKl`Yp=YePWld$+tB?d<7&FKZz zCd}b!paT@Lz|`2CeTDcb@-Xqe{1)Vzl8)yH^B~9o$oex-a63V$qY1}d>*$!{u5~o& zxN99AmS6t{Di%XeD|AwGqyRv=Q*M67%bP}ry{(xHlkBKPcTjwW}J?W0Pk4E-Nq zWP>iK;xFmIP~FN>5JRMHop|=$rA>Ww(|#DRY?VzZ-1Ch=XbgsN)in|B z7=h5WWi*$78KLoQlrN1|Pho>xO|tRNtnDou`?8dgf#3rXx?D<~gh5&njl>C21YHTK zXifvhbEz@uOHl*iRhTk0r)bO(`hly9CL6QnpcXp7YeswBiu1;|xUktV6%-eS2_v-% zNNs{$F^6d!uE5DHn6dz5gpTdvX!TOCVjdo(z+wUT*a285hS&jASf@ef_&et73!f*gl0l`eK;!FJrH5&9b4iTxrqt2N zQdvl!h?^i>f+_XKWn_LPi);02T$MXLPDRkzf^V15r4TPH2Dq4*uoeeqkBiw|6_FbX!<{P=5Xm_ zYm8v|^wuo1gxGMSI7YC{k}B4+32`i3`m%AjbQm2je_wezMzEhH<#`Oc{w5}Be*k9) Bky`)& diff --git a/src/diamonds/__pycache__/model.cpython-313.pyc b/src/diamonds/__pycache__/model.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..25862907106a1b597dec3b51556e805dc4933758 GIT binary patch literal 3771 zcma(UOKcm*b(XtaE|(vX6eUZF6t87lHUpc2967e+RBHW8Oj>HnH4O!lL9ECT#hBcs zXP31lAP9SE(n}N|PSl>9OQT#0_1aU9JyK9m5K|cm&|Z9_V;8;l&2ULkPFr*!zIpTJ z&D%HcH%~7@Ar-+`|JNT%-v$u+J6m*y>>@AD2?#w#I?{zSN(n^J816}XQX&yKE~cfF zmv}iYrR9{5_)-c{_}ZKHr&OYHTn0Qq0vz|HgQ*Y+aa>7k z(Q8(@Rx$4o!?f2dQo$tQp`o9f z_+87nVdkv@CN!)&hFLI3LC+gyU;vSNsZuTDTa{|f;RH3kxOlkoW=e%3lRl7vgI49H zMX>E;a1kb(tI(fb#HHf;szvNxa^yB>We}HCvdn};`zzQmbH=I-iaI!l39$%`aiaa8 zW)NI(X$rZJv-9vN`ufo$RZQ~Obc~{VdXcIXxL7%78Wl`sf}I*M^AKO%;R8&B--}HE zkI`~>PZxC0jIhl1_|QdN(!IJoBQ7)7wP`+G0Ujo!z4q(sjGzaSk|`_+S3s5#MrhgJ z-4A9_7`^Ga=zawYOA#jQ6iS3PTk17}4F_w6sntw}7+|1+#?{vzmYj9XS;yKcSXW!$ zfO}RA0(SzR*xH&^GYeXwMoMN;b803`NmYHX%b=d`jvjMpvzqNdrogxZl9`1xYmI-U z{n4{HSxjoaQ4&as^y<)@jhy#&*DD&zKRv z5oo~7nVn#}!-5ySlq;EFq&ysg2=nsG(9n^qQ1QNLQkkWRK{orc=6%z8Xtpgst0laI zDMX-LArfRD1c0h{jdBg&U?H0DkQgJ${HC_;frX~gE0gP11y6pE&#xO~)tZ`QDK=Rs z85PScbY^?fCi%k!myoP(&|sd&LXH#28IafqKl^L5108{dn)^*rhi%k`VBL8Qd?ea8>NL)-H^vpeS+!?73%)G*ft}bcQq8?b9nihLFq^tzV z72F)}CYM$vxJs-%)F+lMRkuJURqBIE$BG;o1&L$~0F`ZC2WhBc*-mba;0HA*FA!M@ zqz(jLafAA>TRY`a(S+21&G0&8N*U*B?MR{`n3RfO&4f%OCYu!m!m0*g)+FrZBP@g= z))EY7!4IJij_9Zd0RhhFu0lsHVY9O=k2NyEPKMp!ahb?vASU5we*^%+Cy3&sO@Hk3 z)Xvmi{Cq=6HvQ4h=l1(gHk4B>uQ(>ZKw{iizujeA*qPspUuh_Bvr`MZLwoVrhH~W< z)`5wpKfD!eC}%n|Fq~ns27L8}mWqPI4QYs+1s(F;stOBc5gt%%=P}BnOt%ID!5vGn zi*68VzyU557QxUW2iY=NsPlvE`BQ=Zw4au+do#5xr?j$Js|&0&8*NV?WTB`4NE6G%9}m;&_neeMt%=fK8*by zsxK>Ly;(Wy(*<~Dl&q5J<^U+>j!v%iqjv`ps)6aMzguQ?i;t{73=LIQ)x|#arr6O~ zLkmL)1(1e{C?PFEwG=A`24G|AAs47rF{*geGplWi$?3I(kNP0K3Z=Y5;Eh9s)h7~R zAPRtbOAfBs)LVr|$w>sr6-Jc7Lr~7C3=VQDy><4D**Wp~Gzu6aSh9k{L{JG!TC)eL;h0)OQ zFF*Y3!!JJiB=E6xpoF&KTk_WG_Q1Bi9cYA4{Z%>rgNTOC@Cc&9(vjlHGMxv}Dj@$y z5P6o}s7ENn^5m5Vk0}v!cgb1$~yS)p+4!-Ncb5y#gJbxy2#^Pdr5FA=3IHvYP zV-OsH(5ExMnc2Gg^`);a?T+pR<{Hu*_hsTV4chn1&?A`1Rp_$`b0m#)NS)fuD?IJ% zkn>ihY5_AV(R83gg^L}&LGAj_>I)5b7~H3bKM(A+pz+R5yG?N;opmOMDqz#bl~w55 zS(eaf=R~(9>Sv)qDF304-4vgr{iYDLVZWo&OHaKSgIb z4wMT|(G>iBhbsH1@;B7qlE;MCxAhi+>B+s9Y--IN6Nb0%JURK>_ge_i-BY{v9}^t? zv+|Nrez@QfqAevROzhm*J-J)kePi$ZPhKKex6a0d`K{G2%b%57u%3THzTWt1 pd.DataFrame: pd.DataFrame The diamonds dataset """ - + print(df_diamonds.head()) return df_diamonds def clean_data(df: pd.DataFrame) -> pd.DataFrame: @@ -44,7 +44,7 @@ def keep_not_allow(row): The cleaned diamonds dataset """ - return df + return df_diamonds def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: df_diamonds = df.select_dtypes(include=["category"]) @@ -64,14 +64,14 @@ def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: return df -def create_X_y(df: pd.DataFrame) ->tuple[pd.DataFrame, pd.Series]: - # cat_pipe = Pipeline( - # [("cat_imp",SimpleImputer(strategy="most_frequent")), - # ("onehot", OneHotEncoder(dropt="first"), sparsde_output=True)] - # ) - num_cols = df.select_dtypes(include="number").columns.tolist() - cat_cols = df.select_dtypes(include="category").columns.tolist() - preprocessor = create_preproc() +def create_X_y(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series]: + # Split target first so preprocessing columns only reference feature columns. + X = df.drop(columns="price") + y = df["price"] + + num_cols = X.select_dtypes(include="number").columns.tolist() + cat_cols = X.select_dtypes(include=["category", "object"]).columns.tolist() + preprocessor = create_preproc(num_cols, cat_cols) """ Create the feature matrix X and target vector y from the diamonds dataset. @@ -85,7 +85,13 @@ def create_X_y(df: pd.DataFrame) ->tuple[pd.DataFrame, pd.Series]: (pd.DataFrame, pd.Series) The feature matrix X and target vector y """ - return preprocessor + X_transform = preprocessor.fit_transform(X) + X_transform = pd.DataFrame( + X_transform, + columns=preprocessor.get_feature_names_out(), + index=X.index, + ) + return X_transform, y @@ -94,4 +100,4 @@ def create_X_y(df: pd.DataFrame) ->tuple[pd.DataFrame, pd.Series]: df = load_data() df_clean = clean_data(df) df_preprocessed = preprocess_data(df_clean) - # X, y = create_X_y(df_preprocessed) \ No newline at end of file + X, y = create_X_y(df_preprocessed) \ No newline at end of file diff --git a/src/diamonds/model.py b/src/diamonds/model.py index 095dddf..83e9446 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -1,4 +1,5 @@ -from sklearn.base import BaseEstimator, Pipeline +from sklearn.base import BaseEstimator +from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder, StandardScaler from sklearn.impute import SimpleImputer From 08106daa8e3e05c54940e586e3ee2d1f6343affa Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Tue, 10 Mar 2026 08:54:01 +0000 Subject: [PATCH 08/20] saves --- src/diamonds/__pycache__/data.cpython-313.pyc | Bin 0 -> 2645 bytes .../__pycache__/params.cpython-313.pyc | Bin 0 -> 348 bytes .../__pycache__/registry.cpython-313.pyc | Bin 0 -> 1456 bytes .../__pycache__/train.cpython-313.pyc | Bin 0 -> 1974 bytes src/diamonds/registry.py | 35 +++++++++++++----- src/diamonds/train.py | 30 +++++++++++++++ 6 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 src/diamonds/__pycache__/data.cpython-313.pyc create mode 100644 src/diamonds/__pycache__/params.cpython-313.pyc create mode 100644 src/diamonds/__pycache__/registry.cpython-313.pyc create mode 100644 src/diamonds/__pycache__/train.cpython-313.pyc diff --git a/src/diamonds/__pycache__/data.cpython-313.pyc b/src/diamonds/__pycache__/data.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..330dcc0cc077e15d81786bc8cd4486f4f7b6eef0 GIT binary patch literal 2645 zcmbVNO-vg{6rNqL|BctIF;N^s9f$llK{$z^1xiUtQba>SR5q3@fwWre1x)Q-ch*)Q ziki(0lmnzv6z5cWDjeG6*q(ao-Ht2SnWj>toN{vtJ@wKzYm9*=Ipj(E=FQH$dGo&a zGg~b!E(Fy1@6V}KCql32q(QbFVQZN|=pho3$c!V*m?MiVFtX#^RV%iJ(6nXJ(@<-U zVI*4mK$jA>i*AvdW+r|0`Ci`3iq;@n;1(F{6m4(c^G;n(v{PN|`T$Lbsp)=?rswUq zfxp4M9@OPt)(S!|Cpyh@z0IU5-7#;*^>r+`J+uBP_8d+{ zyo_hG^U;KsRH8e(8lxW7aiTe)R(i5a#JOt|d*L((eEKzz^S+0F0W5p-(}Q!NeRp zXNhnVm~I)pxrrbrELgjxQ|lqz0-SiiR+OxyYB@-fACSG~vvUoCe_`ioG=$A`^vh3@|jeV+cUEOb|x`ifK;6 zOPdU_r_@9`pH#rL7F|gziJX+oEoBuw!q#0hy{o5Z9cX^13Kd;9(Z$EW{CW8Fd`OJ)haVKcv zqriwwn^}OQfNbcZQ)^01DvJ>p;gVR(;t<_uF4%HfI;H0@4G3wOP35EntoG?qo0k@IhYPy-Rb;;Ar zJ`EFhylF2R&uSL_A*vc2dC86#DPYx$EE zw=wdP_pRPtxx2o&e7DG-tML6LzQ4j>Eb$l1{D?7DtuJr5o{kkyeMa{TSNPEqKU(3h zm-y>t{)RF3!hdZ2blKl$T&ovw5cxl<2;C*2d*iFJ5H-eM2yKtLzw53#{8e8^#do3P zyHNJ^R=xb{+{)Y=JLk7S!MLF8mxqhoVY6I_Ly|IbN|mGtb2AbkwydlsWgVXdZ-`x2 z-al{;0F1$GK_~|fi_hAcVIOO!!WOq|4$V7 z3q@XfTPxnqXWq`j?Xvfb;eNyUm_r5p{hh~m{y`wtx&q9hwF{4i9t_nGi0hYry!OMj zZ7SA!e2llie(!ngslit7hVZ0gvtyfzwXP#fu%QLw`WGAFC*7Ofzp%eKe{~kmjFh@A zZ6jEyea;}xvwXX3IsDuy+&^Mmdd?p%gztZAj6H8Zu|8jJj~X|gy8~-l*?scf6=USy MH#H~Xf~K4Q0TA;YK>z>% literal 0 HcmV?d00001 diff --git a/src/diamonds/__pycache__/params.cpython-313.pyc b/src/diamonds/__pycache__/params.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..071b873ff3bc4a8f59335229154484ac94f7e4cd GIT binary patch literal 348 zcmey&%ge<81h)>Y%gh7Pk3k$5V1Y6|`v4hJ8G;#t8NC^b7=oFK7=xLMm|_@$*kDQ# zbPy+k4Pynf1hbklL3l;1>5Q6eFF_o?TP!JwC5gA#a`RJCbBb^A`TD!K`osshx_btP z1V!Fr&B;$r%+X}K#gt!si_^t1#4$d=F~s8*7epPH&7PW9mRXdacZ)eawWNp@XzEIa z&mhBZ+308F=cejsB`0Sj7A55y>L&wj(ND=t%+1eBfzieK#YM>oPC;T(Vs5csLFFwD z8=#{~b5iY!_<@Eo0&%fAkodsN$jEq`f%5^kU<2n3UeN}w2ZF-Wr6x*EmzyYeLBU{y O`ei|@M!q6mpjrS716Jq& literal 0 HcmV?d00001 diff --git a/src/diamonds/__pycache__/registry.cpython-313.pyc b/src/diamonds/__pycache__/registry.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dce3b704d9b2cdc292ccd2284f62801d52301b6a GIT binary patch literal 1456 zcmb`H&1)M+6u@U!qt#k#$<2p1C6((*FeM5^BE*Koln_d66Df96tp#muFl+7FUVA^p zn^ju-lw%J)xRgLnCC3Izo1_1L{sC)TP*~hk9ZGKkwU?gyX0@{0oO;Lz=Dm5dGxI)v zPyIq6PjLL${mJ<{L&$GpF&s*&^j%b*5`!30ozx_dn9$|AT+2YFMu8^lOg&puKuL63 z&(%~=QO~X_hO#=cD&5EtV&qn(X~j@4lWhw5|JapjYK$ayZ8Kli{t!=>rIzI$ zQ>){(W9kN`h1SAHCb#E!=y+xr02+#mAK#yQxYn3kcwj6yK8v$nVA*a=+ju%wzz#d$ zw`6f=IA5kHKU8t>=%TX=LuO6`^hlmv;88uCC^9$yDhDVdy>(VhE`v0 z%8g;_hTA9`BmY{Ys*%ATy(2TSq78RHm1j~<8EMK>q@3NmX_${~X0i}W$G0t(M90E_ zSq|S}rf;!9h|CE&6ERoftQ)jU_wQ2E=bd&tfbjGf*qaUyVRx1-V`6h{6Kp@^v1)&b z=Cxp_tN@mZ#21!=@PXHMZ4dWtYYrd)5IKpJ!5Pf*j^zMQw3RcUq5u(Ntc50Q+Toh; zgo_i5vG{IvEAZ^V_m8rQoTz{ zhqUy3`Q`mcXm^gO`qlU^wDd~TBdYiDM$$?PEOa8m6G8NU!0D}^LQYYUno>g~`;9S^ zuCJxiDk6@j_!ya{^ah5f@SI_Y;LyEm53ykooHp2xouI?rT_(~vBxnNyFJY(xqxcjQ zaN5%sMenc;$F-Rsglr?|_|_~-v4D5PhXV`}Vt9OR9zR7`=Ea8tOhj9h<%9;ffI1gM zGX@t?#Cg%hX(cbCK~$43N4U qeXmDQe1GfZ#TT=QdNB2;u=Mm1X=2}aHvP@#J%Z}<#lM6|-uVZ8cTRBt literal 0 HcmV?d00001 diff --git a/src/diamonds/__pycache__/train.cpython-313.pyc b/src/diamonds/__pycache__/train.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc16216a1e4c59b065e13119fbf8accbaed42d17 GIT binary patch literal 1974 zcmZXU&2Jk;6u@V_AGX)uaXy+9+HD1CT+*1T3ACXUfl{?NNmH?1uq2rs?g0U+go*@G%Bja94)jleBjS?CAj~Kgh!3IOT&2Bn;LWVpIWSIU-h1=*&6}Cu zoBdQuM$kU{fEus>KIfcrR#Yl$CzDMjF)6Aml8NpO5!B5iHoUH8mE~oEoMqtoK?^f_EXbpbTy~OR)^I1YF?Gq z#B5AWPM{58gTuqCBWh~CjF1sSXm$8Fn(L>hp!LLhqL6t^^#VtPtA<~LG3#T)c68tJ zeBEo-ZNDH8xmvdjM>h@M02y0`Z|P-ylf>(;VFu<*6I)H}RxQtCh5}ELeb0t#T6L1P zZW;9!{W8!K!8%NVW##3Sg^Nr2)i%piB@DtBP6jc5(qy4$>LIKBZ7r6u2{m!KC;#OTotb3WW-05AacJpSi8I?7FFxrB zS|LKBO#@qw?~$1GfelsS-rS1LY`AN6du=PbOkr1OY*X>wdF4tWg()|fB88y_5rzi? zVPFGciVdbDVEUY3dfzw+9T6KhO&ep10}-1T_FWjlX*zw7Tg1FUV&)B<9Vf|vbg*s9 zBwU$rnj zJ(3={um}Nwj6F&rKos1FHv@&G&d1f6ol}L>PM#%8&Nw40uZNvpALDu@{n`Y<2kYUxoNb MmwG%BCRir_0a(2d5C8xG literal 0 HcmV?d00001 diff --git a/src/diamonds/registry.py b/src/diamonds/registry.py index e631010..a3f407a 100644 --- a/src/diamonds/registry.py +++ b/src/diamonds/registry.py @@ -1,13 +1,30 @@ +from pathlib import Path + +from joblib import dump, load from sklearn.base import BaseEstimator -from diamonds.params import MODEL_REGISTRY -def save_model(model, path): - """Save the model to the specified path.""" - # Implement the logic to save the model (e.g., using pickle, joblib, etc.) - pass +from diamonds.params import MODEL_REGISTRY + + +def save_model(model: BaseEstimator, path: str | Path) -> Path: + """Save a trained model to disk and return its path.""" + if MODEL_REGISTRY != "local": + raise NotImplementedError(f"Unsupported model registry: {MODEL_REGISTRY}") + + target_path = Path(path) + target_path.parent.mkdir(parents=True, exist_ok=True) + dump(model, target_path) + return target_path + + +def load_model(path: str | Path) -> BaseEstimator: + """Load a previously saved model from disk.""" + if MODEL_REGISTRY != "local": + raise NotImplementedError(f"Unsupported model registry: {MODEL_REGISTRY}") + + target_path = Path(path) + if not target_path.exists(): + raise FileNotFoundError(f"Model file not found: {target_path}") -def load_model(path) -> BaseEstimator: - """Load the model from the specified path.""" - # Implement the logic to load the model (e.g., using pickle, joblib, etc.) - pass \ No newline at end of file + return load(target_path) \ No newline at end of file diff --git a/src/diamonds/train.py b/src/diamonds/train.py index df2c9af..7591095 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -1,5 +1,15 @@ +from pathlib import Path + +from sklearn.model_selection import train_test_split + +from diamonds.data import clean_data, create_X_y, load_data, preprocess_data +from diamonds.model import create_model, evaluate_model, train_model +from diamonds.params import MODEL_PATH +from diamonds.registry import save_model + + def train( model_name: str = "baseline", test_size: float = 0.2, @@ -15,12 +25,32 @@ def train( - train, evaluate, and save the trained model """ # 1) Data + df = load_data() + df_clean = clean_data(df) + df_preprocessed = preprocess_data(df_clean) + X, y = create_X_y(df_preprocessed) + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + test_size=test_size, + random_state=random_state, + ) # 2) Model + preprocessing + resolved_model_name = "linear" if model_name == "baseline" else model_name + model = create_model(resolved_model_name) + trained_model = train_model(model, X_train, y_train) # 3) Evaluation + evaluate_model(trained_model, X_test, y_test) # 4) Persistence + model_dir = Path(MODEL_PATH) + model_dir.mkdir(parents=True, exist_ok=True) + model_path = model_dir / f"{resolved_model_name}.joblib" + saved_path = save_model(trained_model, model_path) + print(f"Model saved to: {saved_path}") if __name__ == "__main__": From 72c12771e8c47f267d4fafe0fe73d4542dcba431 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Tue, 10 Mar 2026 09:00:16 +0000 Subject: [PATCH 09/20] change onehotencoder param from ignore to drop=first, sparce_outout=false --- src/diamonds/model.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/diamonds/model.py b/src/diamonds/model.py index 83e9446..7511601 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -50,14 +50,14 @@ def create_preproc(num_cols: list[str], cat_cols: list[str]) -> Pipeline: # pipeline numérique num_pipeline = Pipeline([ - ("imputer", KNNImputer(n_neighbors=5)), + ("num_imp", KNNImputer(n_neighbors=5)), ("scaler", StandardScaler()) ]) # pipeline catégorique cat_pipeline = Pipeline([ - ("imputer", SimpleImputer(strategy="most_frequent")), - ("encoder", OneHotEncoder(handle_unknown="ignore")) + ("cat_imp", SimpleImputer(strategy="most_frequent")), + ("ohe", OneHotEncoder(drop="first",sparse_output=False)) ]) # combiner les deux From df4b5d01ca283d9eb9012b9e20f8d84ac5561b37 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Tue, 10 Mar 2026 10:04:11 +0000 Subject: [PATCH 10/20] correct some functions according to correction --- .gitignore | 1 + poetry.lock | 83 ++++++++++++++---- pyproject.toml | 6 +- .../__pycache__/__init__.cpython-311.pyc | Bin 259 -> 260 bytes src/diamonds/__pycache__/data.cpython-311.pyc | Bin 0 -> 3696 bytes .../__pycache__/model.cpython-311.pyc | Bin 4513 -> 4528 bytes .../__pycache__/params.cpython-311.pyc | Bin 0 -> 360 bytes .../__pycache__/registry.cpython-311.pyc | Bin 0 -> 1669 bytes src/diamonds/data.py | 21 ++++- src/diamonds/model.py | 38 +++++++- src/diamonds/registry.py | 34 +++---- src/diamonds/train.py | 46 +++++----- 12 files changed, 160 insertions(+), 69 deletions(-) create mode 100644 src/diamonds/__pycache__/data.cpython-311.pyc create mode 100644 src/diamonds/__pycache__/params.cpython-311.pyc create mode 100644 src/diamonds/__pycache__/registry.cpython-311.pyc diff --git a/.gitignore b/.gitignore index 4869ac4..545c2b6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .venv/ .python-version .ipynb_checkpoints/ +/__pycache__/ # Data data/ diff --git a/poetry.lock b/poetry.lock index f47064a..e765327 100644 --- a/poetry.lock +++ b/poetry.lock @@ -444,7 +444,7 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] +groups = ["main", "dev"] markers = "sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, @@ -741,19 +741,6 @@ type1 = ["xattr ; sys_platform == \"darwin\""] unicode = ["unicodedata2 (>=17.0.0) ; python_version <= \"3.14\""] woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] -[[package]] -name = "fqdn" -version = "1.4.0" -description = "Validate fully-qualified domain names compliant to RFC 1035 and the preferred form in RFC 3686 s. 2." -optional = false -python-versions = "*" -groups = ["dev"] -markers = "python_version >= \"3.14\"" -files = [ - {file = "fqdn-1.4.0-py3-none-any.whl", hash = "sha256:e935616ae81c9c60a22267593fe8e6af68cecc68549cc71bb9bfbcbbcb383386"}, - {file = "fqdn-1.4.0.tar.gz", hash = "sha256:30e8f2e685ce87cdace4712fd97c5d09f5e6fa519bbb66e8f188f6a7cb3a5c4e"}, -] - [[package]] name = "fqdn" version = "1.5.1" @@ -761,7 +748,6 @@ description = "Validates fully-qualified domain names against RFC 1123, so that optional = false python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" groups = ["dev"] -markers = "python_version < \"3.14\"" files = [ {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, @@ -1452,6 +1438,25 @@ interegular = ["interegular (>=0.3.1,<0.4.0)"] nearley = ["js2py"] regex = ["regex"] +[[package]] +name = "loguru" +version = "0.7.3" +description = "Python logging made (stupidly) simple" +optional = false +python-versions = "<4.0,>=3.5" +groups = ["main"] +files = [ + {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, + {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==0.910) ; python_version < \"3.6\"", "mypy (==0.971) ; python_version == \"3.6\"", "mypy (==1.13.0) ; python_version >= \"3.8\"", "mypy (==1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] + [[package]] name = "markupsafe" version = "3.0.3" @@ -2752,6 +2757,34 @@ files = [ {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, ] +[[package]] +name = "ruff" +version = "0.15.5" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "ruff-0.15.5-py3-none-linux_armv6l.whl", hash = "sha256:4ae44c42281f42e3b06b988e442d344a5b9b72450ff3c892e30d11b29a96a57c"}, + {file = "ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6edd3792d408ebcf61adabc01822da687579a1a023f297618ac27a5b51ef0080"}, + {file = "ruff-0.15.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:89f463f7c8205a9f8dea9d658d59eff49db05f88f89cc3047fb1a02d9f344010"}, + {file = "ruff-0.15.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba786a8295c6574c1116704cf0b9e6563de3432ac888d8f83685654fe528fd65"}, + {file = "ruff-0.15.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd4b801e57955fe9f02b31d20375ab3a5c4415f2e5105b79fb94cf2642c91440"}, + {file = "ruff-0.15.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391f7c73388f3d8c11b794dbbc2959a5b5afe66642c142a6effa90b45f6f5204"}, + {file = "ruff-0.15.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc18f30302e379fe1e998548b0f5e9f4dff907f52f73ad6da419ea9c19d66c8"}, + {file = "ruff-0.15.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc6e7f90087e2d27f98dc34ed1b3ab7c8f0d273cc5431415454e22c0bd2a681"}, + {file = "ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1cb7169f53c1ddb06e71a9aebd7e98fc0fea936b39afb36d8e86d36ecc2636a"}, + {file = "ruff-0.15.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9b037924500a31ee17389b5c8c4d88874cc6ea8e42f12e9c61a3d754ff72f1ca"}, + {file = "ruff-0.15.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:65bb414e5b4eadd95a8c1e4804f6772bbe8995889f203a01f77ddf2d790929dd"}, + {file = "ruff-0.15.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d20aa469ae3b57033519c559e9bc9cd9e782842e39be05b50e852c7c981fa01d"}, + {file = "ruff-0.15.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:15388dd28c9161cdb8eda68993533acc870aa4e646a0a277aa166de9ad5a8752"}, + {file = "ruff-0.15.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b30da330cbd03bed0c21420b6b953158f60c74c54c5f4c1dabbdf3a57bf355d2"}, + {file = "ruff-0.15.5-py3-none-win32.whl", hash = "sha256:732e5ee1f98ba5b3679029989a06ca39a950cced52143a0ea82a2102cb592b74"}, + {file = "ruff-0.15.5-py3-none-win_amd64.whl", hash = "sha256:821d41c5fa9e19117616c35eaa3f4b75046ec76c65e7ae20a333e9a8696bc7fe"}, + {file = "ruff-0.15.5-py3-none-win_arm64.whl", hash = "sha256:b498d1c60d2fe5c10c45ec3f698901065772730b411f164ae270bb6bfcc4740b"}, + {file = "ruff-0.15.5.tar.gz", hash = "sha256:7c3601d3b6d76dce18c5c824fc8d06f4eef33d6df0c21ec7799510cde0f159a2"}, +] + [[package]] name = "scikit-learn" version = "1.8.0" @@ -3198,7 +3231,23 @@ docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx_rtd_theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["pytest", "websockets"] +[[package]] +name = "win32-setctime" +version = "1.2.0" +description = "A small Python utility to set file creation time on Windows" +optional = false +python-versions = ">=3.5" +groups = ["main"] +markers = "sys_platform == \"win32\"" +files = [ + {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, + {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, +] + +[package.extras] +dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] + [metadata] lock-version = "2.1" -python-versions = ">=3.11" -content-hash = "dfb5e761522323802ddc653bb61de697436ad55d50ade1c3b86e9ef318ca35f2" +python-versions = ">=3.11,<4.0" +content-hash = "ce3bd6a9236ac7a3b732c0b976dbb2074d8e3ee826779c59f3ab17f6cfbb9d7b" diff --git a/pyproject.toml b/pyproject.toml index 006462e..ff667f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,17 +6,19 @@ authors = [ {name = "Your Name",email = "you@example.com"} ] readme = "README.md" -requires-python = ">=3.11" +requires-python = ">=3.11,<4.0" dependencies = [ "scikit-learn (>=1.8.0,<2.0.0)", "pandas (>=3.0.1,<4.0.0)", - "seaborn (>=0.13.2,<0.14.0)" + "seaborn (>=0.13.2,<0.14.0)", + "loguru (>=0.7.3,<0.8.0)", ] [tool.poetry] [tool.poetry.group.dev.dependencies] notebook = "^7.5.4" +ruff = "^0.15.5" [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] diff --git a/src/diamonds/__pycache__/__init__.cpython-311.pyc b/src/diamonds/__pycache__/__init__.cpython-311.pyc index 9d7ffdbe39d9b3be549b82c7bac955f3cdcd59bf..e9cf139a8b7cf89d9d17f2623a21530b3fbb8e86 100644 GIT binary patch delta 52 zcmZo>YGLA9&dbZi00gpECUW)2+3RQI=ceix=NBcGid_brR7iD G8~^};AQ2A$ delta 51 zcmZo+YG&eE&dbZi00g%VP2}p4wbReY&rQ|ON>0v5EK15Z)KAV&N!3ruOw7&COPRPO F004g;5ZwR( diff --git a/src/diamonds/__pycache__/data.cpython-311.pyc b/src/diamonds/__pycache__/data.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b1b08ed7b3af04fc6c9a8f955755a64a27cb6cc GIT binary patch literal 3696 zcmbtXO>7&-6`ox#m&+e<8B(My*@+p&R!m2sV%1WFL{>s4Rh7z-(%Jz8Ht1r_T}qTm zE<3x7ErE)+MSwDb011Tw^Uwl31g-)LXpTMf&}(m8VNnqa2vAYtc{=TozgP{E9Z-2;q;zj81KKi)F2d^QpE`&~U=*fcN;X zwi}5vTV=J~mZ)x1Hjo=>OiK=-D$#JJNOboo3Ta$NXqC)tmud@2Er$K8`8%JI1E2tN zJZ;ajK|M#;sTn%sOFj0hv){vd=NaqU`+?AR?M(?)-JQ8Rtr8`%d#)$o#-}z+NDqbb z@$X>^cgB`*M{noA^saLQl@I{My@1JPub;oAh*BoM9Bm;YDv6q?%33@gw;Wi!zwT@G z#8c|0>lfb>Q!7MXTalkNW){%q%;Y8c!TQMaR7cZT$wgD3NQPNrKFguzRm+zJON5iz zEjFtxFU#0sGWoP((TZv@1yNhEm{lc{$HeCrD?iAn8bDZ61Tf8_3zEeF&L#2{qb;wL z7FxDj9Pk99K_&Yfjeh&~*ou;q$5aK2nsPU@R!l2nDMgaU7K>?Uwg!%=IMw+e*2N2J zmb+~$J_qVZ^ilr|L`R3guo)b#zGVdCW-zYLH)x-e`}YuXdVf9ttNB{sb%TkUOuWX# z5BV3i?r)biOTYV|D)0W>;HOP~TAw@g_HDhnJ+nDexng)eD# z!r&%NZnDNr9!3Vu$VheFh>V+&@v^thg$}r(eQu~SwL4Mch79hS$z7}2^&hR_(*}3L zumoV^{;SXepgKh3if{$U-lKb?S4pL6rbURU&?- z0H*0ZM>nQBp>cyQ!6Pvpj^u2H$PR~sSW=<^rR+kNA;fhdc#lcYC5DvHrwG#$h)NC+ zXBIFKnZ5HB0vI~5a$hCuh~fdDmj9kC7lgc`31T*@++QC~Wo0pMBQ8FjRZ?PBor!nL z#9*A-4@5_GuW!duo+?jOKCXOR=R;);6NA4Y6ToDQ2w=3R2etv^42Xq7b}i<>L(q>e z5<-rrN{}0ko>=7RSb#4<$E!qQ5r~c&4DIZ1pf+JqD7^F2$4kFis^q`EwzFh}Crqfp zNqxS~@H^hhduAY7P3#9Qo6Ja!8L@HKxPW{E;8xqxuAL-ikoR~J$m8d_Qlgfry`GT0 zL4k8f2yraHse-Jstl+h;D9e?}r?N#!hQ;@(a#l`hf~2h#WHm-NH^E+i^Yk?x!k?rg zSygQ>;HzNF47}WL+P%^ewc54?@*F_!RK8|G3!NtC zoLjJ*1)NC{@VHV+wwQy2z~+m&yE4Y)RA7P#i&gHf07Fc(F3kV5XNV*n3JvWvaAVdxEmF*EaZWs3QAFHYIfPM zwWuYFTC+GXMgYrH8}rSUuY+F&Ti&J4JSy2JIOe1@vFXu=Fl=(n2TVF-mT9t21C zgQL4YF@j@ea7>>+4E8@7gz;!clz3%6?mK!c6#QqZj`4=H@5ReQ6ERm8c1 z&~zyWHv>ELf+6YFr5K`+Ea3^Fj08peA|WIi*be-bn+7wAS$PKk2zVqcs6PYRa8ML= zgxtFQ)KRF`s&&+-+fN-`u65Ts3fEe-j$*a$dgSJ}Uewtm|4ZeR>3^xRZuqa7{;RsT z!JMN8cE%q~HxM*>$@Orn6B^Zd56Z$X6({LkZ2(;Ln|6ho)B<}zK literal 0 HcmV?d00001 diff --git a/src/diamonds/__pycache__/model.cpython-311.pyc b/src/diamonds/__pycache__/model.cpython-311.pyc index af9df8174247594ab5dc8b64b0056987ffe89235..8ffbe4390aa10c77f1c5d23d1ce15e99c0ffc0f7 100644 GIT binary patch delta 516 zcmXv~&ui2`6wV~O`LS!Z3&l%mWu>6x(mjf`C2Oq#6FIiu3NF{$=9M(DSXPmPBu+DR?MDuscM}dR>_fk=}deD@fDRFJoJ@-zCWu2j4 zTW(Wd2LErCMFZM8Z=cwhW2?}Mf*VKnk(E0%RI#^2I%?Njd3#WoqoS-}5p}SHpk0xr zV+PvGQfZ!aSaKmpIj}c1JCG64zK}RG+dI?_-)Fj+7a(L3*}6f2W4@?T5NyP2S=CZI z*g`v4EOMb?x|k8cYy!S@>}Rc23|G*_sVe=K^PTtMhkM^|PP_5XZanM8Q-7dl{)`MJ zr@>c3*43-_Vt2#H9~sy*@L0WT$7DG9(SB+_e2z@ifCLY1S5&)O3<@S-%kU1Y8^H?$ z&k%(9-(If=cMM}RkW6+u_sPaK#@fME;jW1q;{szdD-5pgw8$jxKIW-}p<#l}RHg}} TC4(K4mZ<660?8+T=Dv}CQmu-v delta 473 zcmY*VO-lk%6rDGtGk#=RxTsK&gu+eIE*1JP2`mgsXj{{~XHGdYa%UunY0+Jmq6_!ja}Vb{F0Y%uOh?+0NJwB+|Gd!$w~?|xS;*Ec zgJcgit**kpHJ{ZiOtM&44a>yT@xO)?=9gH%e^4SfbI9SsZ()B&zCwa<&3afh5i3sc zZxaL@=mduj8dEZ}Ay;&TnuNoy>q;JYuXo2PCSlexS64)6VKd*Er z`tkf@JU@u%`+)*|2@KF;?;&`HP=OlZL~NP4VTD7H!z#T9FQH2BDZDPOY%nF`gAyB_ z*uoIaJ(c+>>kvV3spqLuZ^{3X4BG k)-}iT*BX}UK!q#8lIo~ypc(|K+*YE`(J6#`U(tK?4deiMlK=n! diff --git a/src/diamonds/__pycache__/params.cpython-311.pyc b/src/diamonds/__pycache__/params.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..549953b28f2549b143f2bfc513d3112a2680c041 GIT binary patch literal 360 zcmZ3^%ge<81hQAwW#$3t#~=<2us|7~eSnPV3@HpLj5!QZ3@J=ej48}fOsNc6%rK=3 zU}|9kU^;~*g>@Md1H)<{hJYy66vki%O}3XHuHP+|l*E$6TWq=cDXBTdxA=VhU0i+Q zgIwJ`gF}KMZ?Wd&Cnx4;vfX0JFTTa;;uzu>AK)0`af=J04$Njx%`3|+%FnySoSs@z z#0oTZCBtWs;lFJ4GxBp&^^5b15=-)vGAm2d^7WH}7U}z!rU98LnTfgic`3#E#YM>o zPC;T(Vs5csLFF$F8=$L7b5iY!_<^P|0&%eskodsN$jEqufwKV&A8-pcaNgh*ZQyz! fC_F`Ky4)nW3kn7s)GrEJT@kcu-~+)TUZ6GrXggdw literal 0 HcmV?d00001 diff --git a/src/diamonds/__pycache__/registry.cpython-311.pyc b/src/diamonds/__pycache__/registry.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..950cfebe0825183e3f0b372282ea519343df4129 GIT binary patch literal 1669 zcmcIkO=ufO6rNd)R%@*-w@ECQR<0)@l*$K-(q3#z3njK28Yivn9;%C3Yew-}yIL_b z3bj!olpcEM!GS^orQnm>;6mM7j=l6+Rz?uBU@!z9dK38OQ{Sw961nN2hdyTC@667; zdEc9##>UbJ=(pov-R}|zJ<~>?%${<#3Ccsn5W^nwaS3Cs8=m1ON(rBoNNgv(q;HnY zSSMb}w@Mc1Np3Qek8r%5LWrd}u9(dFhLqAnUb8~j2zYIlUO{>LFTHUdN90pSZRCxJ zu!dich!;2vykj3Zk}pW*`i=?&I5Nw3ZYEYi*tTJKN@=&p?&ze^fgw=zK&264@bW; zn#ShfZ@YT;e-KNs#4ltIPPsogDMreEKCy|K#>IHkfa^+bzq8`pw!>%WrE*zr4n27bQP{XRd)ohDH&P( zOK`6R)x0U7lqkAAZbEALO+4@$LmT(Dc zaq40MeyVXT9bos-X=>upcPzSGxt9^ zBI9k6eM)kNB)7YIa3dtS7MW|4xsc2q6YJZF9lJ$xZIXk)k(~`m_6#;bv38O6s-h}8k?s*Fo{?6#4dPZoXP0b zMVJZ@ThtS~;L9eU+|9UK}0(gpTk%Wr3&+Ea)2RLh=j z+tVF{lON;b%ydW>pS%GKMk}+_&Mbx2(y2WTV6by-TZ2JlVYl1)QQb3Y!*kbr32g@J z+R&H~I)!LdRz2>B+Uz pd.DataFrame: +def load_data() -> pd.DataFrame: df_diamonds = sns.load_dataset("diamonds") """ Load the diamonds dataset. @@ -20,7 +25,15 @@ def load_data(cache = True) -> pd.DataFrame: pd.DataFrame The diamonds dataset """ - print(df_diamonds.head()) + logger.info("Loading diamonds dataset...") + csv_path = os.path.join(DATA_PATH,"raw", "diamonds.csv") + if not os.path.exists(csv_path): + logger.info("Caching the diamonds dataset...") + df_diamonds = sns.load_dataset("diamonds") + df_diamonds.to_csv(csv_path, index=False) + else: + logger.info("Loading diamonds dataset from cache...") + df_diamonds = pd.read_csv(csv_path) return df_diamonds def clean_data(df: pd.DataFrame) -> pd.DataFrame: @@ -61,8 +74,10 @@ def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: pd.DataFrame The preprocessed diamonds dataset """ + preprocessor = create_preproc() + df_preprocessed = preprocessor.transform(df) - return df + return df_preprocessed def create_X_y(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series]: # Split target first so preprocessing columns only reference feature columns. diff --git a/src/diamonds/model.py b/src/diamonds/model.py index 7511601..1de07b4 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -9,8 +9,11 @@ from sklearn.neighbors import KNeighborsRegressor from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, mean_absolute_percentage_error +from diamonds.model import save_model import pandas as pd +import loguru +logger = loguru.logger def create_model(model_name: str) -> BaseEstimator: """ @@ -69,10 +72,41 @@ def create_preproc(num_cols: list[str], cat_cols: list[str]) -> Pipeline: return preprocessing def train_model(model, X_train, y_train): + """ + Train model and save it. + + Parameters + ---------- + model : any + The model to train + X_train : pd.DataFrame + The training data + y_train : pd.Series + The target variable + """ + loguru.info("Training model...") model.fit(X_train, y_train) - return model + loguru.info("Model trained. Saving...") + save_model(model, "model") def evaluate_model(model, X_test, y_test) -> dict[str, float]: + """ + Evaluate the model on the test set. + + Parameters + ---------- + model : any + The model to evaluate + X_test : pd.DataFrame + The test data + y_test : pd.Series + The target variable + + Returns + ------- + dict[str, float] + The metrics for the model. + """ # NB : mae, mse, r2_score, mape # Only print the metrics for now y_pred = model.predict(X_test) @@ -92,6 +126,8 @@ def evaluate_model(model, X_test, y_test) -> dict[str, float]: for name, value in metrics.items(): print(f"{name}: {value:.4f}") + return metrics + def predict(model, X: pd.DataFrame) -> pd.Series: """ Make predictions using the trained model. diff --git a/src/diamonds/registry.py b/src/diamonds/registry.py index a3f407a..7af1ffe 100644 --- a/src/diamonds/registry.py +++ b/src/diamonds/registry.py @@ -1,30 +1,18 @@ - -from pathlib import Path - -from joblib import dump, load +import pickle +import os from sklearn.base import BaseEstimator - -from diamonds.params import MODEL_REGISTRY +from diamonds.params import MODEL_PATH -def save_model(model: BaseEstimator, path: str | Path) -> Path: +def save_model(model: BaseEstimator, name: str): """Save a trained model to disk and return its path.""" - if MODEL_REGISTRY != "local": - raise NotImplementedError(f"Unsupported model registry: {MODEL_REGISTRY}") + model_path = os.path.join(MODEL_PATH, f"{name}.pkl") + with open(model_path, "wb") as f: + pickle.dump(model, f) - target_path = Path(path) - target_path.parent.mkdir(parents=True, exist_ok=True) - dump(model, target_path) - return target_path - -def load_model(path: str | Path) -> BaseEstimator: +def load_model(name: str) -> BaseEstimator: """Load a previously saved model from disk.""" - if MODEL_REGISTRY != "local": - raise NotImplementedError(f"Unsupported model registry: {MODEL_REGISTRY}") - - target_path = Path(path) - if not target_path.exists(): - raise FileNotFoundError(f"Model file not found: {target_path}") - - return load(target_path) \ No newline at end of file + model_path = os.path.join(MODEL_PATH, f"{name}.pkl") + with open(model_path, "rb") as f: + return pickle.load(f) \ No newline at end of file diff --git a/src/diamonds/train.py b/src/diamonds/train.py index 7591095..b2a0681 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -26,31 +26,31 @@ def train( """ # 1) Data df = load_data() - df_clean = clean_data(df) - df_preprocessed = preprocess_data(df_clean) - X, y = create_X_y(df_preprocessed) - - X_train, X_test, y_train, y_test = train_test_split( - X, - y, - test_size=test_size, - random_state=random_state, - ) - - # 2) Model + preprocessing - resolved_model_name = "linear" if model_name == "baseline" else model_name - model = create_model(resolved_model_name) - trained_model = train_model(model, X_train, y_train) + # df_clean = clean_data(df) + # df_preprocessed = preprocess_data(df_clean) + # X, y = create_X_y(df_preprocessed) + + # X_train, X_test, y_train, y_test = train_test_split( + # X, + # y, + # test_size=test_size, + # random_state=random_state, + # ) + + # # 2) Model + preprocessing + # resolved_model_name = "linear" if model_name == "baseline" else model_name + # model = create_model(resolved_model_name) + # trained_model = train_model(model, X_train, y_train) - # 3) Evaluation - evaluate_model(trained_model, X_test, y_test) + # # 3) Evaluation + # evaluate_model(trained_model, X_test, y_test) - # 4) Persistence - model_dir = Path(MODEL_PATH) - model_dir.mkdir(parents=True, exist_ok=True) - model_path = model_dir / f"{resolved_model_name}.joblib" - saved_path = save_model(trained_model, model_path) - print(f"Model saved to: {saved_path}") + # # 4) Persistence + # model_dir = Path(MODEL_PATH) + # model_dir.mkdir(parents=True, exist_ok=True) + # model_path = model_dir / f"{resolved_model_name}.joblib" + # saved_path = save_model(trained_model, model_path) + # print(f"Model saved to: {saved_path}") if __name__ == "__main__": From 55c5ad7e92e7fef1f58532f67a311e8057d3ed5a Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Tue, 10 Mar 2026 10:38:51 +0000 Subject: [PATCH 11/20] add linter and fix format/ruff rules --- Makefile | 15 ++++ notebooks/Exploration.ipynb | 159 +++++++++++++++++++----------------- pyproject.toml | 20 +++++ src/diamonds/data.py | 17 ++-- src/diamonds/model.py | 48 +++++------ src/diamonds/params.py | 4 +- src/diamonds/registry.py | 4 +- src/diamonds/train.py | 63 +++++++------- 8 files changed, 185 insertions(+), 145 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6b98525 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +.PHONY: lint lint-fix format lint-all + +lint: + @echo "checking lint with ruff" + poetry run ruff check . + +lint-fix: + @echo "auto fix lint with ruff" + poetry run ruff check . --fix + +format: + @echo "checking format" + poetry run ruff format . + +lint-all: lint lint-fix format \ No newline at end of file diff --git a/notebooks/Exploration.ipynb b/notebooks/Exploration.ipynb index 4c7af4f..296bff5 100644 --- a/notebooks/Exploration.ipynb +++ b/notebooks/Exploration.ipynb @@ -7,7 +7,7 @@ "metadata": {}, "outputs": [], "source": [ - "# NB : This reload your library after each edit, \n", + "# NB : This reload your library after each edit,\n", "# so you don't have to restart the kernel\n", "%load_ext autoreload\n", "%autoreload 2" @@ -29,7 +29,6 @@ "outputs": [], "source": [ "import seaborn as sns\n", - "import matplotlib.pyplot as plt\n", "import plotly.express as px\n", "\n", "# ML\n", @@ -54,7 +53,7 @@ "metadata": {}, "outputs": [], "source": [ - "df_diamonds = sns.load_dataset('diamonds')" + "df_diamonds = sns.load_dataset(\"diamonds\")" ] }, { @@ -437,8 +436,7 @@ } ], "source": [ - "sns.histplot(data=df_diamonds,\n", - " x=\"price\")" + "sns.histplot(data=df_diamonds, x=\"price\")" ] }, { @@ -1352,8 +1350,7 @@ } ], "source": [ - "px.scatter_3d(data_frame=df_diamonds,\n", - " x=\"x\",y=\"y\",z=\"z\", color=\"price\")" + "px.scatter_3d(data_frame=df_diamonds, x=\"x\", y=\"y\", z=\"z\", color=\"price\")" ] }, { @@ -1415,9 +1412,9 @@ } ], "source": [ - "sns.heatmap(df_diamonds.select_dtypes(include=\"number\").corr(),\n", - " annot=True,\n", - " cmap=\"coolwarm\")" + "sns.heatmap(\n", + " df_diamonds.select_dtypes(include=\"number\").corr(), annot=True, cmap=\"coolwarm\"\n", + ")" ] }, { @@ -1446,8 +1443,7 @@ } ], "source": [ - "df_diamonds.select_dtypes(include=\"category\")\\\n", - " [\"color\"].value_counts()" + "df_diamonds.select_dtypes(include=\"category\")[\"color\"].value_counts()" ] }, { @@ -1470,7 +1466,11 @@ ], "source": [ "import scipy.stats as stats\n", - "groups = [group[\"price\"].values for name, group in df_diamonds.groupby(\"color\", observed=False)]\n", + "\n", + "groups = [\n", + " group[\"price\"].values\n", + " for name, group in df_diamonds.groupby(\"color\", observed=False)\n", + "]\n", "\n", "\n", "print(\"--- Test ANOVA à un facteur ---\")\n", @@ -1479,9 +1479,13 @@ "print(f\"P-value : {p_value_anova:.2e}\")\n", "\n", "if p_value_anova < 0.05:\n", - " print(\"Conclusion : On rejette H0. La couleur a un impact significatif sur le prix moyen.\\n\")\n", + " print(\n", + " \"Conclusion : On rejette H0. La couleur a un impact significatif sur le prix moyen.\\n\"\n", + " )\n", "else:\n", - " print(\"Conclusion : On ne peut pas rejeter H0. La couleur ne semble pas impacter le prix.\\n\")" + " print(\n", + " \"Conclusion : On ne peut pas rejeter H0. La couleur ne semble pas impacter le prix.\\n\"\n", + " )" ] }, { @@ -1494,7 +1498,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": null, "id": "27c4ffbc-55f9-4970-9d4b-df1101c3134d", "metadata": {}, "outputs": [ @@ -1510,13 +1514,14 @@ } ], "source": [ - "def keep_not_null(row) :\n", - " if 0 in row.values : return False\n", + "def keep_not_null(row):\n", + " if 0 in row.values:\n", + " return False\n", " return True\n", "\n", + "\n", "# Pour le test sur une ligne :\n", - "keep_not_null(df_diamonds.loc[11182,:])\n", - " " + "keep_not_null(df_diamonds.loc[11182, :])" ] }, { @@ -1526,7 +1531,7 @@ "metadata": {}, "outputs": [], "source": [ - "df_clean = df_diamonds[df_diamonds.apply(keep_not_null,axis=1)]" + "df_clean = df_diamonds[df_diamonds.apply(keep_not_null, axis=1)]" ] }, { @@ -1619,7 +1624,7 @@ "X = df_clean.drop(columns=[\"price\"])\n", "y = df_clean[\"price\"]\n", "\n", - "X_train, X_test, y_train, y_test = train_test_split(X,y, random_state=42)\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)\n", "X_train.shape, X_test.shape, y_train.shape, y_test.shape" ] }, @@ -2464,9 +2469,11 @@ ], "source": [ "cat_pipe = Pipeline(\n", - " [ (\"cat_imp\",SimpleImputer(strategy=\"most_frequent\"))\n", - " ,(\"ohe\",OneHotEncoder(drop=\"first\",sparse_output=False))\n", - " ])\n", + " [\n", + " (\"cat_imp\", SimpleImputer(strategy=\"most_frequent\")),\n", + " (\"ohe\", OneHotEncoder(drop=\"first\", sparse_output=False)),\n", + " ]\n", + ")\n", "cat_pipe" ] }, @@ -3189,11 +3196,9 @@ ], "source": [ "num_pipe = Pipeline(\n", - " [(\"knn_imp\", KNNImputer(n_neighbors=5))\n", - " ,(\"scaler\", StandardScaler())\n", - " ])\n", - "num_pipe\n", - " " + " [(\"knn_imp\", KNNImputer(n_neighbors=5)), (\"scaler\", StandardScaler())]\n", + ")\n", + "num_pipe" ] }, { @@ -4135,9 +4140,11 @@ ], "source": [ "preprocessor = ColumnTransformer(\n", - " [(\"numeric\",num_pipe, make_column_selector(dtype_include=\"number\"))\n", - " ,(\"categorical\", cat_pipe, make_column_selector(dtype_exclude=\"number\"))\n", - " ]).set_output(transform=\"pandas\")\n", + " [\n", + " (\"numeric\", num_pipe, make_column_selector(dtype_include=\"number\")),\n", + " (\"categorical\", cat_pipe, make_column_selector(dtype_exclude=\"number\")),\n", + " ]\n", + ").set_output(transform=\"pandas\")\n", "preprocessor" ] }, @@ -4148,11 +4155,10 @@ "metadata": {}, "outputs": [], "source": [ - "\n", - "# Normalement j'ai pas besoin de preproc mais pour vérfier \n", + "# Normalement j'ai pas besoin de preproc mais pour vérfier\n", "preprocessor.fit(X_train)\n", "X_train_scaled = preprocessor.transform(X_train)\n", - "X_test_scaled = preprocessor.transform(X_test)" + "X_test_scaled = preprocessor.transform(X_test)" ] }, { @@ -4182,7 +4188,7 @@ } ], "source": [ - "from sklearn.linear_model import LinearRegression, ElasticNet\n", + "from sklearn.linear_model import LinearRegression\n", "from sklearn.ensemble import RandomForestRegressor\n", "from sklearn.neighbors import KNeighborsRegressor\n", "from sklearn.svm import SVR\n", @@ -4199,14 +4205,14 @@ "source": [ "from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\n", "\n", - "def evaluate_model(y_true,y_pred) -> dict[float] : \n", - " mae = mean_absolute_error(y_true,y_pred)\n", - " mse = mean_squared_error(y_true,y_pred)\n", - " r2 = r2_score(y_true,y_pred) \n", - " scores = {\"mae\":mae,\"mse\":mse,\"r2\":r2}\n", + "\n", + "def evaluate_model(y_true, y_pred) -> dict[float]:\n", + " mae = mean_absolute_error(y_true, y_pred)\n", + " mse = mean_squared_error(y_true, y_pred)\n", + " r2 = r2_score(y_true, y_pred)\n", + " scores = {\"mae\": mae, \"mse\": mse, \"r2\": r2}\n", " print(scores)\n", - " return scores\n", - " " + " return scores" ] }, { @@ -4235,9 +4241,9 @@ ], "source": [ "lin = LinearRegression()\n", - "lin.fit(X_train_scaled,y_train) \n", + "lin.fit(X_train_scaled, y_train)\n", "y_pred = lin.predict(X_test_scaled)\n", - "evaluate_model(y_test,y_pred)" + "evaluate_model(y_test, y_pred)" ] }, { @@ -4266,9 +4272,9 @@ ], "source": [ "forest = RandomForestRegressor()\n", - "forest.fit(X_train_scaled,y_train)\n", + "forest.fit(X_train_scaled, y_train)\n", "y_pred = forest.predict(X_test_scaled)\n", - "evaluate_model(y_test,y_pred)" + "evaluate_model(y_test, y_pred)" ] }, { @@ -4297,9 +4303,9 @@ ], "source": [ "knn = KNeighborsRegressor()\n", - "knn.fit(X_train_scaled,y_train)\n", + "knn.fit(X_train_scaled, y_train)\n", "y_pred = knn.predict(X_test_scaled)\n", - "evaluate_model(y_test,y_pred)" + "evaluate_model(y_test, y_pred)" ] }, { @@ -4328,9 +4334,9 @@ ], "source": [ "svm = SVR()\n", - "svm.fit(X_train_scaled,y_train)\n", + "svm.fit(X_train_scaled, y_train)\n", "y_pred = svm.predict(X_test_scaled)\n", - "evaluate_model(y_test,y_pred)" + "evaluate_model(y_test, y_pred)" ] }, { @@ -4339,9 +4345,7 @@ "id": "966abe76-ef40-490b-b043-d560525f6973", "metadata": {}, "outputs": [], - "source": [ - "\n" - ] + "source": [] }, { "cell_type": "code", @@ -5146,12 +5150,12 @@ "source": [ "from sklearn.model_selection import GridSearchCV\n", "\n", - "grid = {\"n_neighbors\": range(2,30)}\n", + "grid = {\"n_neighbors\": range(2, 30)}\n", "\n", "\n", "search = GridSearchCV(KNeighborsRegressor(), grid, verbose=1)\n", "\n", - "search.fit(X_train_scaled,y_train)" + "search.fit(X_train_scaled, y_train)" ] }, { @@ -5182,7 +5186,7 @@ "source": [ "y_pred = search.predict(X_test_scaled)\n", "print(search.best_params_)\n", - "evaluate_model(y_test,y_pred)" + "evaluate_model(y_test, y_pred)" ] }, { @@ -6072,13 +6076,14 @@ } ], "source": [ - "grid = {\"n_estimators\": [100,150,300,500]\n", - " #,\"max_depth\" : [None, 2,5,10]\n", - " #,\"min_samples_leaf\" : [1,5,10,50]\n", - " }\n", + "grid = {\n", + " \"n_estimators\": [100, 150, 300, 500]\n", + " # ,\"max_depth\" : [None, 2,5,10]\n", + " # ,\"min_samples_leaf\" : [1,5,10,50]\n", + "}\n", "\n", - "search = GridSearchCV(RandomForestRegressor(),grid,verbose=1, cv=3)\n", - "search.fit(X_train_scaled,y_train)\n" + "search = GridSearchCV(RandomForestRegressor(), grid, verbose=1, cv=3)\n", + "search.fit(X_train_scaled, y_train)" ] }, { @@ -6109,7 +6114,7 @@ "source": [ "y_pred = search.predict(X_test_scaled)\n", "print(search.best_params_)\n", - "evaluate_model(y_test,y_pred)" + "evaluate_model(y_test, y_pred)" ] }, { @@ -6146,9 +6151,9 @@ ], "source": [ "forest = RandomForestRegressor(**search.best_params_)\n", - "forest.fit(X_train_scaled,y_train)\n", + "forest.fit(X_train_scaled, y_train)\n", "y_pred = forest.predict(X_test_scaled)\n", - "evaluate_model(y_test,y_pred)" + "evaluate_model(y_test, y_pred)" ] }, { @@ -6166,8 +6171,8 @@ "metadata": {}, "outputs": [], "source": [ - "import pickle \n", - "import os " + "import pickle\n", + "import os" ] }, { @@ -6195,12 +6200,12 @@ "metadata": {}, "outputs": [], "source": [ - "# Saving the preprocessor \n", + "# Saving the preprocessor\n", "model_path = \"models\"\n", - "if not os.path.exists(model_path) : \n", + "if not os.path.exists(model_path):\n", " os.mkdir(model_path)\n", - "with open(os.path.join(model_path,\"preproc.pkl\"),\"wb\") as f:\n", - " pickle.dump(preprocessor,f)" + "with open(os.path.join(model_path, \"preproc.pkl\"), \"wb\") as f:\n", + " pickle.dump(preprocessor, f)" ] }, { @@ -6210,9 +6215,9 @@ "metadata": {}, "outputs": [], "source": [ - "# Saving the model \n", - "with open(os.path.join(model_path,\"model.pkl\"),\"wb\") as f:\n", - " pickle.dump(forest,f)" + "# Saving the model\n", + "with open(os.path.join(model_path, \"model.pkl\"), \"wb\") as f:\n", + " pickle.dump(forest, f)" ] }, { @@ -7177,7 +7182,7 @@ } ], "source": [ - "with open(os.path.join(model_path,\"preproc.pkl\"),\"rb\") as f:\n", + "with open(os.path.join(model_path, \"preproc.pkl\"), \"rb\") as f:\n", " new_preproc = pickle.load(f)\n", "new_preproc" ] diff --git a/pyproject.toml b/pyproject.toml index ff667f8..6266850 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,3 +23,23 @@ ruff = "^0.15.5" [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.ruff] +line-length = 100 +target-version = "py311" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "F", # pyflakes + "I", # isort + "B", # bugbear + "UP", # pyupgrade +] +ignore = [ + "E501" +] + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" \ No newline at end of file diff --git a/src/diamonds/data.py b/src/diamonds/data.py index 04b7692..c451186 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -10,6 +10,7 @@ df_diamonds = sns.load_dataset("diamonds") + def load_data() -> pd.DataFrame: df_diamonds = sns.load_dataset("diamonds") """ @@ -26,7 +27,7 @@ def load_data() -> pd.DataFrame: The diamonds dataset """ logger.info("Loading diamonds dataset...") - csv_path = os.path.join(DATA_PATH,"raw", "diamonds.csv") + csv_path = os.path.join(DATA_PATH, "raw", "diamonds.csv") if not os.path.exists(csv_path): logger.info("Caching the diamonds dataset...") df_diamonds = sns.load_dataset("diamonds") @@ -36,11 +37,14 @@ def load_data() -> pd.DataFrame: df_diamonds = pd.read_csv(csv_path) return df_diamonds + def clean_data(df: pd.DataFrame) -> pd.DataFrame: - + def keep_not_allow(row): - if 0 in row: return False + if 0 in row: + return False return True + df_diamonds = df[df.apply(keep_not_allow, axis=1)] df_diamonds[df_diamonds["x"] == 0] """ @@ -59,8 +63,8 @@ def keep_not_allow(row): return df_diamonds + def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: - df_diamonds = df.select_dtypes(include=["category"]) """ Preprocess the diamonds dataset. @@ -79,6 +83,7 @@ def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: return df_preprocessed + def create_X_y(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series]: # Split target first so preprocessing columns only reference feature columns. X = df.drop(columns="price") @@ -107,12 +112,10 @@ def create_X_y(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series]: index=X.index, ) return X_transform, y - - if __name__ == "__main__": df = load_data() df_clean = clean_data(df) df_preprocessed = preprocess_data(df_clean) - X, y = create_X_y(df_preprocessed) \ No newline at end of file + X, y = create_X_y(df_preprocessed) diff --git a/src/diamonds/model.py b/src/diamonds/model.py index 1de07b4..c2bb337 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -8,13 +8,19 @@ from sklearn.ensemble import RandomForestRegressor from sklearn.neighbors import KNeighborsRegressor from sklearn.linear_model import LinearRegression -from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, mean_absolute_percentage_error +from sklearn.metrics import ( + mean_absolute_error, + mean_squared_error, + r2_score, + mean_absolute_percentage_error, +) from diamonds.model import save_model import pandas as pd import loguru logger = loguru.logger + def create_model(model_name: str) -> BaseEstimator: """ Create an untrained model with the best hyperparameters found during tuning. @@ -33,9 +39,7 @@ def create_model(model_name: str) -> BaseEstimator: models = { "ridge": Ridge(alpha=1.0), "random_forest": RandomForestRegressor( - n_estimators=200, - max_depth=10, - random_state=42 + n_estimators=200, max_depth=10, random_state=42 ), "knn": KNeighborsRegressor(n_neighbors=5), "linear": LinearRegression(fit_intercept=True), @@ -46,31 +50,33 @@ def create_model(model_name: str) -> BaseEstimator: return models[model_name] + def create_preproc(num_cols: list[str], cat_cols: list[str]) -> Pipeline: """ Create a preprocessing pipeline. """ # pipeline numérique - num_pipeline = Pipeline([ - ("num_imp", KNNImputer(n_neighbors=5)), - ("scaler", StandardScaler()) - ]) + num_pipeline = Pipeline( + [("num_imp", KNNImputer(n_neighbors=5)), ("scaler", StandardScaler())] + ) # pipeline catégorique - cat_pipeline = Pipeline([ - ("cat_imp", SimpleImputer(strategy="most_frequent")), - ("ohe", OneHotEncoder(drop="first",sparse_output=False)) - ]) + cat_pipeline = Pipeline( + [ + ("cat_imp", SimpleImputer(strategy="most_frequent")), + ("ohe", OneHotEncoder(drop="first", sparse_output=False)), + ] + ) # combiner les deux - preprocessing = ColumnTransformer([ - ("num", num_pipeline, num_cols), - ("cat", cat_pipeline, cat_cols) - ]) + preprocessing = ColumnTransformer( + [("num", num_pipeline, num_cols), ("cat", cat_pipeline, cat_cols)] + ) return preprocessing + def train_model(model, X_train, y_train): """ Train model and save it. @@ -89,6 +95,7 @@ def train_model(model, X_train, y_train): loguru.info("Model trained. Saving...") save_model(model, "model") + def evaluate_model(model, X_test, y_test) -> dict[str, float]: """ Evaluate the model on the test set. @@ -116,18 +123,14 @@ def evaluate_model(model, X_test, y_test) -> dict[str, float]: r2 = r2_score(y_test, y_pred) mape = mean_absolute_percentage_error(y_test, y_pred) - metrics = { - "mae": mae, - "mse": mse, - "r2": r2, - "mape": mape - } + metrics = {"mae": mae, "mse": mse, "r2": r2, "mape": mape} for name, value in metrics.items(): print(f"{name}: {value:.4f}") return metrics + def predict(model, X: pd.DataFrame) -> pd.Series: """ Make predictions using the trained model. @@ -147,4 +150,3 @@ def predict(model, X: pd.DataFrame) -> pd.Series: y_pred = model.predict(X) return pd.Series(y_pred, index=X.index, name="prediction") - diff --git a/src/diamonds/params.py b/src/diamonds/params.py index 49702b5..fb75875 100644 --- a/src/diamonds/params.py +++ b/src/diamonds/params.py @@ -1,6 +1,6 @@ import os -DATA_PATH= "data" +DATA_PATH = "data" MODEL_PATH = "models" -MODEL_REGISTRY = os.environ.get("MODEL_REGISTRY", "local") \ No newline at end of file +MODEL_REGISTRY = os.environ.get("MODEL_REGISTRY", "local") diff --git a/src/diamonds/registry.py b/src/diamonds/registry.py index 7af1ffe..b5ea786 100644 --- a/src/diamonds/registry.py +++ b/src/diamonds/registry.py @@ -8,11 +8,11 @@ def save_model(model: BaseEstimator, name: str): """Save a trained model to disk and return its path.""" model_path = os.path.join(MODEL_PATH, f"{name}.pkl") with open(model_path, "wb") as f: - pickle.dump(model, f) + pickle.dump(model, f) def load_model(name: str) -> BaseEstimator: """Load a previously saved model from disk.""" model_path = os.path.join(MODEL_PATH, f"{name}.pkl") with open(model_path, "rb") as f: - return pickle.load(f) \ No newline at end of file + return pickle.load(f) diff --git a/src/diamonds/train.py b/src/diamonds/train.py index b2a0681..dcd0ff3 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -1,13 +1,9 @@ - - -from pathlib import Path - +import os +from diamonds.data import load_data, clean_data, preprocess_data, create_X_y +from diamonds.model import create_model, train_model, evaluate_model from sklearn.model_selection import train_test_split - -from diamonds.data import clean_data, create_X_y, load_data, preprocess_data -from diamonds.model import create_model, evaluate_model, train_model -from diamonds.params import MODEL_PATH from diamonds.registry import save_model +from diamonds.params import MODEL_PATH def train( @@ -26,33 +22,32 @@ def train( """ # 1) Data df = load_data() - # df_clean = clean_data(df) - # df_preprocessed = preprocess_data(df_clean) - # X, y = create_X_y(df_preprocessed) - - # X_train, X_test, y_train, y_test = train_test_split( - # X, - # y, - # test_size=test_size, - # random_state=random_state, - # ) - - # # 2) Model + preprocessing - # resolved_model_name = "linear" if model_name == "baseline" else model_name - # model = create_model(resolved_model_name) - # trained_model = train_model(model, X_train, y_train) - - # # 3) Evaluation - # evaluate_model(trained_model, X_test, y_test) - - # # 4) Persistence - # model_dir = Path(MODEL_PATH) - # model_dir.mkdir(parents=True, exist_ok=True) - # model_path = model_dir / f"{resolved_model_name}.joblib" - # saved_path = save_model(trained_model, model_path) - # print(f"Model saved to: {saved_path}") + df_clean = clean_data(df) + df_preprocessed = preprocess_data(df_clean) + X, y = create_X_y(df_preprocessed) + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + test_size=test_size, + random_state=random_state, + ) + + # 2) Model + preprocessing + resolved_model_name = "linear" if model_name == "baseline" else model_name + model = create_model(resolved_model_name) + trained_model = train_model(model, X_train, y_train) + + # 3) Evaluation + evaluate_model(trained_model, X_test, y_test) + + # 4) Persistence + model_dir = os.path(MODEL_PATH) + model_dir.mkdir(parents=True, exist_ok=True) + model_path = model_dir / f"{resolved_model_name}.joblib" + saved_path = save_model(trained_model, model_path) + print(f"Model saved to: {saved_path}") if __name__ == "__main__": train() - From ced85c028f910a78acd57a361ec8f3f728a99ec9 Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Tue, 10 Mar 2026 11:12:20 +0000 Subject: [PATCH 12/20] saves suite --- src/diamonds/__pycache__/data.cpython-313.pyc | Bin 2645 -> 3864 bytes .../__pycache__/model.cpython-313.pyc | Bin 3771 -> 4522 bytes .../__pycache__/params.cpython-313.pyc | Bin 348 -> 348 bytes .../__pycache__/registry.cpython-313.pyc | Bin 1456 -> 1342 bytes src/diamonds/data.py | 9 +++++---- src/diamonds/model.py | 7 ++++--- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/diamonds/__pycache__/data.cpython-313.pyc b/src/diamonds/__pycache__/data.cpython-313.pyc index 330dcc0cc077e15d81786bc8cd4486f4f7b6eef0..0d56eeacefd24b40f73600ebef0224bb34cfefda 100644 GIT binary patch literal 3864 zcmbVO-A^0Y6~8kc+v5*B#s&i>39dKE##v$lf&?fbOOmp5$+D>(ORhi~4fbH1m>Ktu zT>@G)&Qn2oAiL5ktW>G=siaaB9^0q(59os(N3t_vE2MqeH@EQEhn_p*u?g!WQm!=j zo_p`P=bX9coZmf%ZEbc0E%U$UY2-xc2Qo35rA{2~QV4yEq9{tuBCL-TrnR{Vn_#48 zna|DG9MJbH*a~Z=S@v@qwgu3FDbitxY>wEzV2${ibAt+^C^G{3NW;#kd4Z1j_1W=$ zn2uWf=pKVzQEO|Cx1MC8tag(7fRi@ur28Ew+gn=$t7nhfuhYY{8HiyfYS-j?7doPj z@i;<4FG35hAR4J3!JP|S5G`~z?!~v@g}Kj|=V`dBF5I1>QdG$KBRMq}qEy?hsk>AB zovFJsFmWZYDC9&wi^VLK6Dpfb3oEjeR8$KVb9pQ!>dLf%*kyw6@SmFN=No$wP<66_ z%P7MX37tXnjKLAH8dP(P(gtq;&9laOL<>V>rjL=fH|JzF?=se+CI}Q_BQ%M6kEC{; z?|2_;*nFYBoV*6|-)+13nC%T=@4u56ig+9B4I)NGEm7+j9Y8U3_I;Y!W11W3)H;Eh ze?L$*0g9J=0nTNaXODHSk$A4m#0K@oG|a9A~AVRhYU?1U4_Z`b>73W;UHpIa7N zotcKXGN+}a_+b6~+e8PJu)GpTfFKdHgq*5LkrdUL0ZaJ0cGZ%RQz;RvOj=r!Ra#b5 zCM)EYRpy?YmN4o0$l;^dpawg z;0sT1XT0nQ7iMd;)65?Ek=gP4*+;WQ_obIic%N(ETHRdT`fBs5Km2khzblowYlWG8 zN88rb&8u6Jo0HoYDvpmzj*s?P*Op_`QS2Cb$zIv_^;CT4U--`Nte1U58;&aLt+4(Q z>)#&T9VrrOu*M>1SCR1@nURgtPfomKukHJ~pWgrG{?3K6?-MxZ@BzyqSc_CTxs<5m zDw!jK?plgZ0|Dqx`5}$sC~};K@Iiw>rK6@X4Xq?P9*i<1oTBFO8H5NGfTWMnXHm#9 z_l62``y}oUJG9zhY8E{-De0Q$%N%qg=i1pF6dR)eNoKvlAPm( zOh#T+gNckNNLtW@Co*zE$S9NHH+epRa|#Dt0aYE&C#J`vRd08d^Wq*@`;o{7J&XXM zq*4zw-6VpAY&NqNGGX%0;6BoILZ^_+2?XlK*qh4nIoJph4)QYv^k2qg?x@+3xASTI z>-e^`H~1u8>>Me1t`ugg47Yu=V08C)U`yBxbD`HN>iv3cf*^^6w@jx~iz6CitO&ILpsK8x7Da}n{ z@+W9zw@0*Bt|7+W@_7Aq1cO@1P%Tn^Wl_Y>DAk&l5}ABb1gwEqH6`OU)gmw66BD_R zS#49q3{ZSBx0V$Z)tZnq`4vDt0Iv+77$$C3+m_NfK8FQKS(5Qe$gG8*%7O+S_!UjC zPC1)a$ynt8>6!~-QqeMy{J)+yTys;)6+8^uZo;RmKvzHzeQr;M>nm}6yKIr`D{_Ms zZmh(ORk%+}+^1#kMq#GPwbwcPd-39hNsaA#h5M|;eOBS-O59wTy8|%h{TTp_ccgH; z>I+tUmrK6Od!DjyxbWqH!(U|lKMn8(=qy1pzB|B4z(y(Za}ph+A|x$NG*SUTB9PlW z(OT6VjYKfLMVdKkfkgNaiOhT>;N!!ML@)y=nj?-Aror^s`)rwqqFZl~MrC8HAQVI~ z3&?0uy%>K3|3bj^M1!irBw6B%!vvJsIn|uS>4X@f@FifxACrz0J@_K&2xx|AeT)1@ z$gVO;EN5{)+0{;j2}SN150H*vI#icN@~NFEF~=`Kd6~x|FF`sgyqwQrO_)`WYbvf% zYxpubJxIDCBEk`GCV)b)ghVkkJ&^77iZ#x!VW`Z|ui;bv3S9vmu=XwMrghu8VJ)(O z!c>*DZ(QAU6s8V1_twMBhdU289u~RF6>hY|jaInpCGL8en<84yY{8uLx<0=R-Z1_*u1N1t}>g`c;zpCy(=x z+Vz?|oF%ZQ=%tTU5rst=OPG|%s;j}X0yRuV_X-IjOd?Htx$r2VNU@?lRT==O=3G9T z5mif6#A#8{E|geByv6f%>;Yua@Dq=dv*dNdr%6X%Pu(Z%1Zd4?#7PWKKOzsR@-OIW zCW@kdK(^P&`x>=&y$+neFwm>texCvvgBkPlldO zd_8f5fUI5VGUhb|BSO}Oy;Scu{YU3_&Kd%8*Yo_;vr|Weto8R&eqBlp z0lD*w-Qe^7XZ?Sp|6%*Pt$1;&boRy(*{Dq*#<{UxHub!+c^>x`ZoJ}pwu6s7%Q6rR~1uf1Nc|5NO^mT}zDrBwo@6(&Rx6b{f-u9PKGBrGi(?<8?#@0!`Q zM5-!rZ;^6n!YaZ&wVX%~&;t_UhB$C0#h^5UP%Cjjy%}0gT$tG;1qoJ~Z{C~t`OWv< z8~2MpWz;9Jm<;Gw{OgP6&B(U;-02Mnzz)!X4rc&{!Omfx?%a%US;S%q)cIM(|CY~G zb^anHvkyypR2S-SHgV|x8!vFWm+oZk@z-Fa5eYJ>^|&ri&I4eM0Z@;W!NnsrI8m3&pq_XpI$4iWKl#j0)m7@J zj{Po23rpk75?q3s@|b0*`M<$a`JjWSj878^)3H%<*W5LOBgncw%N1|Lxb;WSrY1)wq?5bEQ?7lG8Y_d zV~Kg{@dFrdI~HmMdN6wf!R+ukX0bsB!@{g%MD)6y79t@X;U;o}tJ#IN*+z!3ekeCg zpH?tw5~o%NqYic&$aRs0$62-s25AON@8Q!3Pf-co7MjM>^o;!{-0vt1c?jXJApJAQ z{sOc|YI0vK{-757*9Pi~z3A^k0-osO+t+Vh{}WKNI;>>jiLLXWOl?mM0X6Sj`s~W5 zSDrF+IG%uNpS!KxQihbP?xyY)?iQXhb6D}eQO``h0fC@wTpRGYgGg#~w0G$sp6i!4 m*Lv?9jGVf&JQ$hiT|J0qx12%r^o_TBZ{GND7y&{)DB^Et%Q6H2 diff --git a/src/diamonds/__pycache__/model.cpython-313.pyc b/src/diamonds/__pycache__/model.cpython-313.pyc index 25862907106a1b597dec3b51556e805dc4933758..52fef6d55a970196498ee25ea0c48fb493fad30a 100644 GIT binary patch delta 1857 zcmah}&2JM&6rcU@#@^VQ#7V$T9A`t)#2bhyszC~c&P zr-iDDIRU4F79PmEvBO$0LsDLSyP%xaB{1I=#kqx5Z(t~z3FJWFF_M* zf|lDI>xsAIJ?YNm#H$;T6*zPzr~a#lt@k>vv0Ok3JxWnwN{}d{Q=KbfwTSf$eixKSpc`L+0G|A)EwaY9-o03Pzt$eF`VOwdexCaM*hKZv zWYs&h$*MZ7XEp(#le{U@iygT{uv&U+!?Nrr2TK6zMev|Py;AYg` zzs5H$-Hud!vC83<1J%Lts`m`UYUj$6buaRVt855MaDWVh)iGLy+A^6VZ!@o<=frn0BL);P6!JwIBHNSkVfilX#+1 z$ciKnMa{GxG!8AfT2mKI0^(D1&L|!gi`n=o#Z<{B?cdd!J74UUUagh(K)yKyYNXcor7)+gMd`&K%T}MXRn{F zHutWweQT`m#`yK|o4HlCd!6N7!{92rf1MR>mTrSOy4KiSp1_i|>rZc% zO^v2<)}-&^{%Nnn>@$9JQOTDeNktRLajDb`&caj;Q#91qNLIJ;gl7WyKbnbchvHq_ z8yM!3s#(GXgCBAmpVczvjA7yf1LAyMSIpVn$5~KKtYr*wUdJy^9_OuP--pz3>$xw| zJPO3&F(OVA@qrcN2m9S`xpRkYu9INTLN_poGOEX{&-o*PjXmK?vL=j_PjBpvTEFt$ z!czu?2I?I0x0a`{^yn}C0yRqBNMi9g3^rZN+MIhue1YiQ7sfKoF)6YJ`Ad+8m>k3L zal{Slmj7*zd`U^Ne(~3rTC$q5pck@69IH7E?tj(E7@I3X?kff+W!6cn5-#BpvS0v& zNg1};JaHhE#>pWlR=^@5^-r!^7DvGSrV*iqI2D jv`{Vem`Jr&&ad>YlvW07L&vuetm|Wx^+4!g$>skAPBYaz delta 1187 zcmZ8gTW=dh6rT0&&U$@WU*e=*J5HQB@g*XGRBlC@Hr&!gfhL74MkzH!mc2;~wv*1T zxjdj42?-u}pqi@c8>kOe00|jIJn_I^u+=`SmPR0c!G=WQ0UkKB5s}JB^PQP`eXkcCC)u_C-?OpQMF(>p($mqC}^PsdQTupEnFThCqy7? zk+YRj=8IU1x{Q=IkU(SvvPR2^a=PeY+@eQ|xzRCgu&k~vu*;qvz*pB6pYjd3JGgqt zO ~6wV!d#;M%F_nvJJ7o{=r-D^1@gljmp>SsZc0V-pBznFZ>qjpgMPvnc7M&sblepyb!T~(Y3oibWNNf<|k06oB2wcgxqn>r!G5F;r7 z8ynS1LnriaJbYf#Th*PKPHbG?YV8ocz}d=nrB!R_8|~Knt(^~B^s+RC3oLn(Hl^9U zEIUG}61`&T8@oi`B|BB}JUFLe8hZesL;%HxEjfDk)%}@%Y^vv-w&cj&`9}kpo_E|4 z`4m1zd`#+GKO?T}ztE4(^}JVD)=D?tk6rG0=l(|>%v$oi@>QVc%~|rP1xAh?HYjyg z93Kj(Jt0o=P(+o<`QH#=;mVt*zXX$+_2@;KY(ZWef3Y=RyQ`j4C} zx~=+6QmMB#TrZi2v?Z7ZdmkNS3G(O5pDur~^;j6S{Nc`ZlBc(QD)&2FlchiUZhA{X zNi5-#L>2$r;ub0ht8_DPV`>i4ZM?o=>V|3KkIyXVStBn(ki5j;Wd^U%KLV54Q`z+o zDvdT1{sp|%LgZX*F>LjZSmH`Z=VLF{AtQa@Pg$;T&^c-fQ z7bd6?a`x~pyr7Cf*1%=+hDiwfQ*5D8hc$aDu8y`)t5;21+-&SrOu|~R<%Nn_StOOF zPBcbiWqpg>@9ExYd#^y_?S?*2Y7k=2-M9zf@Epe-qU<4>I7CxaiVTkYhMJF1^H((B z;1oAMKNLwAQB3RNik&UZp)VLZu6$aAc^5< z@BkbL96WfeCq4KNc=amLWWbYNyfvxD1TVhX{s6hi!MEKvZ@!s%efzy{w-O2k37Y)- zjd?{TdJW7G80;6Nfs0Tb4E3-7=ne|>(65jJ9 ztAJ0;624iAh~Gv087UI@F49j#Bp$k>F=K=kOiL>`fI#rU!@DEnbCbi<_qoS%bR)+V zTeFN5R@g8vMilSL2XtE`*;tr5x~qmxc^b=&ASp7qHY2s*vkl0DwUf4-3^dl{L<5(J zO_MHPVs)yyzUOf4C68!53o=2)bvVz^3*-{%uWi>QLejEI!bHU@LvPYBNlOvsX*{7V z8LFlhKr?MaS6v3wf}`ptTU0e$SHUP0!B))zQ}bG3A$p)h^NTqyKbfD1__*vat_Ykf zS;w?N^pPu0-mtkhZ>AP=23Pc=m5(SOXaT_k54!&{=N^;NOq@~C_)u)Yv5Z(Ym0HkX z-igOj*pHZQYL;W`^^wIGqz)%wWK33odJ&==+Y~aIcShtE{Au)`tC0k&t5|k&cK&`b#A8zeF-457w$=@^O*$krRoe zf85b@6iFV8CDSRg+_EZ|uB#;tj^*kl3VvjR%OIoyLcAb|10h~l84wat3p%dkFlU6i zf`C&3ZbQe!TZU4A(_&9h?5Xwh90KAXyM^w={cJt6zOuHm6Myln-cIajt(|8Z?TiH6 zn%s(cGegm8U`OZiO97%D-dd9&i{>@ZELK%HMcKJB15w*+QbA9uh5K)y2#Yym2zn3` w^s{T|%2bl1Jrdd@fiL7D{>olO>e;Z$1c%bV4>6Qm1e9>0oyR`~1l@S{4rIzI$ zQ>){(W9kN`h1SAHCb#E!=y+xr02+#mAK#yQxYn3kcwj6yK8v$nVA*a=+ju%wzz#d$ zw`6f=IA5kHKU8t>=%TX=LuO6`^hlmv;88uCC^9$yDhDVdy>(VhE`v0 z%8g;_hTA9`BmY{Ys*%ATy(2TSq78RHm1j~<8EMK>q@3NmX_${~X0i}W$G0t(M90E_ zSq|S}rf;!9h|CE&6ERoftQ)jU_wQ2E=bd&tfbjGf*qaUyVRx1-V`6h{6Kp@^v1)&b z=Cxp_tN@mZ#21!=@PXHMZ4dWtYYrd)5IKpJ!5Pf*j^zMQw3RcUq5u(Ntc50Q+Toh; zgo_i5vG{IvEAZ^V_m8rQoTz{ zhqUy3`Q`mcXm^gO`qlU^wDd~TBdYiDM$$?PEOa8m6G8NU!0D}^LQYYUno>g~`;9S^ zuCJxiDk6@j_!ya{^ah5f@SI_Y;LyEm53ykooHp2xouI?rT_(~vBxnNyFJY(xqxcjQ zaN5%sMenc;$F-Rsglr?|_|_~-v4D5PhXV`}Vt9OR9zR7`=Ea8tOhj9h<%9;ffI1gM zGX@t?#Cg%hX(cbCK~$43N4U qeXmDQe1GfZ#TT=QdNB2;u=Mm1X=2}aHvP@#J%Z}<#lM6|-uVZ8cTRBt diff --git a/src/diamonds/data.py b/src/diamonds/data.py index c451186..4912834 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -78,8 +78,10 @@ def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: pd.DataFrame The preprocessed diamonds dataset """ - preprocessor = create_preproc() - df_preprocessed = preprocessor.transform(df) + num_cols = df.select_dtypes(include="number").columns.tolist() + cat_cols = df.select_dtypes(include=["category", "object"]).columns.tolist() + preprocessor = create_preproc(num_cols, cat_cols) + df_preprocessed = preprocessor.fit_transform(df) return df_preprocessed @@ -117,5 +119,4 @@ def create_X_y(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series]: if __name__ == "__main__": df = load_data() df_clean = clean_data(df) - df_preprocessed = preprocess_data(df_clean) - X, y = create_X_y(df_preprocessed) + X, y = create_X_y(df_clean) diff --git a/src/diamonds/model.py b/src/diamonds/model.py index c2bb337..94c9b54 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -14,7 +14,7 @@ r2_score, mean_absolute_percentage_error, ) -from diamonds.model import save_model +from diamonds.registry import save_model import pandas as pd import loguru @@ -90,10 +90,11 @@ def train_model(model, X_train, y_train): y_train : pd.Series The target variable """ - loguru.info("Training model...") + logger.info("Training model...") model.fit(X_train, y_train) - loguru.info("Model trained. Saving...") + logger.info("Model trained. Saving...") save_model(model, "model") + return model def evaluate_model(model, X_test, y_test) -> dict[str, float]: From e6111f1e4ee042cbde344a688d1a8d2f70c34ae9 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Wed, 11 Mar 2026 01:51:29 +0000 Subject: [PATCH 13/20] Clean repo: ignore pycache and mlflow artifacts and add mlflow tracking experiment function --- .gitignore | 7 +- Makefile | 17 +- data/preprocessed/.gitkeep | 0 data/raw/.gitkeep | 0 models/.gitkeep | 0 notebooks/Experiement-Tracking.ipynb | 1208 +++++++++++++ poetry.lock | 1550 +++++++++++++++-- pyproject.toml | 3 +- .../__pycache__/__init__.cpython-311.pyc | Bin 260 -> 0 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 248 -> 0 bytes src/diamonds/__pycache__/data.cpython-311.pyc | Bin 3696 -> 0 bytes src/diamonds/__pycache__/data.cpython-313.pyc | Bin 2645 -> 0 bytes .../__pycache__/model.cpython-311.pyc | Bin 4528 -> 0 bytes .../__pycache__/model.cpython-313.pyc | Bin 3771 -> 0 bytes .../__pycache__/params.cpython-311.pyc | Bin 360 -> 0 bytes .../__pycache__/params.cpython-313.pyc | Bin 348 -> 0 bytes .../__pycache__/registry.cpython-311.pyc | Bin 1669 -> 0 bytes .../__pycache__/registry.cpython-313.pyc | Bin 1456 -> 0 bytes .../__pycache__/train.cpython-313.pyc | Bin 1974 -> 0 bytes src/diamonds/data.py | 64 +- src/diamonds/model.py | 81 +- src/diamonds/train.py | 88 +- 22 files changed, 2848 insertions(+), 170 deletions(-) delete mode 100644 data/preprocessed/.gitkeep delete mode 100644 data/raw/.gitkeep delete mode 100644 models/.gitkeep create mode 100644 notebooks/Experiement-Tracking.ipynb delete mode 100644 src/diamonds/__pycache__/__init__.cpython-311.pyc delete mode 100644 src/diamonds/__pycache__/__init__.cpython-313.pyc delete mode 100644 src/diamonds/__pycache__/data.cpython-311.pyc delete mode 100644 src/diamonds/__pycache__/data.cpython-313.pyc delete mode 100644 src/diamonds/__pycache__/model.cpython-311.pyc delete mode 100644 src/diamonds/__pycache__/model.cpython-313.pyc delete mode 100644 src/diamonds/__pycache__/params.cpython-311.pyc delete mode 100644 src/diamonds/__pycache__/params.cpython-313.pyc delete mode 100644 src/diamonds/__pycache__/registry.cpython-311.pyc delete mode 100644 src/diamonds/__pycache__/registry.cpython-313.pyc delete mode 100644 src/diamonds/__pycache__/train.cpython-313.pyc diff --git a/.gitignore b/.gitignore index 545c2b6..84c65a6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ .venv/ .python-version .ipynb_checkpoints/ -/__pycache__/ +__pycache__/ # Data data/ @@ -14,4 +14,7 @@ models/ # Env .env -.envrc \ No newline at end of file +.envrc + +.mlartifacts/ +.mlflow.db \ No newline at end of file diff --git a/Makefile b/Makefile index 6b98525..6c22cf1 100644 --- a/Makefile +++ b/Makefile @@ -12,4 +12,19 @@ format: @echo "checking format" poetry run ruff format . -lint-all: lint lint-fix format \ No newline at end of file +lint-all: lint lint-fix format + +.PHONY: start-mlflow stop-mlflow +MLFLOW_PORT=5000 +MLFLOW_PID_FILE=.mlflow.pid + +start-mlflow: + mlflow ui --port $(MLFLOW_PORT) & echo $$! > $(MLFLOW_PID_FILE) + +stop-mlflow: + @if [ -f $(MLFLOW_PID_FILE) ]; then \ + kill `cat $(MLFLOW_PID_FILE)` && rm $(MLFLOW_PID_FILE); \ + echo "MLflow server stopped"; \ + else \ + echo "No MLflow server running"; \ + fi diff --git a/data/preprocessed/.gitkeep b/data/preprocessed/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/data/raw/.gitkeep b/data/raw/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/models/.gitkeep b/models/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/notebooks/Experiement-Tracking.ipynb b/notebooks/Experiement-Tracking.ipynb new file mode 100644 index 0000000..aa3285b --- /dev/null +++ b/notebooks/Experiement-Tracking.ipynb @@ -0,0 +1,1208 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "id": "e11c05bf", + "metadata": {}, + "outputs": [], + "source": [ + "import mlflow \n", + "\n", + "import sklearn\n", + "from sklearn.datasets import load_iris\n", + "from sklearn.ensemble import RandomForestClassifier\n", + "from sklearn.metrics import accuracy_score\n", + "from sklearn.model_selection import train_test_split" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7aecb5ea", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026/03/10 14:12:18 INFO mlflow.tracking.fluent: Experiment with name 'Iris_Experiment' does not exist. Creating a new experiment.\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 1. Set the tracking URI to the MLflow server\n", + "mlflow.set_tracking_uri(\"http://localhost:5000\")\n", + "# 2. Set the Experiment name\n", + "mlflow.set_experiment(\"Iris_Experiment\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "6d746100", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test accuracy: 0.9333\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026/03/10 14:15:44 WARNING mlflow.sklearn: Saving scikit-learn models in the pickle or cloudpickle format requires exercising caution because these formats rely on Python's object serialization mechanism, which can execute arbitrary code during deserialization. The recommended safe alternative is the 'skops' format. For more information, see: https://scikit-learn.org/stable/model_persistence.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🏃 View run omniscient-foal-439 at: http://localhost:5000/#/experiments/1/runs/8fc827ff373b47cf95bf4f1a6d4a0c5d\n", + "🧪 View experiment at: http://localhost:5000/#/experiments/1\n" + ] + } + ], + "source": [ + "import random\n", + "from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score\n", + "\n", + "# Load data\n", + "iris = load_iris()\n", + "X, y = iris.data, iris.target\n", + "\n", + "# Split data\n", + "X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.2, random_state=42, stratify=y\n", + ")\n", + "n_estimators = random.randint(50, 200) # Randomly choose n_estimators for demonstration\n", + "depth = random.randint(5, 20) # Randomly choose max_depth for demonstration\n", + "# Train classifier\n", + "clf = RandomForestClassifier(n_estimators=n_estimators\n", + " , max_depth=depth)\n", + "clf.fit(X_train, y_train)\n", + "\n", + "# Evaluate\n", + "y_pred = clf.predict(X_test)\n", + "acc = accuracy_score(y_test, y_pred)\n", + "print(f\"Test accuracy: {acc:.4f}\")\n", + "with mlflow.start_run() as run:\n", + " mlflow.log_param(\"n_estimators\", n_estimators)\n", + " mlflow.log_param(\"max_depth\", depth)\n", + " mlflow.log_metric(\"accuracy\", acc)\n", + " mlflow.log_metric(\"recall\", recall_score(y_test, y_pred, average=\"weighted\"))\n", + " mlflow.log_metric(\"precision\", precision_score(y_test, y_pred, average=\"weighted\"))\n", + " mlflow.log_metric(\"f1_score\", f1_score(y_test, y_pred, average=\"weighted\"))\n", + " mlflow.sklearn.log_model(clf, name=\"random_forest_model\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "108fa9a0", + "metadata": {}, + "source": [ + "## Autolog" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70d96a88", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026/03/10 14:20:59 INFO mlflow.tracking.fluent: Autologging successfully enabled for sklearn.\n", + "2026/03/10 14:21:00 WARNING mlflow.sklearn: Saving scikit-learn models in the pickle or cloudpickle format requires exercising caution because these formats rely on Python's object serialization mechanism, which can execute arbitrary code during deserialization. The recommended safe alternative is the 'skops' format. For more information, see: https://scikit-learn.org/stable/model_persistence.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test accuracy: 0.9333\n", + "🏃 View run monumental-cat-491 at: http://localhost:5000/#/experiments/1/runs/bc2d0b0d96ad4362ad2e7e10abdb41f3\n", + "🧪 View experiment at: http://localhost:5000/#/experiments/1\n" + ] + } + ], + "source": [ + "with mlflow.start_run():\n", + " mlflow.autolog(log_input_examples=True)\n", + " # Load data\n", + " iris = load_iris()\n", + " X, y = iris.data, iris.target\n", + "\n", + " # Split data\n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.2, random_state=42, stratify=y\n", + " )\n", + " n_estimators = random.randint(50, 200) # Randomly choose n_estimators for demonstration\n", + " depth = random.randint(5, 20) # Randomly choose max_depth for demonstration\n", + " # Train classifier\n", + " clf = RandomForestClassifier(n_estimators=n_estimators\n", + " , max_depth=depth)\n", + " clf.fit(X_train, y_train) \n", + "\n", + " # Evaluate\n", + " y_pred = clf.predict(X_test)\n", + " acc = accuracy_score(y_test, y_pred)\n", + " print(f\"Test accuracy: {acc:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "f0ba4fd5", + "metadata": {}, + "source": [ + "## Loading a model from MLflow" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "6d58a77e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
RandomForestClassifier(max_depth=18, n_estimators=98)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], + "text/plain": [ + "RandomForestClassifier(max_depth=18, n_estimators=98)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client = mlflow.MlflowClient()\n", + "model_name = \"iris\"\n", + "model_version_alias = \"prod\"\n", + "# Get the model version using a model URI\n", + "model_uri = f\"models:/{model_name}@{model_version_alias}\"\n", + "model = mlflow.sklearn.load_model(model_uri)\n", + "\n", + "(model)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "diamond_project_env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/poetry.lock b/poetry.lock index e765327..a4621ac 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,49 @@ # This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. +[[package]] +name = "alembic" +version = "1.18.4" +description = "A database migration tool for SQLAlchemy." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "alembic-1.18.4-py3-none-any.whl", hash = "sha256:a5ed4adcf6d8a4cb575f3d759f071b03cd6e5c7618eb796cb52497be25bfe19a"}, + {file = "alembic-1.18.4.tar.gz", hash = "sha256:cb6e1fd84b6174ab8dbb2329f86d631ba9559dd78df550b57804d607672cedbc"}, +] + +[package.dependencies] +Mako = "*" +SQLAlchemy = ">=1.4.23" +typing-extensions = ">=4.12" + +[package.extras] +tz = ["tzdata"] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +description = "Document parameters, class attributes, return types, and variables inline, with Annotated." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320"}, + {file = "annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4"}, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + [[package]] name = "anyio" version = "4.12.1" @@ -206,6 +250,30 @@ webencodings = "*" [package.extras] css = ["tinycss2 (>=1.1.0,<1.5)"] +[[package]] +name = "blinker" +version = "1.9.0" +description = "Fast, simple object-to-object and broadcast signaling" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"}, + {file = "blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf"}, +] + +[[package]] +name = "cachetools" +version = "7.0.5" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "cachetools-7.0.5-py3-none-any.whl", hash = "sha256:46bc8ebefbe485407621d0a4264b23c080cedd913921bad7ac3ed2f26c183114"}, + {file = "cachetools-7.0.5.tar.gz", hash = "sha256:0cd042c24377200c1dcd225f8b7b12b0ca53cc2c961b43757e774ebe190fd990"}, +] + [[package]] name = "certifi" version = "2026.2.25" @@ -438,6 +506,33 @@ files = [ {file = "charset_normalizer-3.4.5.tar.gz", hash = "sha256:95adae7b6c42a6c5b5b559b1a99149f090a57128155daeea91732c8d970d8644"}, ] +[[package]] +name = "click" +version = "8.3.1" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, + {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "cloudpickle" +version = "3.1.2" +description = "Pickler class to extend the standard pickle.Pickler functionality" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a"}, + {file = "cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414"}, +] + [[package]] name = "colorama" version = "0.4.6" @@ -445,11 +540,11 @@ description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["main", "dev"] -markers = "sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "sys_platform == \"win32\"", dev = "sys_platform == \"win32\" or platform_system == \"Windows\""} [[package]] name = "comm" @@ -472,7 +567,7 @@ version = "1.3.3" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, {file = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"}, @@ -558,13 +653,85 @@ mypy = ["bokeh", "contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.17.0)", " test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] +[[package]] +name = "cryptography" +version = "46.0.5" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = "!=3.9.0,!=3.9.1,>=3.8" +groups = ["dev"] +files = [ + {file = "cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731"}, + {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82"}, + {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1"}, + {file = "cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48"}, + {file = "cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4"}, + {file = "cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663"}, + {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826"}, + {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d"}, + {file = "cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a"}, + {file = "cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4"}, + {file = "cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c"}, + {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4"}, + {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9"}, + {file = "cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72"}, + {file = "cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7"}, + {file = "cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d"}, +] + +[package.dependencies] +cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] +docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] +nox = ["nox[uv] (>=2024.4.15)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.14)", "ruff (>=0.11.11)"] +sdist = ["build (>=1.0.0)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi (>=2024)", "cryptography-vectors (==46.0.5)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test-randomorder = ["pytest-randomly"] + [[package]] name = "cycler" version = "0.12.1" description = "Composable style cycles" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, @@ -574,6 +741,28 @@ files = [ docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] tests = ["pytest", "pytest-cov", "pytest-xdist"] +[[package]] +name = "databricks-sdk" +version = "0.97.0" +description = "Databricks SDK for Python (Beta)" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "databricks_sdk-0.97.0-py3-none-any.whl", hash = "sha256:fbb758e3374ce5b7f697182781c0b8904e341eac4a3722a07138cacde09d4e7b"}, + {file = "databricks_sdk-0.97.0.tar.gz", hash = "sha256:e3d0e0d283963f72fc2b995dd97a6c0e988062214cd28aca4e1a5ff71c264dcb"}, +] + +[package.dependencies] +google-auth = ">=2.0,<3.0" +protobuf = ">=4.25.8,<5.26.dev0 || >5.29.0,<5.29.1 || >5.29.1,<5.29.2 || >5.29.2,<5.29.3 || >5.29.3,<5.29.4 || >5.29.4,<6.30.0 || >6.30.0,<6.30.1 || >6.30.1,<6.31.0 || >6.31.0,<7.0" +requests = ">=2.28.1,<3" + +[package.extras] +dev = ["autoflake (==2.3.1)", "black (==24.8.0)", "build", "databricks-connect", "httpx", "ipython", "ipywidgets", "isort (==5.13.2)", "langchain-openai ; python_version > \"3.7\"", "openai", "pycodestyle", "pyfakefs", "pytest", "pytest-cov", "pytest-mock", "pytest-rerunfailures", "pytest-xdist (>=3.6.1,<4.0)", "requests-mock", "wheel"] +notebook = ["ipython (>=8,<10)", "ipywidgets (>=8,<9)"] +openai = ["httpx", "langchain-openai ; python_version > \"3.7\"", "openai"] + [[package]] name = "debugpy" version = "1.8.20" @@ -638,6 +827,29 @@ files = [ {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, ] +[[package]] +name = "docker" +version = "7.1.0" +description = "A Python library for the Docker Engine API." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"}, + {file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"}, +] + +[package.dependencies] +pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""} +requests = ">=2.26.0" +urllib3 = ">=1.26.0" + +[package.extras] +dev = ["coverage (==7.2.7)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.1.0)", "ruff (==0.1.8)"] +docs = ["myst-parser (==0.18.0)", "sphinx (==5.1.1)"] +ssh = ["paramiko (>=2.4.3)"] +websockets = ["websocket-client (>=1.3.0)"] + [[package]] name = "executing" version = "2.2.1" @@ -653,6 +865,30 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich ; python_version >= \"3.11\""] +[[package]] +name = "fastapi" +version = "0.135.1" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "fastapi-0.135.1-py3-none-any.whl", hash = "sha256:46e2fc5745924b7c840f71ddd277382af29ce1cdb7d5eab5bf697e3fb9999c9e"}, + {file = "fastapi-0.135.1.tar.gz", hash = "sha256:d04115b508d936d254cea545b7312ecaa58a7b3a0f84952535b4c9afae7668cd"}, +] + +[package.dependencies] +annotated-doc = ">=0.0.2" +pydantic = ">=2.7.0" +starlette = ">=0.46.0" +typing-extensions = ">=4.8.0" +typing-inspection = ">=0.4.2" + +[package.extras] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] +standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] + [[package]] name = "fastjsonschema" version = "2.21.2" @@ -668,13 +904,53 @@ files = [ [package.extras] devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] +[[package]] +name = "flask" +version = "3.1.3" +description = "A simple framework for building complex web applications." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c"}, + {file = "flask-3.1.3.tar.gz", hash = "sha256:0ef0e52b8a9cd932855379197dd8f94047b359ca0a78695144304cb45f87c9eb"}, +] + +[package.dependencies] +blinker = ">=1.9.0" +click = ">=8.1.3" +itsdangerous = ">=2.2.0" +jinja2 = ">=3.1.2" +markupsafe = ">=2.1.1" +werkzeug = ">=3.1.0" + +[package.extras] +async = ["asgiref (>=3.2)"] +dotenv = ["python-dotenv"] + +[[package]] +name = "flask-cors" +version = "6.0.2" +description = "A Flask extension simplifying CORS support" +optional = false +python-versions = "<4.0,>=3.9" +groups = ["dev"] +files = [ + {file = "flask_cors-6.0.2-py3-none-any.whl", hash = "sha256:e57544d415dfd7da89a9564e1e3a9e515042df76e12130641ca6f3f2f03b699a"}, + {file = "flask_cors-6.0.2.tar.gz", hash = "sha256:6e118f3698249ae33e429760db98ce032a8bf9913638d085ca0f4c5534ad2423"}, +] + +[package.dependencies] +flask = ">=0.9" +Werkzeug = ">=0.7" + [[package]] name = "fonttools" version = "4.61.1" description = "Tools to manipulate font files" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c7db70d57e5e1089a274cbb2b1fd635c9a24de809a231b154965d415d6c6d24"}, {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5fe9fd43882620017add5eabb781ebfbc6998ee49b35bd7f8f79af1f9f99a958"}, @@ -753,6 +1029,209 @@ files = [ {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, ] +[[package]] +name = "gitdb" +version = "4.0.12" +description = "Git Object Database" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, + {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.46" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "gitpython-3.1.46-py3-none-any.whl", hash = "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058"}, + {file = "gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] +test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy (==1.18.2) ; python_version >= \"3.9\"", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] + +[[package]] +name = "google-auth" +version = "2.49.0" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "google_auth-2.49.0-py3-none-any.whl", hash = "sha256:f893ef7307f19cf53700b7e2f61b5a6affe3aa0edf9943b13788920ab92d8d87"}, + {file = "google_auth-2.49.0.tar.gz", hash = "sha256:9cc2d9259d3700d7a257681f81052db6737495a1a46b610597f4b8bafe5286ae"}, +] + +[package.dependencies] +cryptography = ">=38.0.3" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0)", "requests (>=2.20.0,<3.0.0)"] +cryptography = ["cryptography (>=38.0.3)"] +enterprise-cert = ["pyopenssl"] +pyjwt = ["pyjwt (>=2.0)"] +pyopenssl = ["pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0)"] +testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.6.2,<4.0.0)", "aioresponses", "flask", "freezegun", "grpcio", "oauth2client", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"] +urllib3 = ["packaging", "urllib3"] + +[[package]] +name = "graphene" +version = "3.4.3" +description = "GraphQL Framework for Python" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "graphene-3.4.3-py2.py3-none-any.whl", hash = "sha256:820db6289754c181007a150db1f7fff544b94142b556d12e3ebc777a7bf36c71"}, + {file = "graphene-3.4.3.tar.gz", hash = "sha256:2a3786948ce75fe7e078443d37f609cbe5bb36ad8d6b828740ad3b95ed1a0aaa"}, +] + +[package.dependencies] +graphql-core = ">=3.1,<3.3" +graphql-relay = ">=3.1,<3.3" +python-dateutil = ">=2.7.0,<3" +typing-extensions = ">=4.7.1,<5" + +[package.extras] +dev = ["coveralls (>=3.3,<5)", "mypy (>=1.10,<2)", "pytest (>=8,<9)", "pytest-asyncio (>=0.16,<2)", "pytest-benchmark (>=4,<5)", "pytest-cov (>=5,<6)", "pytest-mock (>=3,<4)", "ruff (==0.5.0)", "types-python-dateutil (>=2.8.1,<3)"] +test = ["coveralls (>=3.3,<5)", "pytest (>=8,<9)", "pytest-asyncio (>=0.16,<2)", "pytest-benchmark (>=4,<5)", "pytest-cov (>=5,<6)", "pytest-mock (>=3,<4)"] + +[[package]] +name = "graphql-core" +version = "3.2.8" +description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." +optional = false +python-versions = "<4,>=3.7" +groups = ["dev"] +files = [ + {file = "graphql_core-3.2.8-py3-none-any.whl", hash = "sha256:cbee07bee1b3ed5e531723685369039f32ff815ef60166686e0162f540f1520c"}, + {file = "graphql_core-3.2.8.tar.gz", hash = "sha256:015457da5d996c924ddf57a43f4e959b0b94fb695b85ed4c29446e508ed65cf3"}, +] + +[[package]] +name = "graphql-relay" +version = "3.2.0" +description = "Relay library for graphql-core" +optional = false +python-versions = ">=3.6,<4" +groups = ["dev"] +files = [ + {file = "graphql-relay-3.2.0.tar.gz", hash = "sha256:1ff1c51298356e481a0be009ccdff249832ce53f30559c1338f22a0e0d17250c"}, + {file = "graphql_relay-3.2.0-py3-none-any.whl", hash = "sha256:c9b22bd28b170ba1fe674c74384a8ff30a76c8e26f88ac3aa1584dd3179953e5"}, +] + +[package.dependencies] +graphql-core = ">=3.2,<3.3" + +[[package]] +name = "greenlet" +version = "3.3.2" +description = "Lightweight in-process concurrent programming" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\"" +files = [ + {file = "greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f"}, + {file = "greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef"}, + {file = "greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca"}, + {file = "greenlet-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f"}, + {file = "greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358"}, + {file = "greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99"}, + {file = "greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be"}, + {file = "greenlet-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5"}, + {file = "greenlet-3.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd"}, + {file = "greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070"}, + {file = "greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79"}, + {file = "greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395"}, + {file = "greenlet-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f"}, + {file = "greenlet-3.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643"}, + {file = "greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab"}, + {file = "greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a"}, + {file = "greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b"}, + {file = "greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124"}, + {file = "greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327"}, + {file = "greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506"}, + {file = "greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce"}, + {file = "greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5"}, + {file = "greenlet-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492"}, + {file = "greenlet-3.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71"}, + {file = "greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4"}, + {file = "greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727"}, + {file = "greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e"}, + {file = "greenlet-3.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a"}, + {file = "greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2"}, +] + +[package.extras] +docs = ["Sphinx", "furo"] +test = ["objgraph", "psutil", "setuptools"] + +[[package]] +name = "gunicorn" +version = "25.1.0" +description = "WSGI HTTP Server for UNIX" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "platform_system != \"Windows\"" +files = [ + {file = "gunicorn-25.1.0-py3-none-any.whl", hash = "sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b"}, + {file = "gunicorn-25.1.0.tar.gz", hash = "sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616"}, +] + +[package.dependencies] +packaging = "*" + +[package.extras] +eventlet = ["eventlet (>=0.40.3)"] +gevent = ["gevent (>=24.10.1)"] +http2 = ["h2 (>=4.1.0)"] +setproctitle = ["setproctitle"] +testing = ["coverage", "eventlet (>=0.40.3)", "gevent (>=24.10.1)", "h2 (>=4.1.0)", "httpx[http2]", "pytest", "pytest-asyncio", "pytest-cov", "uvloop (>=0.19.0)"] +tornado = ["tornado (>=6.5.0)"] + [[package]] name = "h11" version = "0.16.0" @@ -812,6 +1291,21 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "huey" +version = "2.6.0" +description = "a little task queue" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "huey-2.6.0-py3-none-any.whl", hash = "sha256:1b9df9d370b49c6d5721ba8a01ac9a787cf86b3bdc584e4679de27b920395c3f"}, + {file = "huey-2.6.0.tar.gz", hash = "sha256:8d11f8688999d65266af1425b831f6e3773e99415027177b8734b0ffd5e251f6"}, +] + +[package.extras] +backends = ["redis (>=3.0.0)"] + [[package]] name = "idna" version = "3.11" @@ -827,6 +1321,30 @@ files = [ [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +[[package]] +name = "importlib-metadata" +version = "8.7.1" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151"}, + {file = "importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb"}, +] + +[package.dependencies] +zipp = ">=3.20" + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +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 (>=3.4)"] +perf = ["ipython"] +test = ["flufl.flake8", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["mypy (<1.19) ; platform_python_implementation == \"PyPy\"", "pytest-mypy (>=1.0.1)"] + [[package]] name = "ipykernel" version = "7.2.0" @@ -868,7 +1386,7 @@ description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.11" groups = ["dev"] -markers = "python_version < \"3.14\"" +markers = "python_version == \"3.11\"" files = [ {file = "ipython-9.10.0-py3-none-any.whl", hash = "sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d"}, {file = "ipython-9.10.0.tar.gz", hash = "sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77"}, @@ -902,7 +1420,7 @@ description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.12" groups = ["dev"] -markers = "python_version >= \"3.14\"" +markers = "python_version >= \"3.12\"" files = [ {file = "ipython-9.11.0-py3-none-any.whl", hash = "sha256:6922d5bcf944c6e525a76a0a304451b60a2b6f875e86656d8bc2dfda5d710e19"}, {file = "ipython-9.11.0.tar.gz", hash = "sha256:2a94bc4406b22ecc7e4cb95b98450f3ea493a76bec8896cda11b78d7752a6667"}, @@ -958,6 +1476,18 @@ files = [ [package.dependencies] arrow = ">=0.15.0" +[[package]] +name = "itsdangerous" +version = "2.2.0" +description = "Safely pass data to untrusted environments and back." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, + {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, +] + [[package]] name = "jedi" version = "0.19.2" @@ -1002,7 +1532,7 @@ version = "1.5.3" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713"}, {file = "joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3"}, @@ -1299,7 +1829,7 @@ version = "1.5.0" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374"}, {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd"}, @@ -1457,6 +1987,26 @@ win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==0.910) ; python_version < \"3.6\"", "mypy (==0.971) ; python_version == \"3.6\"", "mypy (==1.13.0) ; python_version >= \"3.8\"", "mypy (==1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] +[[package]] +name = "mako" +version = "1.3.10" +description = "A super-fast templating language that borrows the best ideas from the existing templating languages." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59"}, + {file = "mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28"}, +] + +[package.dependencies] +MarkupSafe = ">=0.9.2" + +[package.extras] +babel = ["Babel"] +lingua = ["lingua"] +testing = ["pytest"] + [[package]] name = "markupsafe" version = "3.0.3" @@ -1562,7 +2112,7 @@ version = "3.10.8" description = "Python plotting package" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "matplotlib-3.10.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:00270d217d6b20d14b584c521f810d60c5c78406dc289859776550df837dcda7"}, {file = "matplotlib-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b3c1cc42aa184b3f738cfa18c1c1d72fd496d85467a6cf7b807936d39aa656"}, @@ -1666,9 +2216,125 @@ files = [ ] [[package]] -name = "nbclient" -version = "0.10.4" -description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +name = "mlflow" +version = "3.10.1" +description = "MLflow is an open source platform for the complete machine learning lifecycle" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "mlflow-3.10.1-py3-none-any.whl", hash = "sha256:17bfbd76d4071498d6199c3fc53945e5f50997d14e3e2a6bfd4dc3cb8957f209"}, + {file = "mlflow-3.10.1.tar.gz", hash = "sha256:609509ccc15eb9c17861748e537cbffa57d2caf488ff3e30efed62951a6977cf"}, +] + +[package.dependencies] +alembic = "<1.10.0 || >1.10.0,<2" +cryptography = ">=43.0.0,<47" +docker = ">=4.0.0,<8" +Flask = "<4" +Flask-CORS = "<7" +graphene = "<4" +gunicorn = {version = "<26", markers = "platform_system != \"Windows\""} +huey = ">=2.5.4,<3" +matplotlib = "<4" +mlflow-skinny = "3.10.1" +mlflow-tracing = "3.10.1" +numpy = "<3" +pandas = "<3" +pyarrow = ">=4.0.0,<24" +scikit-learn = "<2" +scipy = "<2" +skops = "<1" +sqlalchemy = ">=1.4.0,<3" +waitress = {version = "<4", markers = "platform_system == \"Windows\""} + +[package.extras] +aliyun-oss = ["aliyunstoreplugin"] +auth = ["Flask-WTF (<2)"] +databricks = ["azure-storage-file-datalake (>12)", "boto3 (>1)", "botocore", "databricks-agents (>=1.2.0,<2.0)", "google-cloud-storage (>=1.30.0)"] +db = ["PyMySQL", "psycopg2-binary", "pymssql"] +extras = ["azureml-core (>=1.2.0)", "boto3", "botocore", "google-cloud-storage (>=1.30.0)", "kubernetes", "prometheus-flask-exporter", "pyarrow", "pysftp", "requests-auth-aws-sigv4"] +gateway = ["aiohttp (<4)", "boto3 (>=1.28.56,<2)", "fastapi (<1)", "slowapi (>=0.1.9,<1)", "tiktoken (<1)", "uvicorn[standard] (<1)", "watchfiles (<2)"] +genai = ["aiohttp (<4)", "boto3 (>=1.28.56,<2)", "fastapi (<1)", "gepa (>=0.0.26,<1)", "litellm (>=1.0.0,<2)", "slowapi (>=0.1.9,<1)", "tiktoken (<1)", "uvicorn[standard] (<1)", "watchfiles (<2)"] +jfrog = ["mlflow-jfrog-plugin"] +langchain = ["langchain (>=0.3.19,<=1.2.9)"] +mcp = ["click (!=8.3.0)", "fastmcp (>=2.0.0,<3)"] +mlserver = ["mlserver (>=1.2.0,!=1.3.1,<2.0.0)", "mlserver-mlflow (>=1.2.0,!=1.3.1,<2.0.0)"] +sqlserver = ["mlflow-dbstore"] + +[[package]] +name = "mlflow-skinny" +version = "3.10.1" +description = "MLflow is an open source platform for the complete machine learning lifecycle" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "mlflow_skinny-3.10.1-py3-none-any.whl", hash = "sha256:df1dd507d8ddadf53bfab2423c76cdcafc235cd1a46921a06d1a6b4dd04b023c"}, + {file = "mlflow_skinny-3.10.1.tar.gz", hash = "sha256:3d1c5c30245b6e7065b492b09dd47be7528e0a14c4266b782fe58f9bcd1e0be0"}, +] + +[package.dependencies] +cachetools = ">=5.0.0,<8" +click = ">=7.0,<9" +cloudpickle = "<4" +databricks-sdk = ">=0.20.0,<1" +fastapi = "<1" +gitpython = ">=3.1.9,<4" +importlib_metadata = ">=3.7.0,<4.7.0 || >4.7.0,<9" +opentelemetry-api = ">=1.9.0,<3" +opentelemetry-proto = ">=1.9.0,<3" +opentelemetry-sdk = ">=1.9.0,<3" +packaging = "<27" +protobuf = ">=3.12.0,<7" +pydantic = ">=2.0.0,<3" +python-dotenv = ">=0.19.0,<2" +pyyaml = ">=5.1,<7" +requests = ">=2.17.3,<3" +sqlparse = ">=0.4.0,<1" +typing-extensions = ">=4.0.0,<5" +uvicorn = "<1" + +[package.extras] +aliyun-oss = ["aliyunstoreplugin"] +auth = ["Flask-WTF (<2)"] +databricks = ["azure-storage-file-datalake (>12)", "boto3 (>1)", "botocore", "databricks-agents (>=1.2.0,<2.0)", "google-cloud-storage (>=1.30.0)"] +db = ["PyMySQL", "psycopg2-binary", "pymssql"] +extras = ["azureml-core (>=1.2.0)", "boto3", "botocore", "google-cloud-storage (>=1.30.0)", "kubernetes", "prometheus-flask-exporter", "pyarrow", "pysftp", "requests-auth-aws-sigv4"] +gateway = ["aiohttp (<4)", "boto3 (>=1.28.56,<2)", "fastapi (<1)", "slowapi (>=0.1.9,<1)", "tiktoken (<1)", "uvicorn[standard] (<1)", "watchfiles (<2)"] +genai = ["aiohttp (<4)", "boto3 (>=1.28.56,<2)", "fastapi (<1)", "gepa (>=0.0.26,<1)", "litellm (>=1.0.0,<2)", "slowapi (>=0.1.9,<1)", "tiktoken (<1)", "uvicorn[standard] (<1)", "watchfiles (<2)"] +jfrog = ["mlflow-jfrog-plugin"] +langchain = ["langchain (>=0.3.19,<=1.2.9)"] +mcp = ["click (!=8.3.0)", "fastmcp (>=2.0.0,<3)"] +mlserver = ["mlserver (>=1.2.0,!=1.3.1,<2.0.0)", "mlserver-mlflow (>=1.2.0,!=1.3.1,<2.0.0)"] +sqlserver = ["mlflow-dbstore"] + +[[package]] +name = "mlflow-tracing" +version = "3.10.1" +description = "MLflow Tracing SDK is an open-source, lightweight Python package that only includes the minimum set of dependencies and functionality to instrument your code/models/agents with MLflow Tracing." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "mlflow_tracing-3.10.1-py3-none-any.whl", hash = "sha256:649c722cc58d54f1f40559023a6bd6f3f08150c3ce3c3bb27972b3e795890f47"}, + {file = "mlflow_tracing-3.10.1.tar.gz", hash = "sha256:9e54d63cf776d29bb9e2278d35bf27352b93f7b35c8fe8452e9ba5e2a3c5b78f"}, +] + +[package.dependencies] +cachetools = ">=5.0.0,<8" +databricks-sdk = ">=0.20.0,<1" +opentelemetry-api = ">=1.9.0,<3" +opentelemetry-proto = ">=1.9.0,<3" +opentelemetry-sdk = ">=1.9.0,<3" +packaging = "<27" +protobuf = ">=3.12.0,<7" +pydantic = ">=2.0.0,<3" + +[[package]] +name = "nbclient" +version = "0.10.4" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false python-versions = ">=3.10.0" groups = ["dev"] @@ -1807,7 +2473,7 @@ version = "2.4.3" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "numpy-2.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:33b3bf58ee84b172c067f56aeadc7ee9ab6de69c5e800ab5b10295d54c581adb"}, {file = "numpy-2.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ba7b51e71c05aa1f9bc3641463cd82308eab40ce0d5c7e1fd4038cbf9938147"}, @@ -1883,6 +2549,70 @@ files = [ {file = "numpy-2.4.3.tar.gz", hash = "sha256:483a201202b73495f00dbc83796c6ae63137a9bdade074f7648b3e32613412dd"}, ] +[[package]] +name = "opentelemetry-api" +version = "1.40.0" +description = "OpenTelemetry Python API" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "opentelemetry_api-1.40.0-py3-none-any.whl", hash = "sha256:82dd69331ae74b06f6a874704be0cfaa49a1650e1537d4a813b86ecef7d0ecf9"}, + {file = "opentelemetry_api-1.40.0.tar.gz", hash = "sha256:159be641c0b04d11e9ecd576906462773eb97ae1b657730f0ecf64d32071569f"}, +] + +[package.dependencies] +importlib-metadata = ">=6.0,<8.8.0" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-proto" +version = "1.40.0" +description = "OpenTelemetry Python Proto" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "opentelemetry_proto-1.40.0-py3-none-any.whl", hash = "sha256:266c4385d88923a23d63e353e9761af0f47a6ed0d486979777fe4de59dc9b25f"}, + {file = "opentelemetry_proto-1.40.0.tar.gz", hash = "sha256:03f639ca129ba513f5819810f5b1f42bcb371391405d99c168fe6937c62febcd"}, +] + +[package.dependencies] +protobuf = ">=5.0,<7.0" + +[[package]] +name = "opentelemetry-sdk" +version = "1.40.0" +description = "OpenTelemetry Python SDK" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "opentelemetry_sdk-1.40.0-py3-none-any.whl", hash = "sha256:787d2154a71f4b3d81f20524a8ce061b7db667d24e46753f32a7bc48f1c1f3f1"}, + {file = "opentelemetry_sdk-1.40.0.tar.gz", hash = "sha256:18e9f5ec20d859d268c7cb3c5198c8d105d073714db3de50b593b8c1345a48f2"}, +] + +[package.dependencies] +opentelemetry-api = "1.40.0" +opentelemetry-semantic-conventions = "0.61b0" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.61b0" +description = "OpenTelemetry Semantic Conventions" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "opentelemetry_semantic_conventions-0.61b0-py3-none-any.whl", hash = "sha256:fa530a96be229795f8cef353739b618148b0fe2b4b3f005e60e262926c4d38e2"}, + {file = "opentelemetry_semantic_conventions-0.61b0.tar.gz", hash = "sha256:072f65473c5d7c6dc0355b27d6c9d1a679d63b6d4b4b16a9773062cb7e31192a"}, +] + +[package.dependencies] +opentelemetry-api = "1.40.0" +typing-extensions = ">=4.5.0" + [[package]] name = "overrides" version = "7.7.0" @@ -1910,95 +2640,102 @@ files = [ [[package]] name = "pandas" -version = "3.0.1" +version = "2.3.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false -python-versions = ">=3.11" -groups = ["main"] +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "pandas-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de09668c1bf3b925c07e5762291602f0d789eca1b3a781f99c1c78f6cac0e7ea"}, - {file = "pandas-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24ba315ba3d6e5806063ac6eb717504e499ce30bd8c236d8693a5fd3f084c796"}, - {file = "pandas-3.0.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:406ce835c55bac912f2a0dcfaf27c06d73c6b04a5dde45f1fd3169ce31337389"}, - {file = "pandas-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:830994d7e1f31dd7e790045235605ab61cff6c94defc774547e8b7fdfbff3dc7"}, - {file = "pandas-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a64ce8b0f2de1d2efd2ae40b0abe7f8ae6b29fbfb3812098ed5a6f8e235ad9bf"}, - {file = "pandas-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9832c2c69da24b602c32e0c7b1b508a03949c18ba08d4d9f1c1033426685b447"}, - {file = "pandas-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:84f0904a69e7365f79a0c77d3cdfccbfb05bf87847e3a51a41e1426b0edb9c79"}, - {file = "pandas-3.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:4a68773d5a778afb31d12e34f7dd4612ab90de8c6fb1d8ffe5d4a03b955082a1"}, - {file = "pandas-3.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:476f84f8c20c9f5bc47252b66b4bb25e1a9fc2fa98cead96744d8116cb85771d"}, - {file = "pandas-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ab749dfba921edf641d4036c4c21c0b3ea70fea478165cb98a998fb2a261955"}, - {file = "pandas-3.0.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e36891080b87823aff3640c78649b91b8ff6eea3c0d70aeabd72ea43ab069b"}, - {file = "pandas-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:532527a701281b9dd371e2f582ed9094f4c12dd9ffb82c0c54ee28d8ac9520c4"}, - {file = "pandas-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:356e5c055ed9b0da1580d465657bc7d00635af4fd47f30afb23025352ba764d1"}, - {file = "pandas-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9d810036895f9ad6345b8f2a338dd6998a74e8483847403582cab67745bff821"}, - {file = "pandas-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:536232a5fe26dd989bd633e7a0c450705fdc86a207fec7254a55e9a22950fe43"}, - {file = "pandas-3.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f463ebfd8de7f326d38037c7363c6dacb857c5881ab8961fb387804d6daf2f7"}, - {file = "pandas-3.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5272627187b5d9c20e55d27caf5f2cd23e286aba25cadf73c8590e432e2b7262"}, - {file = "pandas-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:661e0f665932af88c7877f31da0dc743fe9c8f2524bdffe23d24fdcb67ef9d56"}, - {file = "pandas-3.0.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75e6e292ff898679e47a2199172593d9f6107fd2dd3617c22c2946e97d5df46e"}, - {file = "pandas-3.0.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ff8cf1d2896e34343197685f432450ec99a85ba8d90cce2030c5eee2ef98791"}, - {file = "pandas-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eca8b4510f6763f3d37359c2105df03a7a221a508f30e396a51d0713d462e68a"}, - {file = "pandas-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:06aff2ad6f0b94a17822cf8b83bbb563b090ed82ff4fe7712db2ce57cd50d9b8"}, - {file = "pandas-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9fea306c783e28884c29057a1d9baa11a349bbf99538ec1da44c8476563d1b25"}, - {file = "pandas-3.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:a8d37a43c52917427e897cb2e429f67a449327394396a81034a4449b99afda59"}, - {file = "pandas-3.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d54855f04f8246ed7b6fc96b05d4871591143c46c0b6f4af874764ed0d2d6f06"}, - {file = "pandas-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e1b677accee34a09e0dc2ce5624e4a58a1870ffe56fc021e9caf7f23cd7668f"}, - {file = "pandas-3.0.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9cabbdcd03f1b6cd254d6dda8ae09b0252524be1592594c00b7895916cb1324"}, - {file = "pandas-3.0.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ae2ab1f166668b41e770650101e7090824fd34d17915dd9cd479f5c5e0065e9"}, - {file = "pandas-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6bf0603c2e30e2cafac32807b06435f28741135cb8697eae8b28c7d492fc7d76"}, - {file = "pandas-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c426422973973cae1f4a23e51d4ae85974f44871b24844e4f7de752dd877098"}, - {file = "pandas-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b03f91ae8c10a85c1613102c7bef5229b5379f343030a3ccefeca8a33414cf35"}, - {file = "pandas-3.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:99d0f92ed92d3083d140bf6b97774f9f13863924cf3f52a70711f4e7588f9d0a"}, - {file = "pandas-3.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3b66857e983208654294bb6477b8a63dee26b37bdd0eb34d010556e91261784f"}, - {file = "pandas-3.0.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56cf59638bf24dc9bdf2154c81e248b3289f9a09a6d04e63608c159022352749"}, - {file = "pandas-3.0.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1a9f55e0f46951874b863d1f3906dcb57df2d9be5c5847ba4dfb55b2c815249"}, - {file = "pandas-3.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1849f0bba9c8a2fb0f691d492b834cc8dadf617e29015c66e989448d58d011ee"}, - {file = "pandas-3.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c3d288439e11b5325b02ae6e9cc83e6805a62c40c5a6220bea9beb899c073b1c"}, - {file = "pandas-3.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:93325b0fe372d192965f4cca88d97667f49557398bbf94abdda3bf1b591dbe66"}, - {file = "pandas-3.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:97ca08674e3287c7148f4858b01136f8bdfe7202ad25ad04fec602dd1d29d132"}, - {file = "pandas-3.0.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:58eeb1b2e0fb322befcf2bbc9ba0af41e616abadb3d3414a6bc7167f6cbfce32"}, - {file = "pandas-3.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cd9af1276b5ca9e298bd79a26bda32fa9cc87ed095b2a9a60978d2ca058eaf87"}, - {file = "pandas-3.0.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f87a04984d6b63788327cd9f79dda62b7f9043909d2440ceccf709249ca988"}, - {file = "pandas-3.0.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85fe4c4df62e1e20f9db6ebfb88c844b092c22cd5324bdcf94bfa2fc1b391221"}, - {file = "pandas-3.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:331ca75a2f8672c365ae25c0b29e46f5ac0c6551fdace8eec4cd65e4fac271ff"}, - {file = "pandas-3.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15860b1fdb1973fffade772fdb931ccf9b2f400a3f5665aef94a00445d7d8dd5"}, - {file = "pandas-3.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:44f1364411d5670efa692b146c748f4ed013df91ee91e9bec5677fb1fd58b937"}, - {file = "pandas-3.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:108dd1790337a494aa80e38def654ca3f0968cf4f362c85f44c15e471667102d"}, - {file = "pandas-3.0.1.tar.gz", hash = "sha256:4186a699674af418f655dbd420ed87f50d56b4cd6603784279d9eef6627823c8"}, + {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, + {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"}, + {file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, + {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, + {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"}, + {file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"}, + {file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"}, + {file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"}, + {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, ] [package.dependencies] numpy = [ - {version = ">=1.26.0", markers = "python_version < \"3.14\""}, - {version = ">=2.3.3", markers = "python_version >= \"3.14\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" -tzdata = {version = "*", markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\""} - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)", "beautifulsoup4 (>=4.12.3)", "bottleneck (>=1.4.2)", "fastparquet (>=2024.11.0)", "fsspec (>=2024.10.0)", "gcsfs (>=2024.10.0)", "html5lib (>=1.1)", "hypothesis (>=6.116.0)", "jinja2 (>=3.1.5)", "lxml (>=5.3.0)", "matplotlib (>=3.9.3)", "numba (>=0.60.0)", "numexpr (>=2.10.2)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "psycopg2 (>=2.9.10)", "pyarrow (>=13.0.0)", "pyiceberg (>=0.8.1)", "pymysql (>=1.1.1)", "pyreadstat (>=1.2.8)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)", "python-calamine (>=0.3.0)", "pytz (>=2024.2)", "pyxlsb (>=1.0.10)", "qtpy (>=2.4.2)", "s3fs (>=2024.10.0)", "scipy (>=1.14.1)", "tables (>=3.10.1)", "tabulate (>=0.9.0)", "xarray (>=2024.10.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)", "zstandard (>=0.23.0)"] -aws = ["s3fs (>=2024.10.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.4.2)"] -compression = ["zstandard (>=0.23.0)"] -computation = ["scipy (>=1.14.1)", "xarray (>=2024.10.0)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "python-calamine (>=0.3.0)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)"] -feather = ["pyarrow (>=13.0.0)"] -fss = ["fsspec (>=2024.10.0)"] -gcp = ["gcsfs (>=2024.10.0)"] -hdf5 = ["tables (>=3.10.1)"] -html = ["beautifulsoup4 (>=4.12.3)", "html5lib (>=1.1)", "lxml (>=5.3.0)"] -iceberg = ["pyiceberg (>=0.8.1)"] -mysql = ["SQLAlchemy (>=2.0.36)", "pymysql (>=1.1.1)"] -output-formatting = ["jinja2 (>=3.1.5)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=13.0.0)"] -performance = ["bottleneck (>=1.4.2)", "numba (>=0.60.0)", "numexpr (>=2.10.2)"] -plot = ["matplotlib (>=3.9.3)"] -postgresql = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "psycopg2 (>=2.9.10)"] -pyarrow = ["pyarrow (>=13.0.0)"] -spss = ["pyreadstat (>=1.2.8)"] -sql-other = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)"] -test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)"] -timezone = ["pytz (>=2024.2)"] -xml = ["lxml (>=5.3.0)"] +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] [[package]] name = "pandocfilters" @@ -2050,7 +2787,7 @@ version = "12.1.1" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "pillow-12.1.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f1625b72740fdda5d77b4def688eb8fd6490975d06b909fd19f13f391e077e0"}, {file = "pillow-12.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:178aa072084bd88ec759052feca8e56cbb14a60b39322b99a049e58090479713"}, @@ -2165,6 +2902,24 @@ files = [ {file = "platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934"}, ] +[[package]] +name = "prettytable" +version = "3.17.0" +description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "prettytable-3.17.0-py3-none-any.whl", hash = "sha256:aad69b294ddbe3e1f95ef8886a060ed1666a0b83018bbf56295f6f226c43d287"}, + {file = "prettytable-3.17.0.tar.gz", hash = "sha256:59f2590776527f3c9e8cf9fe7b66dd215837cca96a9c39567414cbc632e8ddb0"}, +] + +[package.dependencies] +wcwidth = "*" + +[package.extras] +tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"] + [[package]] name = "prometheus-client" version = "0.24.1" @@ -2197,6 +2952,26 @@ files = [ [package.dependencies] wcwidth = "*" +[[package]] +name = "protobuf" +version = "6.33.5" +description = "" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b"}, + {file = "protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c"}, + {file = "protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5"}, + {file = "protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190"}, + {file = "protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd"}, + {file = "protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0"}, + {file = "protobuf-6.33.5-cp39-cp39-win32.whl", hash = "sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c"}, + {file = "protobuf-6.33.5-cp39-cp39-win_amd64.whl", hash = "sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a"}, + {file = "protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02"}, + {file = "protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c"}, +] + [[package]] name = "psutil" version = "7.2.2" @@ -2260,6 +3035,93 @@ files = [ [package.extras] tests = ["pytest"] +[[package]] +name = "pyarrow" +version = "23.0.1" +description = "Python library for Apache Arrow" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:3fab8f82571844eb3c460f90a75583801d14ca0cc32b1acc8c361650e006fd56"}, + {file = "pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:3f91c038b95f71ddfc865f11d5876c42f343b4495535bd262c7b321b0b94507c"}, + {file = "pyarrow-23.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:d0744403adabef53c985a7f8a082b502a368510c40d184df349a0a8754533258"}, + {file = "pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c33b5bf406284fd0bba436ed6f6c3ebe8e311722b441d89397c54f871c6863a2"}, + {file = "pyarrow-23.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ddf743e82f69dcd6dbbcb63628895d7161e04e56794ef80550ac6f3315eeb1d5"}, + {file = "pyarrow-23.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e052a211c5ac9848ae15d5ec875ed0943c0221e2fcfe69eee80b604b4e703222"}, + {file = "pyarrow-23.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5abde149bb3ce524782d838eb67ac095cd3fd6090eba051130589793f1a7f76d"}, + {file = "pyarrow-23.0.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6f0147ee9e0386f519c952cc670eb4a8b05caa594eeffe01af0e25f699e4e9bb"}, + {file = "pyarrow-23.0.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:0ae6e17c828455b6265d590100c295193f93cc5675eb0af59e49dbd00d2de350"}, + {file = "pyarrow-23.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:fed7020203e9ef273360b9e45be52a2a47d3103caf156a30ace5247ffb51bdbd"}, + {file = "pyarrow-23.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:26d50dee49d741ac0e82185033488d28d35be4d763ae6f321f97d1140eb7a0e9"}, + {file = "pyarrow-23.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c30143b17161310f151f4a2bcfe41b5ff744238c1039338779424e38579d701"}, + {file = "pyarrow-23.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db2190fa79c80a23fdd29fef4b8992893f024ae7c17d2f5f4db7171fa30c2c78"}, + {file = "pyarrow-23.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:f00f993a8179e0e1c9713bcc0baf6d6c01326a406a9c23495ec1ba9c9ebf2919"}, + {file = "pyarrow-23.0.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f4b0dbfa124c0bb161f8b5ebb40f1a680b70279aa0c9901d44a2b5a20806039f"}, + {file = "pyarrow-23.0.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:7707d2b6673f7de054e2e83d59f9e805939038eebe1763fe811ee8fa5c0cd1a7"}, + {file = "pyarrow-23.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:86ff03fb9f1a320266e0de855dee4b17da6794c595d207f89bba40d16b5c78b9"}, + {file = "pyarrow-23.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:813d99f31275919c383aab17f0f455a04f5a429c261cc411b1e9a8f5e4aaaa05"}, + {file = "pyarrow-23.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bf5842f960cddd2ef757d486041d57c96483efc295a8c4a0e20e704cbbf39c67"}, + {file = "pyarrow-23.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564baf97c858ecc03ec01a41062e8f4698abc3e6e2acd79c01c2e97880a19730"}, + {file = "pyarrow-23.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:07deae7783782ac7250989a7b2ecde9b3c343a643f82e8a4df03d93b633006f0"}, + {file = "pyarrow-23.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6b8fda694640b00e8af3c824f99f789e836720aa8c9379fb435d4c4953a756b8"}, + {file = "pyarrow-23.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8ff51b1addc469b9444b7c6f3548e19dc931b172ab234e995a60aea9f6e6025f"}, + {file = "pyarrow-23.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:71c5be5cbf1e1cb6169d2a0980850bccb558ddc9b747b6206435313c47c37677"}, + {file = "pyarrow-23.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b6f4f17b43bc39d56fec96e53fe89d94bac3eb134137964371b45352d40d0c2"}, + {file = "pyarrow-23.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fc13fc6c403d1337acab46a2c4346ca6c9dec5780c3c697cf8abfd5e19b6b37"}, + {file = "pyarrow-23.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c16ed4f53247fa3ffb12a14d236de4213a4415d127fe9cebed33d51671113e2"}, + {file = "pyarrow-23.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:cecfb12ef629cf6be0b1887f9f86463b0dd3dc3195ae6224e74006be4736035a"}, + {file = "pyarrow-23.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:29f7f7419a0e30264ea261fdc0e5fe63ce5a6095003db2945d7cd78df391a7e1"}, + {file = "pyarrow-23.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:33d648dc25b51fd8055c19e4261e813dfc4d2427f068bcecc8b53d01b81b0500"}, + {file = "pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd395abf8f91c673dd3589cadc8cc1ee4e8674fa61b2e923c8dd215d9c7d1f41"}, + {file = "pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:00be9576d970c31defb5c32eb72ef585bf600ef6d0a82d5eccaae96639cf9d07"}, + {file = "pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c2139549494445609f35a5cda4eb94e2c9e4d704ce60a095b342f82460c73a83"}, + {file = "pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7044b442f184d84e2351e5084600f0d7343d6117aabcbc1ac78eb1ae11eb4125"}, + {file = "pyarrow-23.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a35581e856a2fafa12f3f54fce4331862b1cfb0bef5758347a858a4aa9d6bae8"}, + {file = "pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca"}, + {file = "pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1"}, + {file = "pyarrow-23.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b95a3994f015be13c63148fef8832e8a23938128c185ee951c98908a696e0eb"}, + {file = "pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1"}, + {file = "pyarrow-23.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c250248f1fe266db627921c89b47b7c06fee0489ad95b04d50353537d74d6886"}, + {file = "pyarrow-23.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f4763b83c11c16e5f4c15601ba6dfa849e20723b46aa2617cb4bffe8768479f"}, + {file = "pyarrow-23.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:3a4c85ef66c134161987c17b147d6bffdca4566f9a4c1d81a0a01cdf08414ea5"}, + {file = "pyarrow-23.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:17cd28e906c18af486a499422740298c52d7c6795344ea5002a7720b4eadf16d"}, + {file = "pyarrow-23.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:76e823d0e86b4fb5e1cf4a58d293036e678b5a4b03539be933d3b31f9406859f"}, + {file = "pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a62e1899e3078bf65943078b3ad2a6ddcacf2373bc06379aac61b1e548a75814"}, + {file = "pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:df088e8f640c9fae3b1f495b3c64755c4e719091caf250f3a74d095ddf3c836d"}, + {file = "pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:46718a220d64677c93bc243af1d44b55998255427588e400677d7192671845c7"}, + {file = "pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a09f3876e87f48bc2f13583ab551f0379e5dfb83210391e68ace404181a20690"}, + {file = "pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce"}, + {file = "pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019"}, +] + +[[package]] +name = "pyasn1" +version = "0.6.2" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf"}, + {file = "pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b"}, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +description = "A collection of ASN.1-based protocols modules" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"}, + {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"}, +] + +[package.dependencies] +pyasn1 = ">=0.6.1,<0.7.0" + [[package]] name = "pycparser" version = "3.0" @@ -2273,6 +3135,162 @@ files = [ {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] +[[package]] +name = "pydantic" +version = "2.12.5" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, + {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.41.5" +typing-extensions = ">=4.14.1" +typing-inspection = ">=0.4.2" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146"}, + {file = "pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49"}, + {file = "pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba"}, + {file = "pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9"}, + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"}, + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"}, + {file = "pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9"}, + {file = "pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd"}, + {file = "pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a"}, + {file = "pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008"}, + {file = "pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf"}, + {file = "pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3"}, + {file = "pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460"}, + {file = "pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, + {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, +] + +[package.dependencies] +typing-extensions = ">=4.14.1" + [[package]] name = "pygments" version = "2.19.2" @@ -2294,7 +3312,7 @@ version = "3.3.2" description = "pyparsing - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"}, {file = "pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"}, @@ -2318,6 +3336,21 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-dotenv" +version = "1.2.2" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, + {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "python-json-logger" version = "4.0.0" @@ -2333,6 +3366,49 @@ files = [ [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec ; implementation_name != \"pypy\"", "mypy", "orjson ; implementation_name != \"pypy\"", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] +[[package]] +name = "pytz" +version = "2026.1.post1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +groups = ["main", "dev"] +files = [ + {file = "pytz-2026.1.post1-py2.py3-none-any.whl", hash = "sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a"}, + {file = "pytz-2026.1.post1.tar.gz", hash = "sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1"}, +] + +[[package]] +name = "pywin32" +version = "311" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +groups = ["dev"] +markers = "sys_platform == \"win32\"" +files = [ + {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, + {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, + {file = "pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b"}, + {file = "pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151"}, + {file = "pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503"}, + {file = "pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2"}, + {file = "pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31"}, + {file = "pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067"}, + {file = "pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852"}, + {file = "pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d"}, + {file = "pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d"}, + {file = "pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a"}, + {file = "pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee"}, + {file = "pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87"}, + {file = "pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42"}, + {file = "pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c"}, + {file = "pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd"}, + {file = "pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b"}, + {file = "pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91"}, + {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"}, +] + [[package]] name = "pywinpty" version = "3.0.3" @@ -2757,6 +3833,21 @@ files = [ {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, ] +[[package]] +name = "rsa" +version = "4.9.1" +description = "Pure-Python RSA implementation" +optional = false +python-versions = "<4,>=3.6" +groups = ["dev"] +files = [ + {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"}, + {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + [[package]] name = "ruff" version = "0.15.5" @@ -2791,7 +3882,7 @@ version = "1.8.0" description = "A set of python modules for machine learning and data mining" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "scikit_learn-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:146b4d36f800c013d267b29168813f7a03a43ecd2895d04861f1240b564421da"}, {file = "scikit_learn-1.8.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f984ca4b14914e6b4094c5d52a32ea16b49832c03bd17a110f004db3c223e8e1"}, @@ -2853,7 +3944,7 @@ version = "1.17.1" description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec"}, {file = "scipy-1.17.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696"}, @@ -2997,6 +4088,40 @@ files = [ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] +[[package]] +name = "skops" +version = "0.13.0" +description = "A set of tools, related to machine learning in production." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "skops-0.13.0-py3-none-any.whl", hash = "sha256:55e2cccb18c86f5916e4cfe5acf55ed7b0eecddf08a151906414c092fa5926dc"}, + {file = "skops-0.13.0.tar.gz", hash = "sha256:66949fd3c95cbb5c80270fbe40293c0fe1e46cb4a921860e42584dd9c20ebeb1"}, +] + +[package.dependencies] +numpy = ">=1.25.0" +packaging = ">=17.0" +prettytable = ">=3.9" +scikit-learn = ">=1.2" +scipy = ">=1.10.0" + +[package.extras] +rich = ["rich (>=12)"] + +[[package]] +name = "smmap" +version = "5.0.3" +description = "A pure Python implementation of a sliding window memory map manager" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "smmap-5.0.3-py3-none-any.whl", hash = "sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f"}, + {file = "smmap-5.0.3.tar.gz", hash = "sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c"}, +] + [[package]] name = "soupsieve" version = "2.8.3" @@ -3009,6 +4134,124 @@ files = [ {file = "soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349"}, ] +[[package]] +name = "sqlalchemy" +version = "2.0.48" +description = "Database Abstraction Library" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "sqlalchemy-2.0.48-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89"}, + {file = "sqlalchemy-2.0.48-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0"}, + {file = "sqlalchemy-2.0.48-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd"}, + {file = "sqlalchemy-2.0.48-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29"}, + {file = "sqlalchemy-2.0.48-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0"}, + {file = "sqlalchemy-2.0.48-cp310-cp310-win32.whl", hash = "sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018"}, + {file = "sqlalchemy-2.0.48-cp310-cp310-win_amd64.whl", hash = "sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76"}, + {file = "sqlalchemy-2.0.48-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc"}, + {file = "sqlalchemy-2.0.48-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c"}, + {file = "sqlalchemy-2.0.48-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7"}, + {file = "sqlalchemy-2.0.48-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d"}, + {file = "sqlalchemy-2.0.48-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571"}, + {file = "sqlalchemy-2.0.48-cp311-cp311-win32.whl", hash = "sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617"}, + {file = "sqlalchemy-2.0.48-cp311-cp311-win_amd64.whl", hash = "sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c"}, + {file = "sqlalchemy-2.0.48-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b"}, + {file = "sqlalchemy-2.0.48-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb"}, + {file = "sqlalchemy-2.0.48-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894"}, + {file = "sqlalchemy-2.0.48-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9"}, + {file = "sqlalchemy-2.0.48-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e"}, + {file = "sqlalchemy-2.0.48-cp312-cp312-win32.whl", hash = "sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99"}, + {file = "sqlalchemy-2.0.48-cp312-cp312-win_amd64.whl", hash = "sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a"}, + {file = "sqlalchemy-2.0.48-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4"}, + {file = "sqlalchemy-2.0.48-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f"}, + {file = "sqlalchemy-2.0.48-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed"}, + {file = "sqlalchemy-2.0.48-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658"}, + {file = "sqlalchemy-2.0.48-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8"}, + {file = "sqlalchemy-2.0.48-cp313-cp313-win32.whl", hash = "sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131"}, + {file = "sqlalchemy-2.0.48-cp313-cp313-win_amd64.whl", hash = "sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2"}, + {file = "sqlalchemy-2.0.48-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae"}, + {file = "sqlalchemy-2.0.48-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb"}, + {file = "sqlalchemy-2.0.48-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b"}, + {file = "sqlalchemy-2.0.48-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121"}, + {file = "sqlalchemy-2.0.48-cp313-cp313t-win32.whl", hash = "sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485"}, + {file = "sqlalchemy-2.0.48-cp313-cp313t-win_amd64.whl", hash = "sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79"}, + {file = "sqlalchemy-2.0.48-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd"}, + {file = "sqlalchemy-2.0.48-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f"}, + {file = "sqlalchemy-2.0.48-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b"}, + {file = "sqlalchemy-2.0.48-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0"}, + {file = "sqlalchemy-2.0.48-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2"}, + {file = "sqlalchemy-2.0.48-cp314-cp314-win32.whl", hash = "sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6"}, + {file = "sqlalchemy-2.0.48-cp314-cp314-win_amd64.whl", hash = "sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0"}, + {file = "sqlalchemy-2.0.48-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241"}, + {file = "sqlalchemy-2.0.48-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0"}, + {file = "sqlalchemy-2.0.48-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3"}, + {file = "sqlalchemy-2.0.48-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b"}, + {file = "sqlalchemy-2.0.48-cp314-cp314t-win32.whl", hash = "sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f"}, + {file = "sqlalchemy-2.0.48-cp314-cp314t-win_amd64.whl", hash = "sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933"}, + {file = "sqlalchemy-2.0.48-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e"}, + {file = "sqlalchemy-2.0.48-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616"}, + {file = "sqlalchemy-2.0.48-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7"}, + {file = "sqlalchemy-2.0.48-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b"}, + {file = "sqlalchemy-2.0.48-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67"}, + {file = "sqlalchemy-2.0.48-cp38-cp38-win32.whl", hash = "sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad"}, + {file = "sqlalchemy-2.0.48-cp38-cp38-win_amd64.whl", hash = "sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565"}, + {file = "sqlalchemy-2.0.48-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77"}, + {file = "sqlalchemy-2.0.48-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457"}, + {file = "sqlalchemy-2.0.48-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e"}, + {file = "sqlalchemy-2.0.48-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a"}, + {file = "sqlalchemy-2.0.48-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6"}, + {file = "sqlalchemy-2.0.48-cp39-cp39-win32.whl", hash = "sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5"}, + {file = "sqlalchemy-2.0.48-cp39-cp39-win_amd64.whl", hash = "sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099"}, + {file = "sqlalchemy-2.0.48-py3-none-any.whl", hash = "sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096"}, + {file = "sqlalchemy-2.0.48.tar.gz", hash = "sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7"}, +] + +[package.dependencies] +greenlet = {version = ">=1", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +typing-extensions = ">=4.6.0" + +[package.extras] +aiomysql = ["aiomysql (>=0.2.0)", "greenlet (>=1)"] +aioodbc = ["aioodbc", "greenlet (>=1)"] +aiosqlite = ["aiosqlite", "greenlet (>=1)", "typing_extensions (!=3.10.0.1)"] +asyncio = ["greenlet (>=1)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (>=1)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10)"] +mssql = ["pyodbc"] +mssql-pymssql = ["pymssql"] +mssql-pyodbc = ["pyodbc"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"] +mysql-connector = ["mysql-connector-python"] +oracle = ["cx_oracle (>=8)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql-asyncpg = ["asyncpg", "greenlet (>=1)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] +postgresql-psycopg2binary = ["psycopg2-binary"] +postgresql-psycopg2cffi = ["psycopg2cffi"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] +sqlcipher = ["sqlcipher3_binary"] + +[[package]] +name = "sqlparse" +version = "0.5.5" +description = "A non-validating SQL parser." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "sqlparse-0.5.5-py3-none-any.whl", hash = "sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba"}, + {file = "sqlparse-0.5.5.tar.gz", hash = "sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e"}, +] + +[package.extras] +dev = ["build"] +doc = ["sphinx"] + [[package]] name = "stack-data" version = "0.6.3" @@ -3029,6 +4272,25 @@ pure-eval = "*" [package.extras] tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] +[[package]] +name = "starlette" +version = "0.52.1" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74"}, + {file = "starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933"}, +] + +[package.dependencies] +anyio = ">=3.6.2,<5" +typing-extensions = {version = ">=4.10.0", markers = "python_version < \"3.13\""} + +[package.extras] +full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"] + [[package]] name = "terminado" version = "0.18.1" @@ -3057,7 +4319,7 @@ version = "3.6.0" description = "threadpoolctl" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb"}, {file = "threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e"}, @@ -3132,6 +4394,21 @@ files = [ {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] +[[package]] +name = "typing-inspection" +version = "0.4.2" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, + {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, +] + +[package.dependencies] +typing-extensions = ">=4.12.0" + [[package]] name = "tzdata" version = "2025.3" @@ -3143,7 +4420,6 @@ files = [ {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, ] -markers = {main = "sys_platform == \"win32\" or sys_platform == \"emscripten\""} [[package]] name = "uri-template" @@ -3178,6 +4454,42 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] +[[package]] +name = "uvicorn" +version = "0.41.0" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "uvicorn-0.41.0-py3-none-any.whl", hash = "sha256:29e35b1d2c36a04b9e180d4007ede3bcb32a85fbdfd6c6aeb3f26839de088187"}, + {file = "uvicorn-0.41.0.tar.gz", hash = "sha256:09d11cf7008da33113824ee5a1c6422d89fbc2ff476540d69a34c87fab8b571a"}, +] + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" + +[package.extras] +standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.20)", "websockets (>=10.4)"] + +[[package]] +name = "waitress" +version = "3.0.2" +description = "Waitress WSGI server" +optional = false +python-versions = ">=3.9.0" +groups = ["dev"] +markers = "platform_system == \"Windows\"" +files = [ + {file = "waitress-3.0.2-py3-none-any.whl", hash = "sha256:c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e"}, + {file = "waitress-3.0.2.tar.gz", hash = "sha256:682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f"}, +] + +[package.extras] +docs = ["Sphinx (>=1.8.1)", "docutils", "pylons-sphinx-themes (>=1.0.9)"] +testing = ["coverage (>=7.6.0)", "pytest", "pytest-cov"] + [[package]] name = "wcwidth" version = "0.6.0" @@ -3231,6 +4543,24 @@ docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx_rtd_theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["pytest", "websockets"] +[[package]] +name = "werkzeug" +version = "3.1.6" +description = "The comprehensive WSGI web application library." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "werkzeug-3.1.6-py3-none-any.whl", hash = "sha256:7ddf3357bb9564e407607f988f683d72038551200c704012bb9a4c523d42f131"}, + {file = "werkzeug-3.1.6.tar.gz", hash = "sha256:210c6bede5a420a913956b4791a7f4d6843a43b6fcee4dfa08a65e93007d0d25"}, +] + +[package.dependencies] +markupsafe = ">=2.1.1" + +[package.extras] +watchdog = ["watchdog (>=2.3)"] + [[package]] name = "win32-setctime" version = "1.2.0" @@ -3247,7 +4577,27 @@ files = [ [package.extras] dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] +[[package]] +name = "zipp" +version = "3.23.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, + {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +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)"] +test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] + [metadata] lock-version = "2.1" python-versions = ">=3.11,<4.0" -content-hash = "ce3bd6a9236ac7a3b732c0b976dbb2074d8e3ee826779c59f3ab17f6cfbb9d7b" +content-hash = "2f2caa61b864b814722ec562a5a777dc05105d2d0a91d0d2ae88239f9eb05e3b" diff --git a/pyproject.toml b/pyproject.toml index 6266850..790e4ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ readme = "README.md" requires-python = ">=3.11,<4.0" dependencies = [ "scikit-learn (>=1.8.0,<2.0.0)", - "pandas (>=3.0.1,<4.0.0)", + "pandas (<3)", "seaborn (>=0.13.2,<0.14.0)", "loguru (>=0.7.3,<0.8.0)", ] @@ -19,6 +19,7 @@ dependencies = [ [tool.poetry.group.dev.dependencies] notebook = "^7.5.4" ruff = "^0.15.5" +mlflow = "^3.10.1" [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] diff --git a/src/diamonds/__pycache__/__init__.cpython-311.pyc b/src/diamonds/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index e9cf139a8b7cf89d9d17f2623a21530b3fbb8e86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 260 zcmZ3^%ge<81hQAwW%>c>#~=<2FhUuhK}x1Gq%cG=q%a0EXfl<$0|i_%6La(PQi>IP zeH023ld}`kQxzUHOi?IGO-oEJ$uCl<%r7lc$jdKDP0G*DR!GiINmaE|k+{RZwb9titRyzrI6zZvnPTRbwzIHv2o7Q65RTC$7m&;av_ZVh z`@hBiUS8er_efN@-^?QVGr>>vd(_={T*#7GvY~@UHH|niqQFu)n9txKer$Guw`FX@pAyUQJ4AAamP_@CLEvNZ7&-6`ox#m&+e<8B(My*@+p&R!m2sV%1WFL{>s4Rh7z-(%Jz8Ht1r_T}qTm zE<3x7ErE)+MSwDb011Tw^Uwl31g-)LXpTMf&}(m8VNnqa2vAYtc{=TozgP{E9Z-2;q;zj81KKi)F2d^QpE`&~U=*fcN;X zwi}5vTV=J~mZ)x1Hjo=>OiK=-D$#JJNOboo3Ta$NXqC)tmud@2Er$K8`8%JI1E2tN zJZ;ajK|M#;sTn%sOFj0hv){vd=NaqU`+?AR?M(?)-JQ8Rtr8`%d#)$o#-}z+NDqbb z@$X>^cgB`*M{noA^saLQl@I{My@1JPub;oAh*BoM9Bm;YDv6q?%33@gw;Wi!zwT@G z#8c|0>lfb>Q!7MXTalkNW){%q%;Y8c!TQMaR7cZT$wgD3NQPNrKFguzRm+zJON5iz zEjFtxFU#0sGWoP((TZv@1yNhEm{lc{$HeCrD?iAn8bDZ61Tf8_3zEeF&L#2{qb;wL z7FxDj9Pk99K_&Yfjeh&~*ou;q$5aK2nsPU@R!l2nDMgaU7K>?Uwg!%=IMw+e*2N2J zmb+~$J_qVZ^ilr|L`R3guo)b#zGVdCW-zYLH)x-e`}YuXdVf9ttNB{sb%TkUOuWX# z5BV3i?r)biOTYV|D)0W>;HOP~TAw@g_HDhnJ+nDexng)eD# z!r&%NZnDNr9!3Vu$VheFh>V+&@v^thg$}r(eQu~SwL4Mch79hS$z7}2^&hR_(*}3L zumoV^{;SXepgKh3if{$U-lKb?S4pL6rbURU&?- z0H*0ZM>nQBp>cyQ!6Pvpj^u2H$PR~sSW=<^rR+kNA;fhdc#lcYC5DvHrwG#$h)NC+ zXBIFKnZ5HB0vI~5a$hCuh~fdDmj9kC7lgc`31T*@++QC~Wo0pMBQ8FjRZ?PBor!nL z#9*A-4@5_GuW!duo+?jOKCXOR=R;);6NA4Y6ToDQ2w=3R2etv^42Xq7b}i<>L(q>e z5<-rrN{}0ko>=7RSb#4<$E!qQ5r~c&4DIZ1pf+JqD7^F2$4kFis^q`EwzFh}Crqfp zNqxS~@H^hhduAY7P3#9Qo6Ja!8L@HKxPW{E;8xqxuAL-ikoR~J$m8d_Qlgfry`GT0 zL4k8f2yraHse-Jstl+h;D9e?}r?N#!hQ;@(a#l`hf~2h#WHm-NH^E+i^Yk?x!k?rg zSygQ>;HzNF47}WL+P%^ewc54?@*F_!RK8|G3!NtC zoLjJ*1)NC{@VHV+wwQy2z~+m&yE4Y)RA7P#i&gHf07Fc(F3kV5XNV*n3JvWvaAVdxEmF*EaZWs3QAFHYIfPM zwWuYFTC+GXMgYrH8}rSUuY+F&Ti&J4JSy2JIOe1@vFXu=Fl=(n2TVF-mT9t21C zgQL4YF@j@ea7>>+4E8@7gz;!clz3%6?mK!c6#QqZj`4=H@5ReQ6ERm8c1 z&~zyWHv>ELf+6YFr5K`+Ea3^Fj08peA|WIi*be-bn+7wAS$PKk2zVqcs6PYRa8ML= zgxtFQ)KRF`s&&+-+fN-`u65Ts3fEe-j$*a$dgSJ}Uewtm|4ZeR>3^xRZuqa7{;RsT z!JMN8cE%q~HxM*>$@Orn6B^Zd56Z$X6({LkZ2(;Ln|6ho)B<}zK diff --git a/src/diamonds/__pycache__/data.cpython-313.pyc b/src/diamonds/__pycache__/data.cpython-313.pyc deleted file mode 100644 index 330dcc0cc077e15d81786bc8cd4486f4f7b6eef0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2645 zcmbVNO-vg{6rNqL|BctIF;N^s9f$llK{$z^1xiUtQba>SR5q3@fwWre1x)Q-ch*)Q ziki(0lmnzv6z5cWDjeG6*q(ao-Ht2SnWj>toN{vtJ@wKzYm9*=Ipj(E=FQH$dGo&a zGg~b!E(Fy1@6V}KCql32q(QbFVQZN|=pho3$c!V*m?MiVFtX#^RV%iJ(6nXJ(@<-U zVI*4mK$jA>i*AvdW+r|0`Ci`3iq;@n;1(F{6m4(c^G;n(v{PN|`T$Lbsp)=?rswUq zfxp4M9@OPt)(S!|Cpyh@z0IU5-7#;*^>r+`J+uBP_8d+{ zyo_hG^U;KsRH8e(8lxW7aiTe)R(i5a#JOt|d*L((eEKzz^S+0F0W5p-(}Q!NeRp zXNhnVm~I)pxrrbrELgjxQ|lqz0-SiiR+OxyYB@-fACSG~vvUoCe_`ioG=$A`^vh3@|jeV+cUEOb|x`ifK;6 zOPdU_r_@9`pH#rL7F|gziJX+oEoBuw!q#0hy{o5Z9cX^13Kd;9(Z$EW{CW8Fd`OJ)haVKcv zqriwwn^}OQfNbcZQ)^01DvJ>p;gVR(;t<_uF4%HfI;H0@4G3wOP35EntoG?qo0k@IhYPy-Rb;;Ar zJ`EFhylF2R&uSL_A*vc2dC86#DPYx$EE zw=wdP_pRPtxx2o&e7DG-tML6LzQ4j>Eb$l1{D?7DtuJr5o{kkyeMa{TSNPEqKU(3h zm-y>t{)RF3!hdZ2blKl$T&ovw5cxl<2;C*2d*iFJ5H-eM2yKtLzw53#{8e8^#do3P zyHNJ^R=xb{+{)Y=JLk7S!MLF8mxqhoVY6I_Ly|IbN|mGtb2AbkwydlsWgVXdZ-`x2 z-al{;0F1$GK_~|fi_hAcVIOO!!WOq|4$V7 z3q@XfTPxnqXWq`j?Xvfb;eNyUm_r5p{hh~m{y`wtx&q9hwF{4i9t_nGi0hYry!OMj zZ7SA!e2llie(!ngslit7hVZ0gvtyfzwXP#fu%QLw`WGAFC*7Ofzp%eKe{~kmjFh@A zZ6jEyea;}xvwXX3IsDuy+&^Mmdd?p%gztZAj6H8Zu|8jJj~X|gy8~-l*?scf6=USy MH#H~Xf~K4Q0TA;YK>z>% diff --git a/src/diamonds/__pycache__/model.cpython-311.pyc b/src/diamonds/__pycache__/model.cpython-311.pyc deleted file mode 100644 index 8ffbe4390aa10c77f1c5d23d1ce15e99c0ffc0f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4528 zcmb7HO>7&-6`tiT$>py|ijpN;vR0BUn}#JrM&TdXkqrMRb^Qy=Fn6@0os?bqeB%-h~VKo6#aoc94AN{2Y_FNF0-I>LFm5Y@ZVU7QaT zVtPCs=X?-!66plzLxpZVnNI3G=^ni|-K+0O@8R-rp)cL9MetrNiiMn{b$u$O_h~Ua zfcN&dcY?I|j&>A_IiHpQ-9fGUQyJkb=5Wr2;`gjA}-_&41D~8St#koZK4`h&Llb} zDG!a@Fz`=J`;w70HB4x9&Q=XgCE8q8Er0?{IhWUq1$sn41OTlOuy03VB+(0%1P&Mz#^o5b2Kj$H+-RMHaVO(P}IZXK&eMxD37P#b43 zAts>-F0>w&RD!jZOeV)ORu-0```tr|m}IeGs|&5s*J)6PjTJJ6s$=RS*e($x3%KeO zhBgs?Z@&TZ4B6ZIG-1Q@0@|-SGMj0(iY983=H2kU0NJaK-1fHn5z_n{@{aNTZM}hw zpu1NKeIYFiWmFbE6iC7jY|{;w(R1|W4r@LU%Amc48$d!t?E_Tg`b7;C~q$+_99m1;i{CyB{;OAO5lLtf-NOymJChNN+fSAD0az!&qR>Vc(bF# zo8z6rn_K6sOevO4xR4og8&+b+ub4T$YSW0rcw%8f86gZlBS(SZ@W}u$!Kjf`bH!Wy zzO3!baoz=U*Fw$7Ve8tGVwzaI>7}-oZi4)btiCW@BBOZwQ8VE>bw$Y2^#A>hOAAJ1&KItUKtI6?N za@>(8>Vf#v>1y|At$Wmw4>Y{upzm8GCjH+rQn}h0c5QveNuH@D&(xA<9QkZL5Pce1 zJNf4xCpJ@!&D3Huj(l#n(LH0Jx)NSpbmT)@9B3Y5>-4a7di<4ZjUWp5J5nDx4Ay2l zsRbJB>^QiO1M>`((HeZ;Esz#GZeR(Z3&0Sr!_|opqae_ExuaA6-3-qT)W6hZEVe-B zBtyKj6%@`v&-?JR_5rD&x)k`;tf zyM1O^-0rb}ebK$GWtYG1((m%gUHX07J#v?Re_1Mf%f7N-6CgLsWqFMu?VaL|6c^FG zy}tmTUJfh=Z5F#*r5tz;@7Hor6Q4_8?ub1C`fQ)Zu1LBLSwqxS48+3JLyl8PSBv4(HTFYl`5`~!w3)3XVNE`_D=54H7)LVoEZl^-zJtp+QEkjzPKDgx8 zm(4-Wvtbt)xyZ;Rrt61?0Lf=9D)C2?_d}Lm*00QyxKY47vrar(dc(cofC$goKcmQW_ zH`kNye}ACC+e|f<_~h&=+1t!D6YseTT19Q*qH3$N>|N+mC+Z_bgPtFMp~3JuO!Bz- zc55%y+6ufxo1o$o)8N()A%S@FhK4^P*Wh$g5}Ab$^%OPgYfeYzm|WzjCO3g69B=G6 zVG)i>K8BMFNG%rk0g6f+ij&pIU@bBTPz*&rJH2veZSt#=n*&a0x*D3Ug{B>8nu8#9 zkcO=X1$dwt6Z7z|im)YUtSxFMBA(7@S6iGl^`Z&N3^KH*ErtDUrQc? zJWX=Y#r{oMe*g+@CkS;k=D2Ge9dz8aj>a8#t)m%dw^~Ps9e3Srws%)N?jTpKqe;hI zca!K2`Y*MPx}A1y_y&djt8)zmpS64Zvy)8k5&BneuZ@23^9BNT^T4L{b&9j!$o#XD z9QO$E2I>$wA&jlx-W=U5Z62wOzt=#}-boH8gqfB3&kIaGvqrvJ;>>>}{2KoaPHTZ3 diff --git a/src/diamonds/__pycache__/model.cpython-313.pyc b/src/diamonds/__pycache__/model.cpython-313.pyc deleted file mode 100644 index 25862907106a1b597dec3b51556e805dc4933758..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3771 zcma(UOKcm*b(XtaE|(vX6eUZF6t87lHUpc2967e+RBHW8Oj>HnH4O!lL9ECT#hBcs zXP31lAP9SE(n}N|PSl>9OQT#0_1aU9JyK9m5K|cm&|Z9_V;8;l&2ULkPFr*!zIpTJ z&D%HcH%~7@Ar-+`|JNT%-v$u+J6m*y>>@AD2?#w#I?{zSN(n^J816}XQX&yKE~cfF zmv}iYrR9{5_)-c{_}ZKHr&OYHTn0Qq0vz|HgQ*Y+aa>7k z(Q8(@Rx$4o!?f2dQo$tQp`o9f z_+87nVdkv@CN!)&hFLI3LC+gyU;vSNsZuTDTa{|f;RH3kxOlkoW=e%3lRl7vgI49H zMX>E;a1kb(tI(fb#HHf;szvNxa^yB>We}HCvdn};`zzQmbH=I-iaI!l39$%`aiaa8 zW)NI(X$rZJv-9vN`ufo$RZQ~Obc~{VdXcIXxL7%78Wl`sf}I*M^AKO%;R8&B--}HE zkI`~>PZxC0jIhl1_|QdN(!IJoBQ7)7wP`+G0Ujo!z4q(sjGzaSk|`_+S3s5#MrhgJ z-4A9_7`^Ga=zawYOA#jQ6iS3PTk17}4F_w6sntw}7+|1+#?{vzmYj9XS;yKcSXW!$ zfO}RA0(SzR*xH&^GYeXwMoMN;b803`NmYHX%b=d`jvjMpvzqNdrogxZl9`1xYmI-U z{n4{HSxjoaQ4&as^y<)@jhy#&*DD&zKRv z5oo~7nVn#}!-5ySlq;EFq&ysg2=nsG(9n^qQ1QNLQkkWRK{orc=6%z8Xtpgst0laI zDMX-LArfRD1c0h{jdBg&U?H0DkQgJ${HC_;frX~gE0gP11y6pE&#xO~)tZ`QDK=Rs z85PScbY^?fCi%k!myoP(&|sd&LXH#28IafqKl^L5108{dn)^*rhi%k`VBL8Qd?ea8>NL)-H^vpeS+!?73%)G*ft}bcQq8?b9nihLFq^tzV z72F)}CYM$vxJs-%)F+lMRkuJURqBIE$BG;o1&L$~0F`ZC2WhBc*-mba;0HA*FA!M@ zqz(jLafAA>TRY`a(S+21&G0&8N*U*B?MR{`n3RfO&4f%OCYu!m!m0*g)+FrZBP@g= z))EY7!4IJij_9Zd0RhhFu0lsHVY9O=k2NyEPKMp!ahb?vASU5we*^%+Cy3&sO@Hk3 z)Xvmi{Cq=6HvQ4h=l1(gHk4B>uQ(>ZKw{iizujeA*qPspUuh_Bvr`MZLwoVrhH~W< z)`5wpKfD!eC}%n|Fq~ns27L8}mWqPI4QYs+1s(F;stOBc5gt%%=P}BnOt%ID!5vGn zi*68VzyU557QxUW2iY=NsPlvE`BQ=Zw4au+do#5xr?j$Js|&0&8*NV?WTB`4NE6G%9}m;&_neeMt%=fK8*by zsxK>Ly;(Wy(*<~Dl&q5J<^U+>j!v%iqjv`ps)6aMzguQ?i;t{73=LIQ)x|#arr6O~ zLkmL)1(1e{C?PFEwG=A`24G|AAs47rF{*geGplWi$?3I(kNP0K3Z=Y5;Eh9s)h7~R zAPRtbOAfBs)LVr|$w>sr6-Jc7Lr~7C3=VQDy><4D**Wp~Gzu6aSh9k{L{JG!TC)eL;h0)OQ zFF*Y3!!JJiB=E6xpoF&KTk_WG_Q1Bi9cYA4{Z%>rgNTOC@Cc&9(vjlHGMxv}Dj@$y z5P6o}s7ENn^5m5Vk0}v!cgb1$~yS)p+4!-Ncb5y#gJbxy2#^Pdr5FA=3IHvYP zV-OsH(5ExMnc2Gg^`);a?T+pR<{Hu*_hsTV4chn1&?A`1Rp_$`b0m#)NS)fuD?IJ% zkn>ihY5_AV(R83gg^L}&LGAj_>I)5b7~H3bKM(A+pz+R5yG?N;opmOMDqz#bl~w55 zS(eaf=R~(9>Sv)qDF304-4vgr{iYDLVZWo&OHaKSgIb z4wMT|(G>iBhbsH1@;B7qlE;MCxAhi+>B+s9Y--IN6Nb0%JURK>_ge_i-BY{v9}^t? zv+|Nrez@QfqAevROzhm*J-J)kePi$ZPhKKex6a0d`K{G2%b%57u%3THzTWt1@Md1H)<{hJYy66vki%O}3XHuHP+|l*E$6TWq=cDXBTdxA=VhU0i+Q zgIwJ`gF}KMZ?Wd&Cnx4;vfX0JFTTa;;uzu>AK)0`af=J04$Njx%`3|+%FnySoSs@z z#0oTZCBtWs;lFJ4GxBp&^^5b15=-)vGAm2d^7WH}7U}z!rU98LnTfgic`3#E#YM>o zPC;T(Vs5csLFF$F8=$L7b5iY!_<^P|0&%eskodsN$jEqufwKV&A8-pcaNgh*ZQyz! fC_F`Ky4)nW3kn7s)GrEJT@kcu-~+)TUZ6GrXggdw diff --git a/src/diamonds/__pycache__/params.cpython-313.pyc b/src/diamonds/__pycache__/params.cpython-313.pyc deleted file mode 100644 index 071b873ff3bc4a8f59335229154484ac94f7e4cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 348 zcmey&%ge<81h)>Y%gh7Pk3k$5V1Y6|`v4hJ8G;#t8NC^b7=oFK7=xLMm|_@$*kDQ# zbPy+k4Pynf1hbklL3l;1>5Q6eFF_o?TP!JwC5gA#a`RJCbBb^A`TD!K`osshx_btP z1V!Fr&B;$r%+X}K#gt!si_^t1#4$d=F~s8*7epPH&7PW9mRXdacZ)eawWNp@XzEIa z&mhBZ+308F=cejsB`0Sj7A55y>L&wj(ND=t%+1eBfzieK#YM>oPC;T(Vs5csLFFwD z8=#{~b5iY!_<@Eo0&%fAkodsN$jEq`f%5^kU<2n3UeN}w2ZF-Wr6x*EmzyYeLBU{y O`ei|@M!q6mpjrS716Jq& diff --git a/src/diamonds/__pycache__/registry.cpython-311.pyc b/src/diamonds/__pycache__/registry.cpython-311.pyc deleted file mode 100644 index 950cfebe0825183e3f0b372282ea519343df4129..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1669 zcmcIkO=ufO6rNd)R%@*-w@ECQR<0)@l*$K-(q3#z3njK28Yivn9;%C3Yew-}yIL_b z3bj!olpcEM!GS^orQnm>;6mM7j=l6+Rz?uBU@!z9dK38OQ{Sw961nN2hdyTC@667; zdEc9##>UbJ=(pov-R}|zJ<~>?%${<#3Ccsn5W^nwaS3Cs8=m1ON(rBoNNgv(q;HnY zSSMb}w@Mc1Np3Qek8r%5LWrd}u9(dFhLqAnUb8~j2zYIlUO{>LFTHUdN90pSZRCxJ zu!dich!;2vykj3Zk}pW*`i=?&I5Nw3ZYEYi*tTJKN@=&p?&ze^fgw=zK&264@bW; zn#ShfZ@YT;e-KNs#4ltIPPsogDMreEKCy|K#>IHkfa^+bzq8`pw!>%WrE*zr4n27bQP{XRd)ohDH&P( zOK`6R)x0U7lqkAAZbEALO+4@$LmT(Dc zaq40MeyVXT9bos-X=>upcPzSGxt9^ zBI9k6eM)kNB)7YIa3dtS7MW|4xsc2q6YJZF9lJ$xZIXk)k(~`m_6#;bv38O6s-h}8k?s*Fo{?6#4dPZoXP0b zMVJZ@ThtS~;L9eU+|9UK}0(gpTk%Wr3&+Ea)2RLh=j z+tVF{lON;b%ydW>pS%GKMk}+_&Mbx2(y2WTV6by-TZ2JlVYl1)QQb3Y!*kbr32g@J z+R&H~I)!LdRz2>B+UzrIzI$ zQ>){(W9kN`h1SAHCb#E!=y+xr02+#mAK#yQxYn3kcwj6yK8v$nVA*a=+ju%wzz#d$ zw`6f=IA5kHKU8t>=%TX=LuO6`^hlmv;88uCC^9$yDhDVdy>(VhE`v0 z%8g;_hTA9`BmY{Ys*%ATy(2TSq78RHm1j~<8EMK>q@3NmX_${~X0i}W$G0t(M90E_ zSq|S}rf;!9h|CE&6ERoftQ)jU_wQ2E=bd&tfbjGf*qaUyVRx1-V`6h{6Kp@^v1)&b z=Cxp_tN@mZ#21!=@PXHMZ4dWtYYrd)5IKpJ!5Pf*j^zMQw3RcUq5u(Ntc50Q+Toh; zgo_i5vG{IvEAZ^V_m8rQoTz{ zhqUy3`Q`mcXm^gO`qlU^wDd~TBdYiDM$$?PEOa8m6G8NU!0D}^LQYYUno>g~`;9S^ zuCJxiDk6@j_!ya{^ah5f@SI_Y;LyEm53ykooHp2xouI?rT_(~vBxnNyFJY(xqxcjQ zaN5%sMenc;$F-Rsglr?|_|_~-v4D5PhXV`}Vt9OR9zR7`=Ea8tOhj9h<%9;ffI1gM zGX@t?#Cg%hX(cbCK~$43N4U qeXmDQe1GfZ#TT=QdNB2;u=Mm1X=2}aHvP@#J%Z}<#lM6|-uVZ8cTRBt diff --git a/src/diamonds/__pycache__/train.cpython-313.pyc b/src/diamonds/__pycache__/train.cpython-313.pyc deleted file mode 100644 index dc16216a1e4c59b065e13119fbf8accbaed42d17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1974 zcmZXU&2Jk;6u@V_AGX)uaXy+9+HD1CT+*1T3ACXUfl{?NNmH?1uq2rs?g0U+go*@G%Bja94)jleBjS?CAj~Kgh!3IOT&2Bn;LWVpIWSIU-h1=*&6}Cu zoBdQuM$kU{fEus>KIfcrR#Yl$CzDMjF)6Aml8NpO5!B5iHoUH8mE~oEoMqtoK?^f_EXbpbTy~OR)^I1YF?Gq z#B5AWPM{58gTuqCBWh~CjF1sSXm$8Fn(L>hp!LLhqL6t^^#VtPtA<~LG3#T)c68tJ zeBEo-ZNDH8xmvdjM>h@M02y0`Z|P-ylf>(;VFu<*6I)H}RxQtCh5}ELeb0t#T6L1P zZW;9!{W8!K!8%NVW##3Sg^Nr2)i%piB@DtBP6jc5(qy4$>LIKBZ7r6u2{m!KC;#OTotb3WW-05AacJpSi8I?7FFxrB zS|LKBO#@qw?~$1GfelsS-rS1LY`AN6du=PbOkr1OY*X>wdF4tWg()|fB88y_5rzi? zVPFGciVdbDVEUY3dfzw+9T6KhO&ep10}-1T_FWjlX*zw7Tg1FUV&)B<9Vf|vbg*s9 zBwU$rnj zJ(3={um}Nwj6F&rKos1FHv@&G&d1f6ol}L>PM#%8&Nw40uZNvpALDu@{n`Y<2kYUxoNb MmwG%BCRir_0a(2d5C8xG diff --git a/src/diamonds/data.py b/src/diamonds/data.py index c451186..abe35bb 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -5,6 +5,9 @@ from diamonds.params import DATA_PATH import seaborn as sns from diamonds.model import create_preproc +from diamonds.registry import save_model, load_model + +from sklearn.model_selection import train_test_split logger = loguru.logger @@ -39,14 +42,6 @@ def load_data() -> pd.DataFrame: def clean_data(df: pd.DataFrame) -> pd.DataFrame: - - def keep_not_allow(row): - if 0 in row: - return False - return True - - df_diamonds = df[df.apply(keep_not_allow, axis=1)] - df_diamonds[df_diamonds["x"] == 0] """ Clean the diamonds dataset. @@ -60,11 +55,19 @@ def keep_not_allow(row): pd.DataFrame The cleaned diamonds dataset """ + rows = len(df) + def keep_not_allow(rows): + if 0 in rows.values: + return False + return True - return df_diamonds + df_clean = df[df.apply(keep_not_allow, axis=1)] + logger.info(f"Cleaned the diamonds dataset: {rows} rows -> {len(df_clean)} rows") + + return df_clean -def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: +def preprocess_data(df: pd.DataFrame, train: bool = True) -> pd.DataFrame: """ Preprocess the diamonds dataset. @@ -78,20 +81,22 @@ def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: pd.DataFrame The preprocessed diamonds dataset """ - preprocessor = create_preproc() - df_preprocessed = preprocessor.transform(df) - return df_preprocessed + if train: + preprocessor = create_preproc() + preprocessor.fit(df) + save_model(preprocessor, "preprocessor") + + else: + preprocessor = load_model("preprocessor") + df_preprocessed = preprocessor.transform(df) + logger.info(f"Preprocessed the diamonds dataset: {df.shape} -> {df_preprocessed.shape}") + return df_preprocessed -def create_X_y(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series]: - # Split target first so preprocessing columns only reference feature columns. - X = df.drop(columns="price") - y = df["price"] - num_cols = X.select_dtypes(include="number").columns.tolist() - cat_cols = X.select_dtypes(include=["category", "object"]).columns.tolist() - preprocessor = create_preproc(num_cols, cat_cols) +def create_X_y(df: pd.DataFrame, predict_value: str = "price") -> tuple[pd.DataFrame, pd.Series]: + # Split target first so preprocessing columns only reference feature columns """ Create the feature matrix X and target vector y from the diamonds dataset. @@ -105,17 +110,16 @@ def create_X_y(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series]: (pd.DataFrame, pd.Series) The feature matrix X and target vector y """ - X_transform = preprocessor.fit_transform(X) - X_transform = pd.DataFrame( - X_transform, - columns=preprocessor.get_feature_names_out(), - index=X.index, - ) - return X_transform, y + + X = df.drop(columns=predict_value) + y = df[predict_value] + + return X, y if __name__ == "__main__": df = load_data() - df_clean = clean_data(df) - df_preprocessed = preprocess_data(df_clean) - X, y = create_X_y(df_preprocessed) + df.info() + #df_clean = clean_data(df) + #df_preprocessed = preprocess_data(df_clean) + #X, y = create_X_y(df_preprocessed) diff --git a/src/diamonds/model.py b/src/diamonds/model.py index c2bb337..9ff256e 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -1,6 +1,6 @@ from sklearn.base import BaseEstimator from sklearn.pipeline import Pipeline -from sklearn.compose import ColumnTransformer +from sklearn.compose import ColumnTransformer, make_column_selector from sklearn.preprocessing import OneHotEncoder, StandardScaler from sklearn.impute import SimpleImputer from sklearn.impute import KNNImputer @@ -14,14 +14,19 @@ r2_score, mean_absolute_percentage_error, ) -from diamonds.model import save_model +from diamonds.registry import save_model import pandas as pd import loguru logger = loguru.logger -def create_model(model_name: str) -> BaseEstimator: +def create_model( + model_name: str, + estimators: int = 200, + max_depth: int = 10, + random_state: int = 42 + ) -> BaseEstimator: """ Create an untrained model with the best hyperparameters found during tuning. @@ -39,7 +44,7 @@ def create_model(model_name: str) -> BaseEstimator: models = { "ridge": Ridge(alpha=1.0), "random_forest": RandomForestRegressor( - n_estimators=200, max_depth=10, random_state=42 + n_estimators=estimators, max_depth=max_depth, random_state=random_state ), "knn": KNeighborsRegressor(n_neighbors=5), "linear": LinearRegression(fit_intercept=True), @@ -51,7 +56,7 @@ def create_model(model_name: str) -> BaseEstimator: return models[model_name] -def create_preproc(num_cols: list[str], cat_cols: list[str]) -> Pipeline: +def create_preproc() -> Pipeline: """ Create a preprocessing pipeline. """ @@ -69,13 +74,66 @@ def create_preproc(num_cols: list[str], cat_cols: list[str]) -> Pipeline: ] ) - # combiner les deux - preprocessing = ColumnTransformer( - [("num", num_pipeline, num_cols), ("cat", cat_pipeline, cat_cols)] + preprocessor = ColumnTransformer( + [("numeric",num_pipeline, make_column_selector(dtype_include="number")) + ,("categorical", cat_pipeline, make_column_selector(dtype_exclude="number")) + ]).set_output(transform="pandas") + return preprocessor + + +def create_preproc_with_model() -> ColumnTransformer: + numeric_features = ["carat", "depth", "table", "x", "y", "z"] + categorical_features = ["cut", "color", "clarity"] + + numeric_pipeline = Pipeline([ + ("num_imp", KNNImputer()), + ("scaler", StandardScaler()), + ]) + + categorical_pipeline = Pipeline([ + ("cat_imp", SimpleImputer(strategy="most_frequent")), + ( + "ohe", + OneHotEncoder( + drop="first", + handle_unknown="ignore", + sparse_output=False, + ), + ), + ]) + + preprocessor = ColumnTransformer( + transformers=[ + ("numerical", numeric_pipeline, numeric_features), + ("categorical", categorical_pipeline, categorical_features), + ], + remainder="drop", + verbose_feature_names_out=True, + ) + + return preprocessor + + +def create_training_pipeline( + model_name: str, + estimators: int = 200, + max_depth: int = 10, + random_state: int = 42, +) -> Pipeline: + preprocessor = create_preproc_with_model() + model = create_model( + model_name=model_name, + estimators=estimators, + max_depth=max_depth, + random_state=random_state, ) - return preprocessing + pipeline = Pipeline([ + ("preprocessor", preprocessor), + ("model", model), + ]) + return pipeline def train_model(model, X_train, y_train): """ @@ -90,9 +148,9 @@ def train_model(model, X_train, y_train): y_train : pd.Series The target variable """ - loguru.info("Training model...") + logger.info("Training model...") model.fit(X_train, y_train) - loguru.info("Model trained. Saving...") + logger.info("Model trained. Saving...") save_model(model, "model") @@ -150,3 +208,4 @@ def predict(model, X: pd.DataFrame) -> pd.Series: y_pred = model.predict(X) return pd.Series(y_pred, index=X.index, name="prediction") + diff --git a/src/diamonds/train.py b/src/diamonds/train.py index dcd0ff3..4dc32a4 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -1,15 +1,23 @@ import os -from diamonds.data import load_data, clean_data, preprocess_data, create_X_y -from diamonds.model import create_model, train_model, evaluate_model +from diamonds.data import (load_data, clean_data, preprocess_data, create_X_y) +from diamonds.model import create_training_pipeline, create_model, train_model, evaluate_model from sklearn.model_selection import train_test_split -from diamonds.registry import save_model -from diamonds.params import MODEL_PATH +from sklearn.metrics import ( + mean_absolute_error, + mean_squared_error, + r2_score, + mean_absolute_percentage_error, +) +from diamonds.data import load_data +import random +import mlflow def train( model_name: str = "baseline", test_size: float = 0.2, random_state: int = 42, + ) -> None: """ Simple end‑to‑end pipeline: @@ -23,31 +31,61 @@ def train( # 1) Data df = load_data() df_clean = clean_data(df) - df_preprocessed = preprocess_data(df_clean) - X, y = create_X_y(df_preprocessed) - - X_train, X_test, y_train, y_test = train_test_split( - X, - y, - test_size=test_size, - random_state=random_state, - ) - # 2) Model + preprocessing - resolved_model_name = "linear" if model_name == "baseline" else model_name - model = create_model(resolved_model_name) - trained_model = train_model(model, X_train, y_train) + X, y = create_X_y(df_clean) + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=random_state) + X_train_preproc = preprocess_data(X_train, train=True) + X_test_preproc = preprocess_data(X_test, train=False) + model = create_model(model_name) + train_model(model, X_train_preproc, y_train) # 3) Evaluation - evaluate_model(trained_model, X_test, y_test) + evaluate_model(model, X_test_preproc, y_test) + + +def autolog_mlflow( + model_name: str = "random_forest", + test_size: float = 0.2, + random_state: int = 42, +): + # 1. Set the tracking URI to the MLflow server + mlflow.set_tracking_uri("http://localhost:5000") + # 2. Set the Experiment name + mlflow.set_experiment("Diamonds_experiment") + mlflow.autolog(log_input_examples=True) + n_estimators = random.randint(50, 200) # Randomly choose n_estimators for demonstration + depth = random.randint(5, 20) + # 1) Data + df = load_data() + df_clean = clean_data(df) + # 2) Model + preprocessing + X, y = create_X_y(df_clean) + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=random_state) + pipeline = create_training_pipeline( + model_name=model_name, + estimators=n_estimators, + max_depth=depth, + random_state=random_state, + ) + with mlflow.start_run(): + pipeline.fit(X_train, y_train) + y_pred = pipeline.predict(X_test) + mae = mean_absolute_error(y_test, y_pred) + rmse = mean_squared_error(y_test, y_pred) ** 0.5 + r2 = r2_score(y_test, y_pred) - # 4) Persistence - model_dir = os.path(MODEL_PATH) - model_dir.mkdir(parents=True, exist_ok=True) - model_path = model_dir / f"{resolved_model_name}.joblib" - saved_path = save_model(trained_model, model_path) - print(f"Model saved to: {saved_path}") + mlflow.log_metric("mae", mae) + mlflow.log_metric("rmse", rmse) + mlflow.log_metric("r2", r2) + print(f"Model: {model_name}") + print(f"n_estimators: {n_estimators}") + print(f"max_depth: {depth}") + print(f"MAE: {mae:.2f}") + print(f"RMSE: {rmse:.2f}") + print(f"R2: {r2:.4f}") + return pipeline if __name__ == "__main__": - train() + autolog_mlflow() + #train("random_forest") From ea2dd1c95cf5b22813e3a35b0b0a16feccec16ce Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Wed, 11 Mar 2026 01:53:54 +0000 Subject: [PATCH 14/20] update gitignore for pycache and mlflow artifacts --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 84c65a6..5c41d19 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,7 @@ models/ .env .envrc -.mlartifacts/ -.mlflow.db \ No newline at end of file +# MLflow +mlartifacts/ +mlruns/ +mlflow.db \ No newline at end of file From c08993ada16c5f1782378bf4f052d4018e05a2a0 Mon Sep 17 00:00:00 2001 From: asticotcoco Date: Wed, 11 Mar 2026 08:03:56 +0000 Subject: [PATCH 15/20] modifs --- .mlflow.pid | 1 + src/diamonds/data.py | 11 +++++++++-- src/diamonds/model.py | 11 +++++++++-- src/diamonds/train.py | 19 ++++++++++++++++--- 4 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 .mlflow.pid diff --git a/.mlflow.pid b/.mlflow.pid new file mode 100644 index 0000000..b817fd5 --- /dev/null +++ b/.mlflow.pid @@ -0,0 +1 @@ +78638 diff --git a/src/diamonds/data.py b/src/diamonds/data.py index cf37c19..673144e 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -1,7 +1,7 @@ # Import other necessary libraries here import os +import logging import pandas as pd -import loguru from diamonds.params import DATA_PATH import seaborn as sns from diamonds.model import create_preproc @@ -9,7 +9,14 @@ from sklearn.model_selection import train_test_split -logger = loguru.logger +try: + import loguru + + logger = loguru.logger +except ModuleNotFoundError: + logger = logging.getLogger(__name__) + if not logger.handlers: + logging.basicConfig(level=logging.INFO) df_diamonds = sns.load_dataset("diamonds") diff --git a/src/diamonds/model.py b/src/diamonds/model.py index 6a16883..4d01250 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -1,3 +1,4 @@ +import logging from sklearn.base import BaseEstimator from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer, make_column_selector @@ -16,9 +17,15 @@ ) from diamonds.registry import save_model import pandas as pd -import loguru -logger = loguru.logger +try: + import loguru + + logger = loguru.logger +except ModuleNotFoundError: + logger = logging.getLogger(__name__) + if not logger.handlers: + logging.basicConfig(level=logging.INFO) def create_model( diff --git a/src/diamonds/train.py b/src/diamonds/train.py index 4dc32a4..8c2d2cc 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -10,7 +10,11 @@ ) from diamonds.data import load_data import random -import mlflow + +try: + import mlflow +except ModuleNotFoundError: + mlflow = None def train( @@ -48,6 +52,12 @@ def autolog_mlflow( test_size: float = 0.2, random_state: int = 42, ): + if mlflow is None: + raise ModuleNotFoundError( + "mlflow is not installed in the active Python interpreter. " + "Install mlflow or run train() without experiment tracking." + ) + # 1. Set the tracking URI to the MLflow server mlflow.set_tracking_uri("http://localhost:5000") # 2. Set the Experiment name @@ -87,5 +97,8 @@ def autolog_mlflow( return pipeline if __name__ == "__main__": - autolog_mlflow() - #train("random_forest") + if mlflow is None: + print("mlflow not found in this interpreter. Running training without tracking.") + train("random_forest") + else: + autolog_mlflow() From 1ac407ba9aa134de747a2efdc49a3ffb7598ca41 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Wed, 11 Mar 2026 11:27:20 +0000 Subject: [PATCH 16/20] clean a bit the code and add CI to check linter when pushing --- .env copy | 2 +- .github/workflows/ci.yml | 30 ++++++++++++ Makefile | 4 +- src/diamonds/data.py | 14 +++++- src/diamonds/model.py | 98 +++++++++++++++------------------------- src/diamonds/params.py | 1 + src/diamonds/registry.py | 27 +++++++++-- src/diamonds/train.py | 43 ++++++++++++------ 8 files changed, 133 insertions(+), 86 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.env copy b/.env copy index 5f89edb..d94bec1 100644 --- a/.env copy +++ b/.env copy @@ -1 +1 @@ -MODEL_REGISTRY = "local" \ No newline at end of file +MODEL_REGISTRY = "local" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d07a376 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI + +on: + push: + branches: + - main + - master + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: code checkout + uses: actions/checkout@v4 + + - name: isntall Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install poetry + run: pip install poetry + + - name: Install dependencies + run: poetry install + + - name: launch Makefile + run: make lint-all \ No newline at end of file diff --git a/Makefile b/Makefile index 6c22cf1..c0fa2b9 100644 --- a/Makefile +++ b/Makefile @@ -12,14 +12,14 @@ format: @echo "checking format" poetry run ruff format . -lint-all: lint lint-fix format +lint-all: lint-fix lint format .PHONY: start-mlflow stop-mlflow MLFLOW_PORT=5000 MLFLOW_PID_FILE=.mlflow.pid start-mlflow: - mlflow ui --port $(MLFLOW_PORT) & echo $$! > $(MLFLOW_PID_FILE) + mlflow ui --backend-store-uri sqlite:///models/mlflow.db -port $(MLFLOW_PORT) & echo $$! > $(MLFLOW_PID_FILE) stop-mlflow: @if [ -f $(MLFLOW_PID_FILE) ]; then \ diff --git a/src/diamonds/data.py b/src/diamonds/data.py index 673144e..9c306b9 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -1,13 +1,22 @@ # Import other necessary libraries here import os +<<<<<<< HEAD import logging import pandas as pd from diamonds.params import DATA_PATH import seaborn as sns from diamonds.model import create_preproc from diamonds.registry import save_model, load_model +======= +>>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) -from sklearn.model_selection import train_test_split +import loguru +import pandas as pd +import seaborn as sns + +from diamonds.model import create_preproc +from diamonds.params import DATA_PATH +from diamonds.registry import load_model, save_model try: import loguru @@ -63,6 +72,7 @@ def clean_data(df: pd.DataFrame) -> pd.DataFrame: The cleaned diamonds dataset """ rows = len(df) + def keep_not_allow(rows): if 0 in rows.values: return False @@ -98,7 +108,7 @@ def preprocess_data(df: pd.DataFrame, train: bool = True) -> pd.DataFrame: preprocessor = load_model("preprocessor") df_preprocessed = preprocessor.transform(df) - logger.info(f"Preprocessed the diamonds dataset: {df.shape} -> {df_preprocessed.shape}") + logger.info(f"Preprocessed the diamonds dataset: {df.shape} -> {df_preprocessed.shape}") return df_preprocessed diff --git a/src/diamonds/model.py b/src/diamonds/model.py index 4d01250..00c95d9 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -1,22 +1,29 @@ +<<<<<<< HEAD import logging +======= +import loguru +import pandas as pd +>>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) from sklearn.base import BaseEstimator -from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer, make_column_selector -from sklearn.preprocessing import OneHotEncoder, StandardScaler -from sklearn.impute import SimpleImputer -from sklearn.impute import KNNImputer -from sklearn.linear_model import Ridge from sklearn.ensemble import RandomForestRegressor -from sklearn.neighbors import KNeighborsRegressor -from sklearn.linear_model import LinearRegression +from sklearn.impute import KNNImputer, SimpleImputer +from sklearn.linear_model import LinearRegression, Ridge from sklearn.metrics import ( mean_absolute_error, + mean_absolute_percentage_error, mean_squared_error, r2_score, - mean_absolute_percentage_error, ) +from sklearn.neighbors import KNeighborsRegressor +from sklearn.pipeline import Pipeline +from sklearn.preprocessing import OneHotEncoder, StandardScaler + from diamonds.registry import save_model +<<<<<<< HEAD import pandas as pd +======= +>>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) try: import loguru @@ -29,11 +36,8 @@ def create_model( - model_name: str, - estimators: int = 200, - max_depth: int = 10, - random_state: int = 42 - ) -> BaseEstimator: + model_name: str, estimators: int = 200, max_depth: int = 10, random_state: int = 42 +) -> BaseEstimator: """ Create an untrained model with the best hyperparameters found during tuning. @@ -63,60 +67,28 @@ def create_model( return models[model_name] -def create_preproc() -> Pipeline: - """ - Create a preprocessing pipeline. - """ +def create_preproc(): - # pipeline numérique num_pipeline = Pipeline( - [("num_imp", KNNImputer(n_neighbors=5)), ("scaler", StandardScaler())] + [ + ("num_imp", KNNImputer()), + ("scaler", StandardScaler()), + ] ) - # pipeline catégorique cat_pipeline = Pipeline( [ ("cat_imp", SimpleImputer(strategy="most_frequent")), - ("ohe", OneHotEncoder(drop="first", sparse_output=False)), + ("ohe", OneHotEncoder(drop="first", handle_unknown="ignore", sparse_output=False)), ] ) preprocessor = ColumnTransformer( - [("numeric",num_pipeline, make_column_selector(dtype_include="number")) - ,("categorical", cat_pipeline, make_column_selector(dtype_exclude="number")) - ]).set_output(transform="pandas") - return preprocessor - - -def create_preproc_with_model() -> ColumnTransformer: - numeric_features = ["carat", "depth", "table", "x", "y", "z"] - categorical_features = ["cut", "color", "clarity"] - - numeric_pipeline = Pipeline([ - ("num_imp", KNNImputer()), - ("scaler", StandardScaler()), - ]) - - categorical_pipeline = Pipeline([ - ("cat_imp", SimpleImputer(strategy="most_frequent")), - ( - "ohe", - OneHotEncoder( - drop="first", - handle_unknown="ignore", - sparse_output=False, - ), - ), - ]) - - preprocessor = ColumnTransformer( - transformers=[ - ("numerical", numeric_pipeline, numeric_features), - ("categorical", categorical_pipeline, categorical_features), - ], - remainder="drop", - verbose_feature_names_out=True, - ) + [ + ("numeric", num_pipeline, make_column_selector(dtype_include="number")), + ("categorical", cat_pipeline, make_column_selector(dtype_exclude="number")), + ] + ).set_output(transform="pandas") return preprocessor @@ -127,7 +99,7 @@ def create_training_pipeline( max_depth: int = 10, random_state: int = 42, ) -> Pipeline: - preprocessor = create_preproc_with_model() + preprocessor = create_preproc() model = create_model( model_name=model_name, estimators=estimators, @@ -135,13 +107,16 @@ def create_training_pipeline( random_state=random_state, ) - pipeline = Pipeline([ - ("preprocessor", preprocessor), - ("model", model), - ]) + pipeline = Pipeline( + [ + ("preprocessor", preprocessor), + ("model", model), + ] + ) return pipeline + def train_model(model, X_train, y_train): """ Train model and save it. @@ -216,4 +191,3 @@ def predict(model, X: pd.DataFrame) -> pd.Series: y_pred = model.predict(X) return pd.Series(y_pred, index=X.index, name="prediction") - diff --git a/src/diamonds/params.py b/src/diamonds/params.py index fb75875..e240dbc 100644 --- a/src/diamonds/params.py +++ b/src/diamonds/params.py @@ -4,3 +4,4 @@ MODEL_PATH = "models" MODEL_REGISTRY = os.environ.get("MODEL_REGISTRY", "local") +MLFLOW_TRACKING_URI = os.environ.get("MLFLOW_TRACKING_URI", "http://localhost:5000") diff --git a/src/diamonds/registry.py b/src/diamonds/registry.py index b5ea786..9a3fe4f 100644 --- a/src/diamonds/registry.py +++ b/src/diamonds/registry.py @@ -1,18 +1,35 @@ -import pickle import os +import pickle + +import loguru +import mlflow from sklearn.base import BaseEstimator + from diamonds.params import MODEL_PATH +logger = loguru.logger + -def save_model(model: BaseEstimator, name: str): +def save_model(model: BaseEstimator, name: str, model_registry: str = "local") -> None: """Save a trained model to disk and return its path.""" model_path = os.path.join(MODEL_PATH, f"{name}.pkl") with open(model_path, "wb") as f: pickle.dump(model, f) + if model_registry == "mlflow": + mlflow.sklearn.log_model(model, name) + logger.info(f"Model saved to MLflow registry with name: {name}") -def load_model(name: str) -> BaseEstimator: +def load_model(name: str, model_registry: str = "local") -> BaseEstimator: """Load a previously saved model from disk.""" model_path = os.path.join(MODEL_PATH, f"{name}.pkl") - with open(model_path, "rb") as f: - return pickle.load(f) + if model_registry == "mlflow": + model_uri = f"models:/{name}/latest" + model = mlflow.sklearn.load_model(model_uri) + logger.info(f"Model loaded from MLflow registry with name: {name}") + else: + with open(model_path, "rb") as f: + model = pickle.load(f) + logger.info(f"Model loaded from disk with name: {name}") + + return model diff --git a/src/diamonds/train.py b/src/diamonds/train.py index 8c2d2cc..8ea9e36 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -1,13 +1,12 @@ -import os -from diamonds.data import (load_data, clean_data, preprocess_data, create_X_y) -from diamonds.model import create_training_pipeline, create_model, train_model, evaluate_model -from sklearn.model_selection import train_test_split +import random + +import mlflow from sklearn.metrics import ( mean_absolute_error, mean_squared_error, r2_score, - mean_absolute_percentage_error, ) +<<<<<<< HEAD from diamonds.data import load_data import random @@ -15,13 +14,19 @@ import mlflow except ModuleNotFoundError: mlflow = None +======= +from sklearn.model_selection import train_test_split + +from diamonds.data import clean_data, create_X_y, load_data, preprocess_data +from diamonds.model import create_model, create_training_pipeline, evaluate_model, train_model +from diamonds.params import MLFLOW_TRACKING_URI +>>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) def train( model_name: str = "baseline", test_size: float = 0.2, random_state: int = 42, - ) -> None: """ Simple end‑to‑end pipeline: @@ -37,7 +42,9 @@ def train( df_clean = clean_data(df) # 2) Model + preprocessing X, y = create_X_y(df_clean) - X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=random_state) + X_train, X_test, y_train, y_test = train_test_split( + X, y, test_size=test_size, random_state=random_state + ) X_train_preproc = preprocess_data(X_train, train=True) X_test_preproc = preprocess_data(X_test, train=False) @@ -59,23 +66,25 @@ def autolog_mlflow( ) # 1. Set the tracking URI to the MLflow server - mlflow.set_tracking_uri("http://localhost:5000") + mlflow.set_tracking_uri(MLFLOW_TRACKING_URI) # 2. Set the Experiment name mlflow.set_experiment("Diamonds_experiment") mlflow.autolog(log_input_examples=True) n_estimators = random.randint(50, 200) # Randomly choose n_estimators for demonstration - depth = random.randint(5, 20) + depth = random.randint(5, 20) # 1) Data df = load_data() df_clean = clean_data(df) # 2) Model + preprocessing X, y = create_X_y(df_clean) - X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=random_state) + X_train, X_test, y_train, y_test = train_test_split( + X, y, test_size=test_size, random_state=random_state + ) pipeline = create_training_pipeline( - model_name=model_name, - estimators=n_estimators, - max_depth=depth, - random_state=random_state, + model_name=model_name, + estimators=n_estimators, + max_depth=depth, + random_state=random_state, ) with mlflow.start_run(): pipeline.fit(X_train, y_train) @@ -96,9 +105,15 @@ def autolog_mlflow( print(f"R2: {r2:.4f}") return pipeline + if __name__ == "__main__": +<<<<<<< HEAD if mlflow is None: print("mlflow not found in this interpreter. Running training without tracking.") train("random_forest") else: autolog_mlflow() +======= + autolog_mlflow() + # train("random_forest") +>>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) From c6def8362dfcbf3c4c499e8ca367ec54be88558d Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Wed, 11 Mar 2026 11:35:20 +0000 Subject: [PATCH 17/20] add action in github ci --- .github/workflows/ci.yml | 1 + src/diamonds/train.py | 15 --------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d07a376..98a9c19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ name: CI on: push: branches: + - 0-Starter-productionizing-ml - main - master pull_request: diff --git a/src/diamonds/train.py b/src/diamonds/train.py index 8ea9e36..b1739fa 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -6,21 +6,11 @@ mean_squared_error, r2_score, ) -<<<<<<< HEAD -from diamonds.data import load_data -import random - -try: - import mlflow -except ModuleNotFoundError: - mlflow = None -======= from sklearn.model_selection import train_test_split from diamonds.data import clean_data, create_X_y, load_data, preprocess_data from diamonds.model import create_model, create_training_pipeline, evaluate_model, train_model from diamonds.params import MLFLOW_TRACKING_URI ->>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) def train( @@ -107,13 +97,8 @@ def autolog_mlflow( if __name__ == "__main__": -<<<<<<< HEAD if mlflow is None: print("mlflow not found in this interpreter. Running training without tracking.") train("random_forest") else: autolog_mlflow() -======= - autolog_mlflow() - # train("random_forest") ->>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) From a33020696d613671d561fc76059bb04a98bf2370 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Wed, 11 Mar 2026 11:46:07 +0000 Subject: [PATCH 18/20] fix data conflict stash --- src/diamonds/data.py | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/diamonds/data.py b/src/diamonds/data.py index 9c306b9..a81bfa7 100644 --- a/src/diamonds/data.py +++ b/src/diamonds/data.py @@ -1,14 +1,5 @@ # Import other necessary libraries here import os -<<<<<<< HEAD -import logging -import pandas as pd -from diamonds.params import DATA_PATH -import seaborn as sns -from diamonds.model import create_preproc -from diamonds.registry import save_model, load_model -======= ->>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) import loguru import pandas as pd @@ -18,17 +9,9 @@ from diamonds.params import DATA_PATH from diamonds.registry import load_model, save_model -try: - import loguru - - logger = loguru.logger -except ModuleNotFoundError: - logger = logging.getLogger(__name__) - if not logger.handlers: - logging.basicConfig(level=logging.INFO) - df_diamonds = sns.load_dataset("diamonds") +logger = loguru.logger def load_data() -> pd.DataFrame: df_diamonds = sns.load_dataset("diamonds") From da06cb9ca81fd0ea2a608a00ad8e84073938f3a5 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Wed, 11 Mar 2026 11:57:33 +0000 Subject: [PATCH 19/20] fix model conflict stash --- src/diamonds/model.py | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/diamonds/model.py b/src/diamonds/model.py index 00c95d9..f75a2f0 100644 --- a/src/diamonds/model.py +++ b/src/diamonds/model.py @@ -1,9 +1,5 @@ -<<<<<<< HEAD -import logging -======= import loguru import pandas as pd ->>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) from sklearn.base import BaseEstimator from sklearn.compose import ColumnTransformer, make_column_selector from sklearn.ensemble import RandomForestRegressor @@ -20,20 +16,8 @@ from sklearn.preprocessing import OneHotEncoder, StandardScaler from diamonds.registry import save_model -<<<<<<< HEAD -import pandas as pd -======= ->>>>>>> 848d30b (clean a bit the code and add CI to check linter when pushing) - -try: - import loguru - - logger = loguru.logger -except ModuleNotFoundError: - logger = logging.getLogger(__name__) - if not logger.handlers: - logging.basicConfig(level=logging.INFO) +logger = loguru.logger def create_model( model_name: str, estimators: int = 200, max_depth: int = 10, random_state: int = 42 From fb5c2b22181be18d5f280a8916c6d6c50b89a039 Mon Sep 17 00:00:00 2001 From: yufo fukuda Date: Tue, 24 Mar 2026 13:44:07 +0000 Subject: [PATCH 20/20] updated diamonds api --- api/data_model.py | 18 ++++++++++++++++++ api/rest.py | 23 +++++++++++++++++++++++ src/diamonds/registry.py | 3 +-- src/diamonds/train.py | 34 +++++++++++++++++++--------------- 4 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 api/data_model.py create mode 100644 api/rest.py diff --git a/api/data_model.py b/api/data_model.py new file mode 100644 index 0000000..483b587 --- /dev/null +++ b/api/data_model.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel + +class Diamond(BaseModel): + carat: float + cut: str + color: str + clarity: str + depth: float + table: float + x: float + y: float + z: float + +class DiamondResponse(Diamond): + price: float + +class Diamonds(BaseModel): + diamonds: list[Diamond] \ No newline at end of file diff --git a/api/rest.py b/api/rest.py new file mode 100644 index 0000000..dc1c9d1 --- /dev/null +++ b/api/rest.py @@ -0,0 +1,23 @@ +import pandas as pd +from fastapi import FastAPI +from src.diamonds.registry import load_model +from .data_model import Diamond, DiamondResponse + +app = FastAPI( + title="Diamond API", + description="api to get diamond price", + version="0.1.0" +) + +model = load_model("model", "local") + +@app.get("/") +def read_root(): + return {"Hello": "World"} + +@app.post("/price") +def predict_price(diamond: Diamond): + diamond_df = pd.Dataframe([diamond.model_dump()]) + prediction = model.predict(diamond_df) + diamond_reponse = DiamondResponse(**diamond.model_dump(), price=prediction[0]) + return diamond_reponse \ No newline at end of file diff --git a/src/diamonds/registry.py b/src/diamonds/registry.py index 9a3fe4f..12a872c 100644 --- a/src/diamonds/registry.py +++ b/src/diamonds/registry.py @@ -9,7 +9,6 @@ logger = loguru.logger - def save_model(model: BaseEstimator, name: str, model_registry: str = "local") -> None: """Save a trained model to disk and return its path.""" model_path = os.path.join(MODEL_PATH, f"{name}.pkl") @@ -30,6 +29,6 @@ def load_model(name: str, model_registry: str = "local") -> BaseEstimator: else: with open(model_path, "rb") as f: model = pickle.load(f) - logger.info(f"Model loaded from disk with name: {name}") + logger.info(f"Model loaded from local with name: {name}") return model diff --git a/src/diamonds/train.py b/src/diamonds/train.py index b1739fa..c3a8e40 100644 --- a/src/diamonds/train.py +++ b/src/diamonds/train.py @@ -1,5 +1,5 @@ import random - +import pandas as pd import mlflow from sklearn.metrics import ( mean_absolute_error, @@ -13,7 +13,8 @@ from diamonds.params import MLFLOW_TRACKING_URI -def train( +def train_from_raw_data( + raw_data : pd.DataFrame = load_data, model_name: str = "baseline", test_size: float = 0.2, random_state: int = 42, @@ -21,27 +22,30 @@ def train( """ Simple end‑to‑end pipeline: - - load and clean the raw data + - clean the raw data - preprocess it and build X, y - split into train / test - build the model and preprocessing - train, evaluate, and save the trained model """ - # 1) Data - df = load_data() - df_clean = clean_data(df) - # 2) Model + preprocessing + n_estimators = random.randint(50, 200) # Randomly choose n_estimators for demonstration + depth = random.randint(5, 20) + # 1) Clean data + df_clean = clean_data(raw_data) + # 2) Preprocess data X, y = create_X_y(df_clean) - X_train, X_test, y_train, y_test = train_test_split( + X_train, _, y_train, _ = train_test_split( X, y, test_size=test_size, random_state=random_state ) - X_train_preproc = preprocess_data(X_train, train=True) - X_test_preproc = preprocess_data(X_test, train=False) - model = create_model(model_name) - train_model(model, X_train_preproc, y_train) - # 3) Evaluation - evaluate_model(model, X_test_preproc, y_test) + pipeline = create_training_pipeline( + model_name=model_name, + estimators=n_estimators, + max_depth=depth, + random_state=random_state, + ) + # 3) Train model + train_model(pipeline, X_train, y_train) def autolog_mlflow( @@ -99,6 +103,6 @@ def autolog_mlflow( if __name__ == "__main__": if mlflow is None: print("mlflow not found in this interpreter. Running training without tracking.") - train("random_forest") + train_from_raw_data(raw_data=load_data(), model_name="random_forest") else: autolog_mlflow()