Reupload (purge)

This commit is contained in:
gauvainboiche
2026-08-04 16:42:35 +02:00
commit bb74ba5173
1023 changed files with 79600 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
3.12
View File
+5
View File
@@ -0,0 +1,5 @@
prenom = "Alice"
nom = "Dupont"
age = 30
print(prenom)
+9
View File
@@ -0,0 +1,9 @@
[project]
name = "bases"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"requests>=2.32.5",
]
+113
View File
@@ -0,0 +1,113 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "bases"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "requests" },
]
[package.metadata]
requires-dist = [{ name = "requests", specifier = ">=2.32.5" }]
[[package]]
name = "certifi"
version = "2026.1.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" },
]
[[package]]
name = "charset-normalizer"
version = "3.4.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" },
{ url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" },
{ url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" },
{ url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" },
{ url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" },
{ url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" },
{ url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" },
{ url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" },
{ url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" },
{ url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" },
{ url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" },
{ url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" },
{ url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" },
{ url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" },
{ url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" },
{ url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" },
{ url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" },
{ url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" },
{ url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" },
{ url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" },
{ url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" },
{ url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" },
{ url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" },
{ url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" },
{ url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" },
{ url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" },
{ url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" },
{ url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" },
{ url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" },
{ url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" },
{ url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" },
{ url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" },
{ url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" },
{ url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" },
{ url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" },
{ url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" },
{ url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" },
{ url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" },
{ url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" },
{ url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" },
{ url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" },
{ url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" },
{ url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" },
{ url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" },
{ url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" },
{ url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" },
{ url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
]
[[package]]
name = "idna"
version = "3.11"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
]
[[package]]
name = "requests"
version = "2.32.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "charset-normalizer" },
{ name = "idna" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
]
[[package]]
name = "urllib3"
version = "2.6.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" },
]
+1
View File
@@ -0,0 +1 @@
3.12
View File
+26
View File
@@ -0,0 +1,26 @@
[
{
"Title": "LSDA",
"Author": "Tolkien"
},
{
"Title": "1984",
"Author": "Orwell"
},
{
"Title": "La voie des rois",
"Author": "Brendan Sanderson"
},
{
"Title": "Justici\u00e8re",
"Author": "Brendan Sanderson"
},
{
"Title": "Jus d'abricot",
"Author": "COCKTAILS"
},
{
"Title": "Jugement et trahison",
"Author": "Alan O'Reilly"
}
]
+92
View File
@@ -0,0 +1,92 @@
import json
class Book:
def __init__(self, title: str, author: str):
self.title = title
self.author = author
def __repr__(self):
return f"{self.title} de {self.author}"
def __eq__(self, other: "Book"):
"""Pour comparer un objet de classe à un autre au lieu de l'ID par défaut"""
return self.title == other.title and self.author == other.author
def __gt__(self, other: "Book"):
return self.title > other.title
def __lt__(self, other: "Book"):
return self.title.lower() < other.title.lower()
def serialized(self):
"""Converti la classe en dictionnaire JSONable"""
return {"Title": self.title, "Author": self.author}
@classmethod
def deserialized(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe Book"""
return cls(title= dictionnary["Title"], author= dictionnary["Author"])
class Library:
"""Gère un contenu de livres"""
def __init__(self, name: str):
self.name = name
self.books = self.load()
def add_new_book(self, book: Book):
"""Ajoute un nouveau livre"""
if book in self.books:
return f"{book.title.capitalize()} y est déjà."
self.books.append(book)
self.save()
return f"{book.title.capitalize()} a été ajouté."
def take_out_book(self, book_name: str):
"""Retire un livre déjà présent"""
for book in self.books:
if book.title.lower() == book_name.lower():
self.books.remove(book)
self.save()
return f"{book.title.capitalize()} a été retiré."
return f"{book.title.capitalize()} n'y est pas."
def list_books_in_list(self):
"""Liste les livres présents"""
return self.books
def sort_books_by_name(self):
"""Tri les livres par ordre alphabétique"""
self.books.sort()
def display_number_of_books(self) -> int:
"""Donne le nombre de livres présents"""
return len(self.books)
def search_book_by_word(self, word: str):
"""Cherche un livre par mot de départ"""
results = []
for book in self.books:
if word.lower() in book.title.lower():
results.append(book)
return results if len(results) > 0 else "Pas de résultat."
def search_book_by_letter(self, letter: str):
"""Cherche un livre par lettre de départ"""
results = []
for book in self.books:
if book.title.lower().startswith(letter.lower()):
results.append(book)
return results if len(results) > 0 else "Pas de résultat."
# Sauvegarde des livres dans un JSON pour persistance des données
def save(self):
"""Inscris dans un fichier JSON le contenu de la bibliothèque"""
book_dict = [book.serialized() for book in self.books]
with open("books.json", "w", encoding= "utf-8") as json_file: # a pour append, w pour write
json.dump(book_dict, json_file, indent= 4)
def load(self) -> list[Book]:
"""Récupère le contenu d'un fichier JSON"""
with open("books.json", encoding= "utf-8") as json_file:
return json.load(json_file, object_hook= Book.deserialized)
+167
View File
@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>520</width>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
<string>Bibliothèque - Python</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTabWidget" name="tabWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>480</width>
<height>210</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
<widget class="QWidget" name="tab_add_book">
<attribute name="title">
<string>Ajouter Livre</string>
</attribute>
<widget class="QLineEdit" name="title_input">
<property name="geometry">
<rect>
<x>140</x>
<y>40</y>
<width>320</width>
<height>20</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="title_lb">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>100</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Titre</string>
</property>
</widget>
<widget class="QLineEdit" name="author_input">
<property name="geometry">
<rect>
<x>140</x>
<y>80</y>
<width>320</width>
<height>20</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="author_lb">
<property name="geometry">
<rect>
<x>20</x>
<y>80</y>
<width>100</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Auteur</string>
</property>
</widget>
<widget class="QPushButton" name="save_btn">
<property name="geometry">
<rect>
<x>140</x>
<y>120</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Enregistrer</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab_search">
<attribute name="title">
<string>Recherche</string>
</attribute>
<widget class="QListView" name="results_view">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>430</width>
<height>100</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="search_lb">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>181</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Recherche (par mot ou lettre)</string>
</property>
</widget>
<widget class="QLineEdit" name="search_input">
<property name="geometry">
<rect>
<x>210</x>
<y>20</y>
<width>240</width>
<height>20</height>
</rect>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab_delete">
<attribute name="title">
<string>Supprimer</string>
</attribute>
<widget class="QPushButton" name="delete_btn">
<property name="geometry">
<rect>
<x>360</x>
<y>50</y>
<width>100</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>Supprimer</string>
</property>
</widget>
<widget class="QComboBox" name="title_list">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>320</width>
<height>20</height>
</rect>
</property>
</widget>
</widget>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>
+15
View File
@@ -0,0 +1,15 @@
from typing import TYPE_CHECKING
from PyQt6.QtCore import QObject, pyqtSignal
if TYPE_CHECKING:
from gui.ui_library import Ui_Library
class SignalManagement(QObject):
change_list_signal = pyqtSignal()
def __init__(self, ui):
super().__init__()
self.ui = ui
def connect_signals(self):
self.change_list_signal.connect(self.ui.refresh_title_list)
+77
View File
@@ -0,0 +1,77 @@
# Form implementation generated from reading ui file '.\gui\library.ui'
#
# Created by: PyQt6 UI code generator 6.10.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(520, 250)
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tabWidget = QtWidgets.QTabWidget(parent=self.centralwidget)
self.tabWidget.setGeometry(QtCore.QRect(20, 20, 480, 210))
self.tabWidget.setElideMode(QtCore.Qt.TextElideMode.ElideNone)
self.tabWidget.setObjectName("tabWidget")
self.tab_add_book = QtWidgets.QWidget()
self.tab_add_book.setObjectName("tab_add_book")
self.title_input = QtWidgets.QLineEdit(parent=self.tab_add_book)
self.title_input.setGeometry(QtCore.QRect(140, 40, 320, 20))
self.title_input.setObjectName("title_input")
self.title_lb = QtWidgets.QLabel(parent=self.tab_add_book)
self.title_lb.setGeometry(QtCore.QRect(20, 40, 100, 20))
self.title_lb.setObjectName("title_lb")
self.author_input = QtWidgets.QLineEdit(parent=self.tab_add_book)
self.author_input.setGeometry(QtCore.QRect(140, 80, 320, 20))
self.author_input.setObjectName("author_input")
self.author_lb = QtWidgets.QLabel(parent=self.tab_add_book)
self.author_lb.setGeometry(QtCore.QRect(20, 80, 100, 20))
self.author_lb.setObjectName("author_lb")
self.save_btn = QtWidgets.QPushButton(parent=self.tab_add_book)
self.save_btn.setGeometry(QtCore.QRect(140, 120, 111, 41))
self.save_btn.setObjectName("save_btn")
self.tabWidget.addTab(self.tab_add_book, "")
self.tab_search = QtWidgets.QWidget()
self.tab_search.setObjectName("tab_search")
self.results_view = QtWidgets.QListView(parent=self.tab_search)
self.results_view.setGeometry(QtCore.QRect(20, 60, 430, 100))
self.results_view.setObjectName("results_view")
self.search_lb = QtWidgets.QLabel(parent=self.tab_search)
self.search_lb.setGeometry(QtCore.QRect(20, 20, 181, 16))
self.search_lb.setObjectName("search_lb")
self.search_input = QtWidgets.QLineEdit(parent=self.tab_search)
self.search_input.setGeometry(QtCore.QRect(210, 20, 240, 20))
self.search_input.setObjectName("search_input")
self.tabWidget.addTab(self.tab_search, "")
self.tab_delete = QtWidgets.QWidget()
self.tab_delete.setObjectName("tab_delete")
self.delete_btn = QtWidgets.QPushButton(parent=self.tab_delete)
self.delete_btn.setGeometry(QtCore.QRect(360, 50, 100, 40))
self.delete_btn.setObjectName("delete_btn")
self.title_list = QtWidgets.QComboBox(parent=self.tab_delete)
self.title_list.setGeometry(QtCore.QRect(20, 60, 320, 20))
self.title_list.setObjectName("title_list")
self.tabWidget.addTab(self.tab_delete, "")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Bibliothèque - Python"))
self.title_lb.setText(_translate("MainWindow", "Titre"))
self.author_lb.setText(_translate("MainWindow", "Auteur"))
self.save_btn.setText(_translate("MainWindow", "Enregistrer"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_add_book), _translate("MainWindow", "Ajouter Livre"))
self.search_lb.setText(_translate("MainWindow", "Recherche (par mot ou lettre)"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_search), _translate("MainWindow", "Recherche"))
self.delete_btn.setText(_translate("MainWindow", "Supprimer"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_delete), _translate("MainWindow", "Supprimer"))
+19
View File
@@ -0,0 +1,19 @@
from typing import TYPE_CHECKING
from logic import actions
if TYPE_CHECKING:
from gui.ui_library import Ui_Library
class Ui_Initialization:
def __init__(self, ui: Ui_Library):
self.ui = ui
def connect_button(self):
self.ui.save_btn.clicked.connect(self.ui.record_book)
self.ui.delete_btn.clicked.connect(self.ui.delete_book)
self.ui.change_list_signal.connect(self.ui.refresh_title_list)
self.ui.search_input.textChanged.connect(self.ui.search_book)
def fulfill_list(self):
self.ui.title_list.addItems(actions.list_titles())
+59
View File
@@ -0,0 +1,59 @@
from logic import actions
from gui.signal_mgt import SignalManagement
from gui.ui_init import Ui_Initialization
from gui.ui_base import Ui_MainWindow
from PyQt6.QtWidgets import QMessageBox
from PyQt6.QtGui import QStandardItemModel, QStandardItem
class Ui_Library(Ui_MainWindow):
##### Méthode de mise à jour de la liste des titres avec QTSignal
def setupUi(self, MainWindow):
super().setupUi(MainWindow)
ui_init = Ui_Initialization(self)
ui_init.connect_button()
ui_init.fulfill_list()
self.signal_mgt = SignalManagement(self)
self.signal_mgt.connect_signals()
def record_book(self):
title = self.title_input.text()
author = self.author_input.text()
message = actions.register_book(title, author)
QMessageBox.information(None, "Nouvel enregistrement", message)
# self.refresh_title_list()
self.signal_mgt.change_list_signal.emit()
def delete_book(self):
title = self.title_list.currentText()
message = actions.delete_book(title)
QMessageBox.information(None, "Suppression confirmée", message)
# self.refresh_title_list()
self.signal_mgt.change_list_signal.emit()
def refresh_title_list(self):
self.title_list.clear()
self.title_list.addItems(actions.list_titles())
def search_book(self):
word = self.search_input.text()
if len(word) == 1:
results = actions.search_by_letter(word)
self.display_list_view(results)
return
if len(word) > 1:
results = actions.search_by_word(word)
self.display_list_view(results)
return
def display_list_view(self, results):
self.model = QStandardItemModel()
self.results_view.setModel(self.model)
if isinstance(results, str):
self.model.appendRow(QStandardItem(results))
else:
for book in results:
self.model.appendRow(QStandardItem(str(book)))
+19
View File
@@ -0,0 +1,19 @@
from classes import Book, Library
library = Library("Romanesque")
def register_book(title: str, author: str):
book = Book(title, author)
return library.add_new_book(book)
def list_titles() -> list[str]:
return [book.title for book in library.list_books_in_list()]
def delete_book(title: str):
return library.take_out_book(title)
def search_by_letter(letter: str):
return library.search_book_by_letter(letter)
def search_by_word(word: str):
return library.search_book_by_word(word)
+12
View File
@@ -0,0 +1,12 @@
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from gui.ui_library import Ui_Library
app = QApplication([])
MainWindow = QMainWindow()
gui = Ui_Library()
gui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec())
+16
View File
@@ -0,0 +1,16 @@
from classes import Book, Library
library = Library("Romans")
for i in range(3):
new_book_title = input ("Quel livre ajouter ? > ")
new_book_author = input ("Qui l'a écrit ? > ")
new_book = Book(new_book_title, new_book_author)
new_book_added = library.add_new_book(new_book)
print(new_book_added)
print(library.list_books_in_list())
library.sort_books_by_name()
print(library.list_books_in_list())
+9
View File
@@ -0,0 +1,9 @@
[project]
name = "bibliotheque"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"pyqt6>=6.10.2",
]
+67
View File
@@ -0,0 +1,67 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "bibliotheque"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "pyqt6" },
]
[package.metadata]
requires-dist = [{ name = "pyqt6", specifier = ">=6.10.2" }]
[[package]]
name = "pyqt6"
version = "6.10.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyqt6-qt6" },
{ name = "pyqt6-sip" },
]
sdist = { url = "https://files.pythonhosted.org/packages/96/03/e756f52e8b0d7bb5527baf8c46d59af0746391943bdb8655acba22ee4168/pyqt6-6.10.2.tar.gz", hash = "sha256:6c0db5d8cbb9a3e7e2b5b51d0ff3f283121fa27b864db6d2f35b663c9be5cc83", size = 1085573, upload-time = "2026-01-08T16:40:00.244Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/fb/3f/f073a980969aa485ef288eb2e3b94c223ba9c7ac9941543f19b51659b98d/pyqt6-6.10.2-cp39-abi3-macosx_10_14_universal2.whl", hash = "sha256:37ae7c1183fe4dd0c6aefd2006a35731245de1cb6f817bb9e414a3e4848dfd6d", size = 60244482, upload-time = "2026-01-08T16:38:50.837Z" },
{ url = "https://files.pythonhosted.org/packages/ec/3e/9a015651ec71cea2e2f960c37edeb21623ba96a74956c0827def837f7c6b/pyqt6-6.10.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:78e1b3d5763e4cbc84485aef600e0aba5e1932fd263b716f92cd1a40dfa5e924", size = 37899440, upload-time = "2026-01-08T16:39:09.027Z" },
{ url = "https://files.pythonhosted.org/packages/51/74/a88fec2b99700270ca5d7dc7d650236a4990ed6fc88e055ca0fc8a339ee3/pyqt6-6.10.2-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:bbc3af541bbecd27301bfe69fe445aa1611a9b490bd3de77306b12df632f7ec6", size = 40748467, upload-time = "2026-01-08T16:39:29.551Z" },
{ url = "https://files.pythonhosted.org/packages/75/34/be7a55529607b21db00a49ca53cb07c3092d2a5a95ea19bb95cfa0346904/pyqt6-6.10.2-cp39-abi3-win_amd64.whl", hash = "sha256:bd328cb70bc382c48861cd5f0a11b2b8ae6f5692d5a2d6679ba52785dced327b", size = 26015391, upload-time = "2026-01-08T16:39:42.946Z" },
{ url = "https://files.pythonhosted.org/packages/af/de/d9c88f976602b7884fec4ad54a4575d48e23e4f390e5357ea83917358846/pyqt6-6.10.2-cp39-abi3-win_arm64.whl", hash = "sha256:7901ba1df024b7ee9fdacfb2b7661aeb3749ae8b0bef65428077de3e0450eabb", size = 26208415, upload-time = "2026-01-08T16:39:57.751Z" },
]
[[package]]
name = "pyqt6-qt6"
version = "6.10.1"
source = { registry = "https://pypi.org/simple" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/54/1b/137184632cad83a210e7955226744a77945260ca2e75892fe36299d26ada/pyqt6_qt6-6.10.1-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:4bb2798a95f624b462b70c4f185422235b714b01e55abab32af1740f147948e2", size = 68472463, upload-time = "2025-11-27T14:20:51.694Z" },
{ url = "https://files.pythonhosted.org/packages/af/df/ca795ac3d04243ad63499cfedcf92d8b5f6e3585a2a26c09f34cb58c8e44/pyqt6_qt6-6.10.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:0921cc522512cb40dbab673806bc1676924819550e0aec8e3f3fe6907387c5b7", size = 62296168, upload-time = "2025-11-27T14:21:21.232Z" },
{ url = "https://files.pythonhosted.org/packages/f4/7e/9867361252e2a4717dba95c64a0f3a793603f4a52cb9a46abbb041e960f5/pyqt6_qt6-6.10.1-py3-none-manylinux_2_34_x86_64.whl", hash = "sha256:04069aea421703b1269c8a1bcf017e36463af284a044239a4ebda3bde0a629fb", size = 83829262, upload-time = "2025-11-27T14:22:00.399Z" },
{ url = "https://files.pythonhosted.org/packages/9b/7b/18f4eb2273a92283fe4d87aa740a400eb14a4e41b8f990aaf563e9767db6/pyqt6_qt6-6.10.1-py3-none-manylinux_2_39_aarch64.whl", hash = "sha256:5b9be39e0120e32d0b42cdb844e3ae110ddadd39629c991e511902c06f155aff", size = 82877396, upload-time = "2025-11-27T14:22:36.994Z" },
{ url = "https://files.pythonhosted.org/packages/53/5c/648c515d57bc82909d0597befb03bbc2f7a570f323dba3ad38629669efcb/pyqt6_qt6-6.10.1-py3-none-win_amd64.whl", hash = "sha256:df564d3dc2863b1fde22b39bea9f56ceb2a3ed7d6f0b76d3f96c2d3bc5d71516", size = 76670151, upload-time = "2025-11-27T14:23:11.172Z" },
{ url = "https://files.pythonhosted.org/packages/0a/13/2d2a9c0559bfa53effea5e2c1ed7aebb430186ce0b64cfba235231a049d9/pyqt6_qt6-6.10.1-py3-none-win_arm64.whl", hash = "sha256:48282e0f99682daf4f1e220cfe9f41255e003af38f7728a30d40c76e55c89816", size = 58276316, upload-time = "2025-11-27T14:23:38.744Z" },
]
[[package]]
name = "pyqt6-sip"
version = "13.11.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/7d/d2916048e2e3960f68cb4e93907639844f7b8ff95897dcc98553776ccdfc/pyqt6_sip-13.11.0.tar.gz", hash = "sha256:d463af37738bda1856c9ef513e5620a37b7a005e9d589c986c3304db4a8a14d3", size = 92509, upload-time = "2026-01-13T16:01:32.16Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/53/a6/0e4d8fa7d6deb750bd0fdf89024e39c71fb127efb5eeedfab6830ad6679a/pyqt6_sip-13.11.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:6b3267cd93b7f4da6fdf9a6a26f3baed8faae06e5cdd76235f2acc2116c40a54", size = 112367, upload-time = "2026-01-13T16:01:09.08Z" },
{ url = "https://files.pythonhosted.org/packages/66/e6/25dc20a03c46000e8b93aaf79347227926b67959283e5aab797daa7f64d8/pyqt6_sip-13.11.0-cp312-cp312-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c30248d9bbe54c46a78e5d549da50295ecd6584b965597f751e272f000fb8527", size = 301150, upload-time = "2026-01-13T16:01:12.385Z" },
{ url = "https://files.pythonhosted.org/packages/11/9f/e850cd350aade789660cafba38c00777e686040c06b8cd0b45339b80fcba/pyqt6_sip-13.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c367b53a91e575ef66c1375f899713bdaf0a8b2c64b95ac226e9644854a4984", size = 323303, upload-time = "2026-01-13T16:01:10.736Z" },
{ url = "https://files.pythonhosted.org/packages/77/26/5261d62108f7579407230f8c1d4dda43c18b5600ce70bf3becb2f997d5cc/pyqt6_sip-13.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:077958105c2ea2f62be2f1a7611ff8bd44cb52fb5ea8fc8c59ea949144acb7b5", size = 53461, upload-time = "2026-01-13T16:01:13.875Z" },
{ url = "https://files.pythonhosted.org/packages/46/80/6c88b97eda309d6babb7292200bf51165dc06d0204d891b7bf1fb17a8ed0/pyqt6_sip-13.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:52812471619d3d3750b940d7d124cd0954107656924921ac177e098ba36362fb", size = 48650, upload-time = "2026-01-13T16:01:14.897Z" },
{ url = "https://files.pythonhosted.org/packages/df/a0/46abcae4fce175a326185460a02c13ab81332bca7dd55c1e853ba6aee71e/pyqt6_sip-13.11.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:929716eebde1a64ffdb6b1715db6a22aefd5634d6df84858c7deb5e85be84fdf", size = 112353, upload-time = "2026-01-13T16:01:16.152Z" },
{ url = "https://files.pythonhosted.org/packages/0e/38/27c3aa3f153fcd83a0765fedf8e44a1136f189a322bcc9c494c5b3793cd7/pyqt6_sip-13.11.0-cp313-cp313-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75144e8a0bcf9d1a9069011890401748af353749f1de1b6a314b880781edf9d", size = 301497, upload-time = "2026-01-13T16:01:20.531Z" },
{ url = "https://files.pythonhosted.org/packages/6f/ac/1053ffce45e4174f0a8174557b88537aa82bf96ba03c7dd208c59de36f69/pyqt6_sip-13.11.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8082b5f57ffad5dddf5efcf0ef5eaf94841395aa4e7c374c79ef24cf49b0f0ce", size = 323498, upload-time = "2026-01-13T16:01:17.859Z" },
{ url = "https://files.pythonhosted.org/packages/40/d3/447b30d1f00cc50ad9e5c53b2e920068606b16857da83f8036b390c79fad/pyqt6_sip-13.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8d49b5bf3d8d36cd7db93ddc54cd09dbba96a3fd926e445ef75499b41e47b5a3", size = 53469, upload-time = "2026-01-13T16:01:21.762Z" },
{ url = "https://files.pythonhosted.org/packages/92/67/77e6fafcabd01c0a11166ab7464509896f137929f82c4f2e03aea1bf41b3/pyqt6_sip-13.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:293eac1b53c66c54b03266cc30015ec77454af679043a4f188b9bb80a9656996", size = 48643, upload-time = "2026-01-13T16:01:22.669Z" },
{ url = "https://files.pythonhosted.org/packages/ff/28/a5178c8e005bafbf9c0fd507f45a3eef619ab582811414a0a461ee75994f/pyqt6_sip-13.11.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:4dc9c4df24af0571423c3e85b5c008bad42ed48558eef80fbc3e5d30274c5abb", size = 112431, upload-time = "2026-01-13T16:01:23.832Z" },
{ url = "https://files.pythonhosted.org/packages/13/3c/02770b02b5a05779e26bd02c202c2fd32aa38e225d01f14c06908e33738c/pyqt6_sip-13.11.0-cp314-cp314-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c974d5a193f32e55e746e9b63138503163ac63500dbb1fd67233d8a8d71369bd", size = 301236, upload-time = "2026-01-13T16:01:28.733Z" },
{ url = "https://files.pythonhosted.org/packages/40/47/5af493a698cc520581ca1000b4ab09b8182992053ffe2478062dde5e4671/pyqt6_sip-13.11.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4284540ffccd8349763ddce3518264dde62f20556720d4061b9c895e09011ca0", size = 323919, upload-time = "2026-01-13T16:01:25.122Z" },
{ url = "https://files.pythonhosted.org/packages/b7/2d/64b26e21183a7ff180105871dd5983a8da539d8768921728268dc6d0a73d/pyqt6_sip-13.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:9bd81cb351640abc803ea2fe7262b5adea28615c9b96fd103d1b6f3459937211", size = 55078, upload-time = "2026-01-13T16:01:29.853Z" },
{ url = "https://files.pythonhosted.org/packages/7e/36/23f699fa8b1c3fcc312ecd12661a1df6057d92e16d4def2399b59cf7bf22/pyqt6_sip-13.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:cd95ec98f8edb15bcea832b8657809f69d758bc4151cc6fd7790c0181949e45f", size = 49465, upload-time = "2026-01-13T16:01:31.174Z" },
]
+1
View File
@@ -0,0 +1 @@
3.12
View File
+91
View File
@@ -0,0 +1,91 @@
import json
class Contact:
def __init__(self, name: str, phone: str, email: str):
self.name = name
self.phone = phone
self.email = email
def __iter__(self):
yield self.name
yield self.phone
yield self.email
def __repr__(self) -> str:
return f"{self.name} - {self.phone} - {self.email}"
def __eq__(self, other: "Contact"):
return self.name == other.name\
and self.phone == other.phone\
and self.email == other.email
def serialized(self):
"""Converti la classe en dictionnaire JSONable"""
return {"Name": self.name, "Phone": self.phone, "Email": self.email}
@classmethod
def deserialized(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe Contact"""
return cls(name= dictionnary["Name"], phone= dictionnary["Phone"], email= dictionnary["Email"])
class Repertory:
def __init__(self, name: str):
self.name = name
self.contacts: list[Contact] = self.load()
def __iter__(self):
return iter(self.contacts)
def __getitem__(self, index: int) -> Contact:
return self.contacts[index]
def add_contact(self, contact: Contact):
if contact in self.contacts:
return f"{contact.name} est déjà dans le répertoire."
self.contacts.append(contact)
self.save()
return f"Nouveau contact :\nNom : {contact.name}\nNuméro : {contact.phone}\nCourriel : {contact.email}"
def delete_contact(self, contact_info: str):
for contact in self.contacts:
if contact.name.lower() == contact_info.lower()\
or contact.phone.lower() == contact_info.lower()\
or contact.email.lower() == contact_info.lower():
self.contacts.remove(contact)
self.save()
return f"{contact.name} a été supprimé du répertoire."
return f"{contact.name} n'est pas dans le répertoire."
def search_contact(self, research_str: str):
results = []
for contact in self.contacts:
if research_str.lower() in contact.name.lower()\
or research_str.lower() in contact.phone.lower()\
or research_str.lower() in contact.email.lower():
results.append(contact)
return results if len(results) > 0 else "Pas de résultat."
def display_contacts(self):
results = []
for idx, contact in enumerate(self.contacts):
results.append(
f"----- Contact n°{idx + 1} -----\n"
f"Nom : {contact.name}\n"
f"Numéro : {contact.phone}\n"
f"Courriel : {contact.email}\n"
" "
)
return "".join(results) if results else "Aucun contact dans le répertoire."
# Sauvegarde des livres dans un JSON pour persistance des données
def save(self):
"""Inscris dans un fichier JSON le contenu de la bibliothèque"""
contact_dict = [contact.serialized() for contact in self.contacts]
with open("contacts.json", "w") as json_file: # a pour append, w pour write
json.dump(contact_dict, json_file, indent= 4)
def load(self) -> list[Contact]:
"""Récupère le contenu d'un fichier JSON"""
with open("contacts.json") as json_file:
return json.load(json_file, object_hook= Contact.deserialized)
+27
View File
@@ -0,0 +1,27 @@
[
{
"Name": "Alberto",
"Phone": "0612345678",
"Email": "alberto@courriel.fr"
},
{
"Name": "Alice",
"Phone": "0123456789",
"Email": "alice@gmail.com"
},
{
"Name": "Alberto",
"Phone": "0482764563",
"Email": "kfjsbdfg@sdfgj.fr"
},
{
"Name": "Giorgio",
"Phone": "857398375493",
"Email": "giorgio.armani@armagnac.it"
},
{
"Name": "Fran\u00e7ois LE GUERAND",
"Phone": "0145892367",
"Email": "fr-le-g@gmail.fr"
}
]
+18
View File
@@ -0,0 +1,18 @@
from classes import Contact,Repertory
repertory = Repertory("Repertoire")
for i in range(1):
new_contact_name = input("Nom > ")
new_contact_phone = input("Numéro > ")
new_contact_email = input("Courriel > ")
new_contact = Contact(new_contact_name, new_contact_phone, new_contact_email)
new_contact_added = repertory.add_contact(new_contact)
print(new_contact_added)
search_criteria = input("Critères de recherche > ")
print(repertory.search_contact(search_criteria))
print(repertory.display_contacts())
+7
View File
@@ -0,0 +1,7 @@
[project]
name = "contacts"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
+8
View File
@@ -0,0 +1,8 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "contacts"
version = "0.1.0"
source = { virtual = "." }
+1
View File
@@ -0,0 +1 @@
3.12
View File
+33
View File
@@ -0,0 +1,33 @@
class Fraction:
def __init__(self, numerateur, denominateur):
if denominateur == 0:
raise ValueError("Le denominateur ne peut etre nul")
if not isinstance(denominateur, int) or not isinstance(numerateur, int):
raise TypeError("Le numerateur/denominateur doit etre un entier")
self.numerateur = numerateur
self.denominateur = denominateur
@property
def quotient(self):
return self.numerateur / self.denominateur
print("Debut programme")
try:
tiers = Fraction(1, '0')
print(tiers.quotient)
except (ValueError, TypeError) as msg :
print(msg)
liste = [1,2,3,4]
dico = {'nom': "John"}
try:
print(dico['prenom'])
print(liste[7])
except LookupError as msg:
if isinstance(msg, KeyError):
print("La cle n'existe pas")
else:
print(msg)
print("Fin du programme")
+31
View File
@@ -0,0 +1,31 @@
from typing import TypedDict
def addition(*args): # args => tuple (2,3,4,5,6,6,6,7,7,8,9)
return sum(args)
print(addition(2,3,4,5))
livres = [
{"titre": "1984", "auteur": "Orwell"},
{"titre": "1983", "auteur": "Orwella"},
{"titre": "1985", "auteur": "Orwell"}
]
def display_infos(**kwargs): # kwargs => dict {"Titre": "Scandale", "Auteur": "Marlène Schiappa"}
resultats = []
for livre in livres:
if "auteur" in kwargs and kwargs["auteur"].lower() in livre["auteur"]:
resultats.append(livre)
if "titre" in kwargs and kwargs["titre"].lower() in livre["titre"]:
resultats.append(livre)
return resultats
infos: dict[str | int, str | int] = {"age": 23, "nom": "Albatar", "is_admin" : False}
class Criteres(TypedDict):
auteur: NotRequired[str]
titre: NotRequired[str]
print(CONSTANTES["db_name"])
+42
View File
@@ -0,0 +1,42 @@
from datetime import date, time, datetime, timedelta
import pytz
date_2026 = date(2026, 1, 10)
print(date_2026)
today = date.today()
print(today)
hour = time()
print(hour)
hour = time(12, 34, 23)
print(hour)
hour_now = datetime.now().time()
print(hour_now)
day_now = datetime.now().date()
print(day_now)
timezone_paris = pytz.timezone("Europe/Paris")
timezone_moscou = pytz.timezone("Europe/Moscow")
timezone_pyongyang = pytz.timezone("Asia/Pyongyang")
heure_actuelle_paris = datetime.now(tz= timezone_paris)
heure_actuelle_moscou = datetime.now(tz= timezone_moscou)
heure_actuelle_pyongyang = datetime.now(tz= timezone_pyongyang)
print(heure_actuelle_paris)
print(heure_actuelle_moscou)
print(heure_actuelle_pyongyang)
date_15_jours = date.today() + timedelta(days= 15)
print(date_15_jours)
debut_voyage = datetime(2026, 1, 16, 12, 7, 18, tzinfo= timezone_paris)
fin_voyage = datetime(2026, 12, 25, 13, 56, 23, tzinfo= timezone_pyongyang)
print(debut_voyage - fin_voyage)
detail_voyage = debut_voyage - fin_voyage
print(detail_voyage.days)
print(detail_voyage.seconds)
+9
View File
@@ -0,0 +1,9 @@
[project]
name = "divers"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"pytz>=2025.2",
]
+23
View File
@@ -0,0 +1,23 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "divers"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "pytz" },
]
[package.metadata]
requires-dist = [{ name = "pytz", specifier = ">=2025.2" }]
[[package]]
name = "pytz"
version = "2025.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
]
+1
View File
@@ -0,0 +1 @@
3.12
View File
+21
View File
@@ -0,0 +1,21 @@
"""
An isogram is a word that has no repeating letters, consecutive or non-consecutive. Implement a function that determines whether a string that contains only letters is an isogram. Assume the empty string is an isogram. Ignore letter case.
Example: (Input --> Output)
"Dermatoglyphics" --> true
"aba" --> false
"moOse" --> false (ignore letter case)
"""
def is_isogram(string):
string = string.lower()
for letter in string:
if string.count(letter) > 1:
return False
return True
# Solution la plus opti
def is_isogram(string):
return len(string) == len(set(string.lower()))
+72
View File
@@ -0,0 +1,72 @@
destinations = {
"Pyongyang": 5,
"Havana": 2,
"Caracas": 7
}
destinations["Moscow"] = 0
destinations["Ho-Chi-Minh Town"] = 0
def add_destination(destinations: dict, town: str, number: int):
if town not in destinations:
destinations[town] = 0
def add_reservation(destinations: dict, town: str, number: int):
if town in destinations:
destinations[town] += number
else:
destinations[town] = number
def remove_reservation(destinations: dict, town: str):
if town in destinations:
new_destinations = dict(destinations)
del new_destinations[town]
return new_destinations
def show_destinations_available(destinations: dict):
for town in destinations:
if destinations[town] != 0:
print(town + " : " + str(destinations[town]))
def show_destinations_by_reservations(destinations: dict):
print(sorted(destinations)) # ["Pyongyang", "Havana", "Caracas"]
print(sorted(destinations.keys())) # ["Pyongyang", "Havana", "Caracas"]
print(sorted(destinations.values)) # [5, 2, 7]
print(sorted(destinations.items)) # [("Pyongyang", 5), ("Havana", 2), ("Caracas", 7)]
def return_second_tuple_element(tuple):
return tuple[1]
print(sorted(destinations.items(), key= return_second_tuple_element)) # [('Moscow', 0), ('Ho-Chi-Minh Town', 0), ('Havana', 2), ('Pyongyang', 5), ('Caracas', 7)]
print(sorted(destinations.items(), key= lambda tuple : tuple[1])) # [('Moscow', 0), ('Ho-Chi-Minh Town', 0), ('Havana', 2), ('Pyongyang', 5), ('Caracas', 7)]
#show_destinations_available(destinations)
# Données déstructurées
dc_infos = ("Dale", "Cooper", "32")
dc_prenom = dc_infos[0]
dc_nom = dc_infos[1]
dc_age = dc_infos[2]
dc_prenom, dc_nom, dc_age = dc_infos
def generator():
for i in range(10):
yield i
def square_generator(n):
for i in range(n):
yield i ** 2
print(generator())
squares = square_generator(10)
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
+28
View File
@@ -0,0 +1,28 @@
import sys
input_string = input("Ecris un truc > ")
if len(input_string) == 0:
print("Tu aurais pu participer.")
sys.exit()
def return_string_infos(input_string: str):
print("Tu as tapé : " + "\"" + input_string + "\"")
print("Elle fait exactement " + str(len(input_string)) + " caractères.")
print("EN MAJUSCULES, ELLE DONNE : " + "\"" + input_string.upper() + "\"")
print("en minuscules, elle donne : " + "\"" + input_string.lower() + "\"")
print("A l'envers, elle donne : " + "\"" + input_string[::-1] + "\"")
def replace_word_in_string(input_string: str, word_to_replace: str, word_replacement: str) -> str:
print(f"Remplaçant \"{word_to_replace}\" par \"{word_replacement}\", cela donne : {input_string.replace(word_to_replace, word_replacement)}")
def count_occurences_in_string(input_string: str, occurence: str):
print(f"L'occurence \"{occurence}\" apparaît {input_string.count(occurence)} fois.")
def strip_of_spaces(input_string: str):
print(f"Sans les espaces de début et de fin, cela donne : {input_string.strip()}")
return_string_infos(input_string)
replace_word_in_string(input_string, "vie", "mort")
count_occurences_in_string(input_string, "e")
strip_of_spaces(input_string)
+1
View File
@@ -0,0 +1 @@
from Semaine_04.Exercice_01.exo_01 import
+34
View File
@@ -0,0 +1,34 @@
word_to_find = "parapluie"
word_hidden = "_" * len(word_to_find)
list_word_hidden = list(word_hidden)
attempts = 10
already_chosen_letter = []
print(word_hidden)
while word_hidden != word_to_find and attempts > 0:
chosen_letter = input("Saisir une lettre > ").strip().lower()[0] # on ne prend VRAIMENT que la première lettre
if chosen_letter in already_chosen_letter:
print(f"Vous avez déjà saisie la lettre {chosen_letter.upper()}.")
attempts -= 1
continue
already_chosen_letter.append(chosen_letter)
if chosen_letter not in word_to_find:
attempts -= 1
continue
for index, letter in enumerate(word_to_find):
if letter == chosen_letter:
list_word_hidden[index] = chosen_letter
word_hidden = "".join(list_word_hidden)
print(f"Il reste {attempts} tentatives. \n {word_hidden} \n")
if word_hidden != word_to_find:
print(f"Perdu ! Le mot était {word_to_find.upper()}.")
else:
print("Gagné !")
+7
View File
@@ -0,0 +1,7 @@
[project]
name = "exercice-01"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
+8
View File
@@ -0,0 +1,8 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "exercice-01"
version = "0.1.0"
source = { virtual = "." }
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
3.12
View File
+6
View File
@@ -0,0 +1,6 @@
from math import pi
class Point:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
+1
View File
@@ -0,0 +1 @@
Nom,Prénom,Âge
+57
View File
@@ -0,0 +1,57 @@
# Reussir dans la POO c'est se rapprocher au plus pret de la realite
from typing import Self
class Fraction:
def __init__(self, numerateur, denominateur):
# Attributs
self.numerateur = numerateur # tiers.numerateur = 1
self.denominateur = denominateur
self.simplifier()
def quotient(self):
return self.numerateur / self.denominateur
@classmethod # decorateur
def from_str(cls, num: str, den: str):
return cls(numerateur= int(num), denominateur= int(den))
@staticmethod # Pas de 'self' => Helpers
def pgcd(a, b):
if b == 0: return a
return Fraction.pgcd(a= b, b= a % b)
def simplifier(self):
a = self.numerateur
b = self.denominateur
pgcd = Fraction.pgcd(a, b)
self.numerateur = self.numerateur // pgcd
self.denominateur //= pgcd
def __add__(self, fraction):
num = (self.numerateur * fraction.denominateur) + (self.denominateur * fraction.numerateur)
den = self.denominateur * fraction.denominateur
return Fraction(numerateur= num, denominateur= den)
def __mul__(self, facteur: int | Self):
if isinstance(facteur, int):
return Fraction(
numerateur= self.numerateur * facteur,
denominateur= self.denominateur
)
return Fraction(
numerateur= self.numerateur * facteur.numerateur,
denominateur= self.denominateur * facteur.denominateur
)
def __rmul__(self, nombre: int):
return self.__mul__(nombre)
def __repr__(self):
return f"Fraction({self.numerateur}/{self.denominateur})"
# le PGCD de 146 et 248
fraction = Fraction.from_str('2', '5')
print(fraction * 2)
print(2 * fraction)
+42
View File
@@ -0,0 +1,42 @@
import os
from tkinter.ttk import Separator
import pandas
import csv
def addition(a: int, b: int):
somme = a + b
return somme
def create_folder(path: str, name:str):
chemin_complet = os.path.join(path, name)
if not os.path.isdir(chemin_complet):
os.mkdir(chemin_complet)
def create_empty_csv_file(
path: str,
filename: str,
/, # ce qui est avant le / est du positionnage
*, # ce qui est après le * est du nommage
colonnes: list,
separateur: str = ","
):
tableau = pandas.DataFrame(columns= colonnes)
chemin_complet = os.path.join(path, filename)
tableau.to_csv(
path_or_buf= chemin_complet,
sep= separateur,
index= False
)
def write_to_csv(
path: str,
filename: str,
colonnes: list,
donnees: list[dict]
):
if not filename.endswith(".csv"):
filename += ".csv"
chemin_complet = os.path.join(path, filename)
fichier_csv = open(chemin_complet, "a")
writer = csv.DictWriter(fichier_csv, colonnes, delimiter= separateur, lineterminator= "\n")
writer.writerows(donnees)
+31
View File
@@ -0,0 +1,31 @@
from functions import addition, create_folder, create_empty_csv_file, write_to_csv
print(addition(3,7))
create_folder(".", "data")
# Ou bien, si on veut changer l'ordre des arguments
create_folder(
name= "data",
path= "."
)
create_empty_csv_file(
".",
"csv_test",
colonnes= ["Nom", "Prénom", "Âge"]
)
data = [
{"id" = 1, "Prénom": "Dale", "Nom": "Cooper", "Âge": 35},
{"id" = 2, "Prénom": "Dale", "Nom": "Cooper", "Âge": 35},
{"id" = 3, "Prénom": "Dougie", "Nom": "Jones", "Âge": 35},
]
write_to_csv(
path= "data",
filename= "donnees",
colonnes= ["Nom", "Prénom", "Âge"],
donnees= data[]
)
+26
View File
@@ -0,0 +1,26 @@
# Heritage / Composition
# Heritage: relation "EST UN"
class Person:
def __init__(self, nom, prenom, age):
self.nom = nom
self.prenom = prenom
self.age = age
def dire_bonjour(self):
return "Bonjour tout le monde"
class Student(Person): # Heritage
def __init__(self, nom, prenom, age, domaine):
super().__init__(nom, prenom, age)
self.domaine = domaine
# override
def dire_bonjour(self):
return super().dire_bonjour() + "! Ca va?"
alice = Student('Smith', 'Alice', 19, 'Finance')
print(alice.dire_bonjour())
print(alice.__dict__)
print(isinstance(alice, Student))
print(isinstance(alice, Person))
+9
View File
@@ -0,0 +1,9 @@
[project]
name = "fonctions"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"pandas>=2.3.3",
]
+47
View File
@@ -0,0 +1,47 @@
# Composition: traduit une relation "A UN" "POSSED UN" "DEPEND DE"
from math import pi
from composition import Point
class Forme: # Abstraction
def __init__(self, centre: Point):
self.centre = centre
def aire(self):
raise NotImplementedError("Attention aire doit etre redefini")
def perimetre(self):
raise NotImplementedError("Attention perimetre doit etre redefini")
class Cercle:
def __init__(self, centre: Point, rayon: float):
self.centre = centre
self.rayon = rayon
@property
def aire(self):
return pi * self.rayon ** 2
@property
def perimetre(self):
return 2 * pi * self.rayon
class Rectangle(Forme):
def __init__(self, centre: Point, longeur: float, largeur: float):
super().__init__(centre)
self.longueur = longeur
self.largeur = largeur
def aire(self):
return self.longueur * self.largeur
def perimetre(self):
return 2 * (self.longueur + self.largeur)
cercle1 = Cercle(centre= Point(2, 2), rayon= 5)
cercle2 = Cercle(centre= Point(-2, 2), rayon= 6)
rect1 = Rectangle(centre= Point(0, 0), longeur= 12, largeur= 5)
rect2 = Rectangle(centre= Point(1, 1), longeur= 10, largeur= 6)
formes = [cercle1, cercle2, rect1, rect2]
for forme in formes:
print(forme.aire())
+161
View File
@@ -0,0 +1,161 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "fonctions"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "pandas" },
]
[package.metadata]
requires-dist = [{ name = "pandas", specifier = ">=2.3.3" }]
[[package]]
name = "numpy"
version = "2.4.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/24/62/ae72ff66c0f1fd959925b4c11f8c2dea61f47f6acaea75a08512cdfe3fed/numpy-2.4.1.tar.gz", hash = "sha256:a1ceafc5042451a858231588a104093474c6a5c57dcc724841f5c888d237d690", size = 20721320, upload-time = "2026-01-10T06:44:59.619Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/78/7f/ec53e32bf10c813604edf07a3682616bd931d026fcde7b6d13195dfb684a/numpy-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d3703409aac693fa82c0aee023a1ae06a6e9d065dba10f5e8e80f642f1e9d0a2", size = 16656888, upload-time = "2026-01-10T06:42:40.913Z" },
{ url = "https://files.pythonhosted.org/packages/b8/e0/1f9585d7dae8f14864e948fd7fa86c6cb72dee2676ca2748e63b1c5acfe0/numpy-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7211b95ca365519d3596a1d8688a95874cc94219d417504d9ecb2df99fa7bfa8", size = 12373956, upload-time = "2026-01-10T06:42:43.091Z" },
{ url = "https://files.pythonhosted.org/packages/8e/43/9762e88909ff2326f5e7536fa8cb3c49fb03a7d92705f23e6e7f553d9cb3/numpy-2.4.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:5adf01965456a664fc727ed69cc71848f28d063217c63e1a0e200a118d5eec9a", size = 5202567, upload-time = "2026-01-10T06:42:45.107Z" },
{ url = "https://files.pythonhosted.org/packages/4b/ee/34b7930eb61e79feb4478800a4b95b46566969d837546aa7c034c742ef98/numpy-2.4.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:26f0bcd9c79a00e339565b303badc74d3ea2bd6d52191eeca5f95936cad107d0", size = 6549459, upload-time = "2026-01-10T06:42:48.152Z" },
{ url = "https://files.pythonhosted.org/packages/79/e3/5f115fae982565771be994867c89bcd8d7208dbfe9469185497d70de5ddf/numpy-2.4.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0093e85df2960d7e4049664b26afc58b03236e967fb942354deef3208857a04c", size = 14404859, upload-time = "2026-01-10T06:42:49.947Z" },
{ url = "https://files.pythonhosted.org/packages/d9/7d/9c8a781c88933725445a859cac5d01b5871588a15969ee6aeb618ba99eee/numpy-2.4.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ad270f438cbdd402c364980317fb6b117d9ec5e226fff5b4148dd9aa9fc6e02", size = 16371419, upload-time = "2026-01-10T06:42:52.409Z" },
{ url = "https://files.pythonhosted.org/packages/a6/d2/8aa084818554543f17cf4162c42f162acbd3bb42688aefdba6628a859f77/numpy-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:297c72b1b98100c2e8f873d5d35fb551fce7040ade83d67dd51d38c8d42a2162", size = 16182131, upload-time = "2026-01-10T06:42:54.694Z" },
{ url = "https://files.pythonhosted.org/packages/60/db/0425216684297c58a8df35f3284ef56ec4a043e6d283f8a59c53562caf1b/numpy-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cf6470d91d34bf669f61d515499859fa7a4c2f7c36434afb70e82df7217933f9", size = 18295342, upload-time = "2026-01-10T06:42:56.991Z" },
{ url = "https://files.pythonhosted.org/packages/31/4c/14cb9d86240bd8c386c881bafbe43f001284b7cce3bc01623ac9475da163/numpy-2.4.1-cp312-cp312-win32.whl", hash = "sha256:b6bcf39112e956594b3331316d90c90c90fb961e39696bda97b89462f5f3943f", size = 5959015, upload-time = "2026-01-10T06:42:59.631Z" },
{ url = "https://files.pythonhosted.org/packages/51/cf/52a703dbeb0c65807540d29699fef5fda073434ff61846a564d5c296420f/numpy-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:e1a27bb1b2dee45a2a53f5ca6ff2d1a7f135287883a1689e930d44d1ff296c87", size = 12310730, upload-time = "2026-01-10T06:43:01.627Z" },
{ url = "https://files.pythonhosted.org/packages/69/80/a828b2d0ade5e74a9fe0f4e0a17c30fdc26232ad2bc8c9f8b3197cf7cf18/numpy-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:0e6e8f9d9ecf95399982019c01223dc130542960a12edfa8edd1122dfa66a8a8", size = 10312166, upload-time = "2026-01-10T06:43:03.673Z" },
{ url = "https://files.pythonhosted.org/packages/04/68/732d4b7811c00775f3bd522a21e8dd5a23f77eb11acdeb663e4a4ebf0ef4/numpy-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d797454e37570cfd61143b73b8debd623c3c0952959adb817dd310a483d58a1b", size = 16652495, upload-time = "2026-01-10T06:43:06.283Z" },
{ url = "https://files.pythonhosted.org/packages/20/ca/857722353421a27f1465652b2c66813eeeccea9d76d5f7b74b99f298e60e/numpy-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c55962006156aeef1629b953fd359064aa47e4d82cfc8e67f0918f7da3344f", size = 12368657, upload-time = "2026-01-10T06:43:09.094Z" },
{ url = "https://files.pythonhosted.org/packages/81/0d/2377c917513449cc6240031a79d30eb9a163d32a91e79e0da47c43f2c0c8/numpy-2.4.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:71abbea030f2cfc3092a0ff9f8c8fdefdc5e0bf7d9d9c99663538bb0ecdac0b9", size = 5197256, upload-time = "2026-01-10T06:43:13.634Z" },
{ url = "https://files.pythonhosted.org/packages/17/39/569452228de3f5de9064ac75137082c6214be1f5c532016549a7923ab4b5/numpy-2.4.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5b55aa56165b17aaf15520beb9cbd33c9039810e0d9643dd4379e44294c7303e", size = 6545212, upload-time = "2026-01-10T06:43:15.661Z" },
{ url = "https://files.pythonhosted.org/packages/8c/a4/77333f4d1e4dac4395385482557aeecf4826e6ff517e32ca48e1dafbe42a/numpy-2.4.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0faba4a331195bfa96f93dd9dfaa10b2c7aa8cda3a02b7fd635e588fe821bf5", size = 14402871, upload-time = "2026-01-10T06:43:17.324Z" },
{ url = "https://files.pythonhosted.org/packages/ba/87/d341e519956273b39d8d47969dd1eaa1af740615394fe67d06f1efa68773/numpy-2.4.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e3087f53e2b4428766b54932644d148613c5a595150533ae7f00dab2f319a8", size = 16359305, upload-time = "2026-01-10T06:43:19.376Z" },
{ url = "https://files.pythonhosted.org/packages/32/91/789132c6666288eaa20ae8066bb99eba1939362e8f1a534949a215246e97/numpy-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:49e792ec351315e16da54b543db06ca8a86985ab682602d90c60ef4ff4db2a9c", size = 16181909, upload-time = "2026-01-10T06:43:21.808Z" },
{ url = "https://files.pythonhosted.org/packages/cf/b8/090b8bd27b82a844bb22ff8fdf7935cb1980b48d6e439ae116f53cdc2143/numpy-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79e9e06c4c2379db47f3f6fc7a8652e7498251789bf8ff5bd43bf478ef314ca2", size = 18284380, upload-time = "2026-01-10T06:43:23.957Z" },
{ url = "https://files.pythonhosted.org/packages/67/78/722b62bd31842ff029412271556a1a27a98f45359dea78b1548a3a9996aa/numpy-2.4.1-cp313-cp313-win32.whl", hash = "sha256:3d1a100e48cb266090a031397863ff8a30050ceefd798f686ff92c67a486753d", size = 5957089, upload-time = "2026-01-10T06:43:27.535Z" },
{ url = "https://files.pythonhosted.org/packages/da/a6/cf32198b0b6e18d4fbfa9a21a992a7fca535b9bb2b0cdd217d4a3445b5ca/numpy-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:92a0e65272fd60bfa0d9278e0484c2f52fe03b97aedc02b357f33fe752c52ffb", size = 12307230, upload-time = "2026-01-10T06:43:29.298Z" },
{ url = "https://files.pythonhosted.org/packages/44/6c/534d692bfb7d0afe30611320c5fb713659dcb5104d7cc182aff2aea092f5/numpy-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:20d4649c773f66cc2fc36f663e091f57c3b7655f936a4c681b4250855d1da8f5", size = 10313125, upload-time = "2026-01-10T06:43:31.782Z" },
{ url = "https://files.pythonhosted.org/packages/da/a1/354583ac5c4caa566de6ddfbc42744409b515039e085fab6e0ff942e0df5/numpy-2.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f93bc6892fe7b0663e5ffa83b61aab510aacffd58c16e012bb9352d489d90cb7", size = 12496156, upload-time = "2026-01-10T06:43:34.237Z" },
{ url = "https://files.pythonhosted.org/packages/51/b0/42807c6e8cce58c00127b1dc24d365305189991f2a7917aa694a109c8d7d/numpy-2.4.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:178de8f87948163d98a4c9ab5bee4ce6519ca918926ec8df195af582de28544d", size = 5324663, upload-time = "2026-01-10T06:43:36.211Z" },
{ url = "https://files.pythonhosted.org/packages/fe/55/7a621694010d92375ed82f312b2f28017694ed784775269115323e37f5e2/numpy-2.4.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:98b35775e03ab7f868908b524fc0a84d38932d8daf7b7e1c3c3a1b6c7a2c9f15", size = 6645224, upload-time = "2026-01-10T06:43:37.884Z" },
{ url = "https://files.pythonhosted.org/packages/50/96/9fa8635ed9d7c847d87e30c834f7109fac5e88549d79ef3324ab5c20919f/numpy-2.4.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:941c2a93313d030f219f3a71fd3d91a728b82979a5e8034eb2e60d394a2b83f9", size = 14462352, upload-time = "2026-01-10T06:43:39.479Z" },
{ url = "https://files.pythonhosted.org/packages/03/d1/8cf62d8bb2062da4fb82dd5d49e47c923f9c0738032f054e0a75342faba7/numpy-2.4.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:529050522e983e00a6c1c6b67411083630de8b57f65e853d7b03d9281b8694d2", size = 16407279, upload-time = "2026-01-10T06:43:41.93Z" },
{ url = "https://files.pythonhosted.org/packages/86/1c/95c86e17c6b0b31ce6ef219da00f71113b220bcb14938c8d9a05cee0ff53/numpy-2.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2302dc0224c1cbc49bb94f7064f3f923a971bfae45c33870dcbff63a2a550505", size = 16248316, upload-time = "2026-01-10T06:43:44.121Z" },
{ url = "https://files.pythonhosted.org/packages/30/b4/e7f5ff8697274c9d0fa82398b6a372a27e5cef069b37df6355ccb1f1db1a/numpy-2.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9171a42fcad32dcf3fa86f0a4faa5e9f8facefdb276f54b8b390d90447cff4e2", size = 18329884, upload-time = "2026-01-10T06:43:46.613Z" },
{ url = "https://files.pythonhosted.org/packages/37/a4/b073f3e9d77f9aec8debe8ca7f9f6a09e888ad1ba7488f0c3b36a94c03ac/numpy-2.4.1-cp313-cp313t-win32.whl", hash = "sha256:382ad67d99ef49024f11d1ce5dcb5ad8432446e4246a4b014418ba3a1175a1f4", size = 6081138, upload-time = "2026-01-10T06:43:48.854Z" },
{ url = "https://files.pythonhosted.org/packages/16/16/af42337b53844e67752a092481ab869c0523bc95c4e5c98e4dac4e9581ac/numpy-2.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:62fea415f83ad8fdb6c20840578e5fbaf5ddd65e0ec6c3c47eda0f69da172510", size = 12447478, upload-time = "2026-01-10T06:43:50.476Z" },
{ url = "https://files.pythonhosted.org/packages/6c/f8/fa85b2eac68ec631d0b631abc448552cb17d39afd17ec53dcbcc3537681a/numpy-2.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:a7870e8c5fc11aef57d6fea4b4085e537a3a60ad2cdd14322ed531fdca68d261", size = 10382981, upload-time = "2026-01-10T06:43:52.575Z" },
{ url = "https://files.pythonhosted.org/packages/1b/a7/ef08d25698e0e4b4efbad8d55251d20fe2a15f6d9aa7c9b30cd03c165e6f/numpy-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3869ea1ee1a1edc16c29bbe3a2f2a4e515cc3a44d43903ad41e0cacdbaf733dc", size = 16652046, upload-time = "2026-01-10T06:43:54.797Z" },
{ url = "https://files.pythonhosted.org/packages/8f/39/e378b3e3ca13477e5ac70293ec027c438d1927f18637e396fe90b1addd72/numpy-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e867df947d427cdd7a60e3e271729090b0f0df80f5f10ab7dd436f40811699c3", size = 12378858, upload-time = "2026-01-10T06:43:57.099Z" },
{ url = "https://files.pythonhosted.org/packages/c3/74/7ec6154f0006910ed1fdbb7591cf4432307033102b8a22041599935f8969/numpy-2.4.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:e3bd2cb07841166420d2fa7146c96ce00cb3410664cbc1a6be028e456c4ee220", size = 5207417, upload-time = "2026-01-10T06:43:59.037Z" },
{ url = "https://files.pythonhosted.org/packages/f7/b7/053ac11820d84e42f8feea5cb81cc4fcd1091499b45b1ed8c7415b1bf831/numpy-2.4.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:f0a90aba7d521e6954670550e561a4cb925713bd944445dbe9e729b71f6cabee", size = 6542643, upload-time = "2026-01-10T06:44:01.852Z" },
{ url = "https://files.pythonhosted.org/packages/c0/c4/2e7908915c0e32ca636b92e4e4a3bdec4cb1e7eb0f8aedf1ed3c68a0d8cd/numpy-2.4.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d558123217a83b2d1ba316b986e9248a1ed1971ad495963d555ccd75dcb1556", size = 14418963, upload-time = "2026-01-10T06:44:04.047Z" },
{ url = "https://files.pythonhosted.org/packages/eb/c0/3ed5083d94e7ffd7c404e54619c088e11f2e1939a9544f5397f4adb1b8ba/numpy-2.4.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f44de05659b67d20499cbc96d49f2650769afcb398b79b324bb6e297bfe3844", size = 16363811, upload-time = "2026-01-10T06:44:06.207Z" },
{ url = "https://files.pythonhosted.org/packages/0e/68/42b66f1852bf525050a67315a4fb94586ab7e9eaa541b1bef530fab0c5dd/numpy-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:69e7419c9012c4aaf695109564e3387f1259f001b4326dfa55907b098af082d3", size = 16197643, upload-time = "2026-01-10T06:44:08.33Z" },
{ url = "https://files.pythonhosted.org/packages/d2/40/e8714fc933d85f82c6bfc7b998a0649ad9769a32f3494ba86598aaf18a48/numpy-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2ffd257026eb1b34352e749d7cc1678b5eeec3e329ad8c9965a797e08ccba205", size = 18289601, upload-time = "2026-01-10T06:44:10.841Z" },
{ url = "https://files.pythonhosted.org/packages/80/9a/0d44b468cad50315127e884802351723daca7cf1c98d102929468c81d439/numpy-2.4.1-cp314-cp314-win32.whl", hash = "sha256:727c6c3275ddefa0dc078524a85e064c057b4f4e71ca5ca29a19163c607be745", size = 6005722, upload-time = "2026-01-10T06:44:13.332Z" },
{ url = "https://files.pythonhosted.org/packages/7e/bb/c6513edcce5a831810e2dddc0d3452ce84d208af92405a0c2e58fd8e7881/numpy-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:7d5d7999df434a038d75a748275cd6c0094b0ecdb0837342b332a82defc4dc4d", size = 12438590, upload-time = "2026-01-10T06:44:15.006Z" },
{ url = "https://files.pythonhosted.org/packages/e9/da/a598d5cb260780cf4d255102deba35c1d072dc028c4547832f45dd3323a8/numpy-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:ce9ce141a505053b3c7bce3216071f3bf5c182b8b28930f14cd24d43932cd2df", size = 10596180, upload-time = "2026-01-10T06:44:17.386Z" },
{ url = "https://files.pythonhosted.org/packages/de/bc/ea3f2c96fcb382311827231f911723aeff596364eb6e1b6d1d91128aa29b/numpy-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4e53170557d37ae404bf8d542ca5b7c629d6efa1117dac6a83e394142ea0a43f", size = 12498774, upload-time = "2026-01-10T06:44:19.467Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ab/ef9d939fe4a812648c7a712610b2ca6140b0853c5efea361301006c02ae5/numpy-2.4.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:a73044b752f5d34d4232f25f18160a1cc418ea4507f5f11e299d8ac36875f8a0", size = 5327274, upload-time = "2026-01-10T06:44:23.189Z" },
{ url = "https://files.pythonhosted.org/packages/bd/31/d381368e2a95c3b08b8cf7faac6004849e960f4a042d920337f71cef0cae/numpy-2.4.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:fb1461c99de4d040666ca0444057b06541e5642f800b71c56e6ea92d6a853a0c", size = 6648306, upload-time = "2026-01-10T06:44:25.012Z" },
{ url = "https://files.pythonhosted.org/packages/c8/e5/0989b44ade47430be6323d05c23207636d67d7362a1796ccbccac6773dd2/numpy-2.4.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:423797bdab2eeefbe608d7c1ec7b2b4fd3c58d51460f1ee26c7500a1d9c9ee93", size = 14464653, upload-time = "2026-01-10T06:44:26.706Z" },
{ url = "https://files.pythonhosted.org/packages/10/a7/cfbe475c35371cae1358e61f20c5f075badc18c4797ab4354140e1d283cf/numpy-2.4.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:52b5f61bdb323b566b528899cc7db2ba5d1015bda7ea811a8bcf3c89c331fa42", size = 16405144, upload-time = "2026-01-10T06:44:29.378Z" },
{ url = "https://files.pythonhosted.org/packages/f8/a3/0c63fe66b534888fa5177cc7cef061541064dbe2b4b60dcc60ffaf0d2157/numpy-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42d7dd5fa36d16d52a84f821eb96031836fd405ee6955dd732f2023724d0aa01", size = 16247425, upload-time = "2026-01-10T06:44:31.721Z" },
{ url = "https://files.pythonhosted.org/packages/6b/2b/55d980cfa2c93bd40ff4c290bf824d792bd41d2fe3487b07707559071760/numpy-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7b6b5e28bbd47b7532698e5db2fe1db693d84b58c254e4389d99a27bb9b8f6b", size = 18330053, upload-time = "2026-01-10T06:44:34.617Z" },
{ url = "https://files.pythonhosted.org/packages/23/12/8b5fc6b9c487a09a7957188e0943c9ff08432c65e34567cabc1623b03a51/numpy-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:5de60946f14ebe15e713a6f22850c2372fa72f4ff9a432ab44aa90edcadaa65a", size = 6152482, upload-time = "2026-01-10T06:44:36.798Z" },
{ url = "https://files.pythonhosted.org/packages/00/a5/9f8ca5856b8940492fc24fbe13c1bc34d65ddf4079097cf9e53164d094e1/numpy-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:8f085da926c0d491ffff3096f91078cc97ea67e7e6b65e490bc8dcda65663be2", size = 12627117, upload-time = "2026-01-10T06:44:38.828Z" },
{ url = "https://files.pythonhosted.org/packages/ad/0d/eca3d962f9eef265f01a8e0d20085c6dd1f443cbffc11b6dede81fd82356/numpy-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:6436cffb4f2bf26c974344439439c95e152c9a527013f26b3577be6c2ca64295", size = 10667121, upload-time = "2026-01-10T06:44:41.644Z" },
]
[[package]]
name = "pandas"
version = "2.3.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy" },
{ name = "python-dateutil" },
{ name = "pytz" },
{ name = "tzdata" },
]
sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" },
{ url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" },
{ url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" },
{ url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" },
{ url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" },
{ url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" },
{ url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" },
{ url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" },
{ url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" },
{ url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" },
{ url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" },
{ url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" },
{ url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" },
{ url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" },
{ url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" },
{ url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" },
{ url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" },
{ url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" },
{ url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" },
{ url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" },
{ url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" },
{ url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" },
{ url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" },
{ url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" },
{ url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" },
{ url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" },
{ url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" },
{ url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" },
{ url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" },
{ url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" },
{ url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" },
{ url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" },
{ url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" },
]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
]
[[package]]
name = "pytz"
version = "2025.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
]
[[package]]
name = "six"
version = "1.17.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
]
[[package]]
name = "tzdata"
version = "2025.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" },
]
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,533 @@
from datetime import date
from typing import Iterator, Callable
class Service:
"""
Un service deploye.
"""
__slots__ = ('_nom', '_port', '_protocole', '_critique')
def __init__(self, nom: str, port: int, protocole: str, *, critique: bool = False):
self._nom = nom
self._port = port
self._protocole = protocole
self._critique = critique
def est_critique(self) -> bool:
"""Ce service est-il critique pour le SI?"""
return self._critique
def ecoute_sur(self, port: int) -> bool:
"""Ce service ecoute-t-il sur ce port?"""
return self._port == port
def utilise_protocole(self, protocole: str) -> bool:
"""Ce service utilise-t-il ce protocole?"""
return self._protocole.lower() == protocole.lower()
def __eq__(self, autre: object) -> bool:
if not isinstance(autre, Service):
return NotImplemented
return self._nom == autre._nom and self._port == autre._port
def __repr__(self) -> str:
return f"Service({self._nom!r}, {self._port}, {self._protocole!r}, critique={self._critique})"
class Services:
"""
Une collection de services. Encapsule la logique de gestion.
Cet objet sait filtrer, compter, itérer sur ses services.
"""
__slots__ = ('_services',)
def __init__(self, *services: Service):
self._services: tuple[Service, ...] = services
def avec(self, service: Service) -> 'Services':
"""Retourne une nouvelle collection incluant ce service."""
if service in self._services:
return self
return Services(*self._services, service)
def sans(self, service: Service) -> 'Services':
"""Retourne une nouvelle collection sans ce service."""
return Services(*(s for s in self._services if s != service))
def critiques(self) -> 'Services':
"""Retourne uniquement les services critiques."""
return Services(*(s for s in self._services if s.est_critique()))
def sur_port(self, port: int) -> 'Services':
"""Retourne les services écoutant sur ce port."""
return Services(*(s for s in self._services if s.ecoute_sur(port)))
def contient(self, service: Service) -> bool:
"""Cette collection contient-elle ce service?"""
return service in self._services
def est_vide(self) -> bool:
"""Cette collection est-elle vide?"""
return len(self._services) == 0
def __len__(self) -> int:
return len(self._services)
def __iter__(self) -> Iterator[Service]:
return iter(self._services)
def __contains__(self, service: Service) -> bool:
return service in self._services
def __repr__(self) -> str:
return f"Services({', '.join(repr(s) for s in self._services)})"
class Serveur:
"""
Un serveur hebergeant des services.
"""
def __init__(self, nom: str, ip: str, os: str, mise_en_service: date):
self._nom = nom
self._ip = ip
self._os = os
self._mise_en_service = mise_en_service
self._services = Services()
def heberge(self, service: Service) -> None:
"""Ajoute un service a ce serveur."""
self._services = self._services.avec(service)
def retire(self, service: Service) -> None:
"""Retire un service de ce serveur."""
self._services = self._services.sans(service)
def services_critiques(self) -> Services:
"""Retourne les services critiques heberges."""
return self._services.critiques()
def nombre_services(self) -> int:
"""Combien de services ce serveur heberge-t-il?"""
return len(self._services)
def repond_au_nom(self, nom: str) -> bool:
"""Ce serveur repond-il a ce nom?"""
return self._nom == nom
def a_pour_ip(self, ip: str) -> bool:
"""Ce serveur a-t-il cette IP?"""
return self._ip == ip
def fonctionne_sous(self, os: str) -> bool:
"""Ce serveur fonctionne-t-il sous cet OS?"""
return self._os.lower() == os.lower()
def en_service_depuis(self, depuis: date) -> bool:
"""Ce serveur est-il en service depuis au moins cette date?"""
return self._mise_en_service <= depuis
def fiche(self) -> str:
"""Retourne une fiche descriptive complete du serveur."""
lignes = [
f"Serveur: {self._nom}",
f" IP: {self._ip}",
f" OS: {self._os}",
f" En service depuis: {self._mise_en_service}",
f" Services ({len(self._services)}):",
]
for service in self._services:
lignes.append(f" - {service}")
return "\n".join(lignes)
def __eq__(self, autre: object) -> bool:
if not isinstance(autre, Serveur):
return NotImplemented
return self._nom == autre._nom and self._ip == autre._ip
def __len__(self) -> int:
"""Nombre de services heberges."""
return len(self._services)
def __repr__(self) -> str:
return f"Serveur({self._nom!r}, {self._ip!r}, {self._os!r}, {self._mise_en_service!r})"
class ServeurPhysique(Serveur):
"""
Un serveur physique dans un rack.
"""
def __init__(
self,
nom: str,
ip: str,
os: str,
mise_en_service: date,
*,
rack: str,
consommation_kw: float,
sous_garantie: bool = True
):
super().__init__(nom, ip, os, mise_en_service)
self._rack = rack
self._consommation_kw = consommation_kw
self._sous_garantie = sous_garantie
def est_sous_garantie(self) -> bool:
"""Ce serveur est-il encore sous garantie?"""
return self._sous_garantie
def consomme_plus_que(self, seuil_kw: float) -> bool:
"""Ce serveur consomme-t-il plus que le seuil?"""
return self._consommation_kw > seuil_kw
def dans_rack(self, rack: str) -> bool:
"""Ce serveur est-il dans ce rack?"""
return self._rack == rack
def fiche(self) -> str:
"""Retourne une fiche descriptive complete du serveur."""
base = super().fiche()
garantie = "Oui" if self._sous_garantie else "Non"
return "\n".join([
base,
f" Rack: {self._rack}",
f" Consommation: {self._consommation_kw} kW",
f" Sous garantie: {garantie}",
])
def __repr__(self) -> str:
return f"ServeurPhysique({self._nom!r}, rack={self._rack!r})"
class ServeurVirtuel(Serveur):
"""
Un serveur virtuel (VM).
"""
def __init__(
self,
nom: str,
ip: str,
os: str,
mise_en_service: date,
*,
hyperviseur: str,
allocation: str
):
super().__init__(nom, ip, os, mise_en_service)
self._hyperviseur = hyperviseur
self._allocation = allocation
def tourne_sur_hyperviseur(self, hyperviseur: str) -> bool:
"""Cette VM tourne-t-elle sur cet hyperviseur?"""
return self._hyperviseur.lower() == hyperviseur.lower()
def fiche(self) -> str:
"""Retourne une fiche descriptive complete du serveur."""
base = super().fiche()
return "\n".join([
base,
f" Hyperviseur: {self._hyperviseur}",
f" Allocation: {self._allocation}",
])
def __repr__(self) -> str:
return f"ServeurVirtuel({self._nom!r}, hyperviseur={self._hyperviseur!r})"
class Technicien:
"""
Un technicien.
"""
__slots__ = ('_identifiant', '_nom', '_specialite')
def __init__(self, identifiant: str, nom: str, specialite: str):
self._identifiant = identifiant
self._nom = nom
self._specialite = specialite
def est_specialise_en(self, domaine: str) -> bool:
"""Ce technicien est-il specialise dans ce domaine?"""
return self._specialite.lower() == domaine.lower()
def __eq__(self, autre: object) -> bool:
if not isinstance(autre, Technicien):
return NotImplemented
return self._identifiant == autre._identifiant
def __repr__(self) -> str:
return f"Technicien({self._identifiant!r}, {self._nom!r}, {self._specialite!r})"
class Maintenance:
"""
Une intervention de maintenance sur un serveur.
"""
__slots__ = ('_identifiant', '_date', '_type', '_serveur', '_technicien')
PREVENTIVE = "preventive"
CORRECTIVE = "corrective"
def __init__(
self,
identifiant: str,
date_intervention: date,
type_maintenance: str,
serveur: Serveur,
technicien: Technicien
):
if type_maintenance not in (self.PREVENTIVE, self.CORRECTIVE):
raise ValueError(f"Type de maintenance invalide: {type_maintenance}")
self._identifiant = identifiant
self._date = date_intervention
self._type = type_maintenance
self._serveur = serveur
self._technicien = technicien
def concerne_serveur(self, serveur: Serveur) -> bool:
"""Cette maintenance concerne-t-elle ce serveur?"""
return self._serveur == serveur
def effectuee_par(self, technicien: Technicien) -> bool:
"""Cette maintenance a-t-elle ete effectuee par ce technicien?"""
return self._technicien == technicien
def est_preventive(self) -> bool:
"""Est-ce une maintenance preventive?"""
return self._type == self.PREVENTIVE
def est_corrective(self) -> bool:
"""Est-ce une maintenance corrective?"""
return self._type == self.CORRECTIVE
def a_eu_lieu_apres(self, depuis: date) -> bool:
"""Cette maintenance a-t-elle eu lieu après cette date?"""
return self._date >= depuis
def rapport(self) -> str:
"""Retourne un rapport formater de la maintenance."""
sep = "=" * 50
return "\n".join([
sep,
f"MAINTENANCE {self._identifiant}",
sep,
f"Date: {self._date}",
f"Type: {self._type.upper()}",
f"Serveur: {self._serveur}",
f"Technicien: {self._technicien}",
sep,
])
def __eq__(self, autre: object) -> bool:
if not isinstance(autre, Maintenance):
return NotImplemented
return self._identifiant == autre._identifiant
def __repr__(self) -> str:
return f"Maintenance({self._identifiant!r}, {self._date!r}, {self._type!r})"
class Datacenter:
"""
Un datacenter regroupant des serveurs.
"""
def __init__(self, nom: str, localisation: str):
self._nom = nom
self._localisation = localisation
self._serveurs: list[Serveur] = []
self._maintenances: list[Maintenance] = []
def accueille(self, serveur: Serveur) -> None:
"""Accueille un nouveau serveur dans le datacenter."""
if serveur not in self._serveurs:
self._serveurs.append(serveur)
def retire_serveur(self, serveur: Serveur) -> None:
"""Retire un serveur du datacenter."""
if serveur in self._serveurs:
self._serveurs.remove(serveur)
def enregistre(self, maintenance: Maintenance) -> None:
"""Enregistre une maintenance effectuee."""
self._maintenances.append(maintenance)
def services_critiques(self) -> Services:
"""Tous les services critiques heberges dans ce datacenter."""
critiques = []
for serveur in self._serveurs:
for service in serveur.services_critiques():
critiques.append(service)
return Services(*critiques)
def total_services(self) -> int:
"""Nombre total de services heberges."""
return sum(serveur.nombre_services() for serveur in self._serveurs)
def serveurs_maintenus_par(self, technicien: Technicien) -> list[Serveur]:
"""Liste des serveurs ayant ete maintenus par ce technicien."""
serveurs_trouves = []
for maintenance in self._maintenances:
if maintenance.effectuee_par(technicien):
for serveur in self._serveurs:
if maintenance.concerne_serveur(serveur) and serveur not in serveurs_trouves:
serveurs_trouves.append(serveur)
return serveurs_trouves
def pour_chaque_serveur(self, action: Callable[[Serveur], None]) -> None:
"""Applique une action a chaque serveur"""
for serveur in self._serveurs:
action(serveur)
def pour_chaque_serveur_physique(self, action: Callable[[ServeurPhysique], None]) -> None:
"""Applique une action a chaque serveur physique."""
for serveur in self._serveurs:
if isinstance(serveur, ServeurPhysique):
action(serveur)
def inventaire(self) -> str:
"""Retourne l'inventaire complet du datacenter."""
sep = "#" * 60
lignes = [
"",
sep,
f"DATACENTER: {self._nom}",
f"Localisation: {self._localisation}",
sep,
"",
f"Nombre de serveurs: {len(self._serveurs)}",
f"Total services: {self.total_services()}",
f"Services critiques: {len(self.services_critiques())}",
"",
]
for serveur in self._serveurs:
lignes.append(serveur.fiche())
lignes.append("")
return "\n".join(lignes)
def __len__(self) -> int:
"""Nombre de serveurs dans le datacenter."""
return len(self._serveurs)
def __contains__(self, serveur: Serveur) -> bool:
"""Ce serveur est-il dans le datacenter?"""
return serveur in self._serveurs
def __repr__(self) -> str:
return f"Datacenter({self._nom!r}, {self._localisation!r})"
if __name__ == "__main__":
# Creation de services
nginx = Service("nginx", 80, "HTTP", critique=True)
api = Service("api-backend", 8080, "HTTP", critique=True)
ssh = Service("sshd", 22, "TCP")
postgres = Service("postgresql", 5432, "TCP", critique=True)
redis = Service("redis", 6379, "TCP")
# Creation de serveurs
srv_web = ServeurPhysique(
"srv-web-01",
"192.168.1.10",
"Debian 12",
date(2023, 6, 15),
rack="R01-U12",
consommation_kw=0.8,
sous_garantie=True
)
srv_web.heberge(nginx)
srv_web.heberge(ssh)
srv_api = ServeurVirtuel(
"srv-api-01",
"192.168.1.20",
"Ubuntu 22.04",
date(2024, 1, 10),
hyperviseur="Proxmox",
allocation="4 vCPU / 8 Go RAM"
)
srv_api.heberge(api)
srv_api.heberge(redis)
srv_db = ServeurPhysique(
"srv-db-01",
"192.168.1.30",
"Rocky Linux 9",
date(2022, 3, 1),
rack="R02-U08",
consommation_kw=1.2,
sous_garantie=False
)
srv_db.heberge(postgres)
srv_db.heberge(ssh)
# Creation du datacenter
dc_paris = Datacenter("DC-Paris-01", "Paris, France")
dc_paris.accueille(srv_web)
dc_paris.accueille(srv_api)
dc_paris.accueille(srv_db)
# Creation de techniciens
alice = Technicien("T001", "Alice Martin", "Linux")
bob = Technicien("T002", "Bob Dupont", "Virtualisation")
# Creation de maintenances
maint_1 = Maintenance(
"M2024-001",
date(2024, 11, 15),
Maintenance.PREVENTIVE,
srv_web,
alice
)
maint_2 = Maintenance(
"M2024-002",
date(2024, 12, 3),
Maintenance.CORRECTIVE,
srv_db,
alice
)
maint_3 = Maintenance(
"M2025-001",
date(2025, 1, 8),
Maintenance.PREVENTIVE,
srv_api,
bob
)
dc_paris.enregistre(maint_1)
dc_paris.enregistre(maint_2)
dc_paris.enregistre(maint_3)
# Inventaire complet
print(dc_paris.inventaire())
# Services critiques
print("--- SERVICES CRITIQUES ---")
print(dc_paris.services_critiques())
# Serveurs maintenus par Alice
print("\n--- SERVEURS MAINTENUS PAR ALICE ---")
for srv in dc_paris.serveurs_maintenus_par(alice):
print(f" - {srv}")
# Rapport de maintenance
print("\n--- RAPPORT MAINTENANCE ---")
print(maint_1.rapport())
print("\n--- SERVEURS HORS GARANTIE ---")
dc_paris.pour_chaque_serveur_physique(
lambda s: print(f" ! {s}") if not s.est_sous_garantie() else None
)
print("\n--- TEST ÉGALITÉ ---")
nginx_copie = Service("nginx", 80, "HTTPS") # Meme nom/port, protocole different
print(f"nginx == nginx_copie: {nginx == nginx_copie}") # True (egalite sur nom+port)
+28
View File
@@ -0,0 +1,28 @@
def persistance(num: int):
"""
A partir d'un entier positif, renvoie la persistance multiplicative,
à savoir le nombre de fois qu'on peut multiplier les chiffres de l'entier
entre eux jusqu'à un résultat d'un seul chiffre.
Exemples :
4 -> 0
39 -> 3 (3*9=27, 2*7=14, 1*4=4)
"""
if num < 0:
return "Merci d'utiliser un entier positif."
steps = 0
start = num
while len(str(num)) > 1:
base = 1
for n in str(num):
base *= int(n)
steps += 1
num = base
if steps == 0:
return f"Partant de {start}, pas besoin de multiplication."
return f"Partant de {start}, la persistance multiplicative est de {steps} étapes."
+22
View File
@@ -0,0 +1,22 @@
def numeral_square(num: int):
"""
A partir d'un entier positif, renvoie la racine numérique,
à savoir la somme récursive de tous les chiffres d'un nombre.
Exemples :
16 -> 1+6=7
1567 -> 1+5+6+7=19, 1+9=10, 1+0=1
"""
if num < 0:
return "Merci d'utiliser un entier positif."
start = num
while len(str(num)) > 1:
base = 0
for n in str(num):
base += int(n)
num = base
return f"La racine numérique de {start} donne {base}."
+18
View File
@@ -0,0 +1,18 @@
def gen_pyramid(num: int) -> list[str]:
"""
A partir d'un entier, renvoie sous forme de tableau une
pyramide composée d'autant d'étages avec le caractère *
"""
if num == 0:
return ["Merci d'utiliser un entier non nul."]
if num < 0:
num = +abs(num)
pyramid = []
for n in range(num):
white_spaces = ' ' * (num - n - 1)
bloc_spaces = '*' * (2 * n + 1)
pyramid.append(f"{white_spaces}{bloc_spaces}{white_spaces}")
return pyramid
+45
View File
@@ -0,0 +1,45 @@
from datetime import date, time, datetime, timedelta
from pprint import pprint
from exo_01 import persistance
from exo_02 import numeral_square
from exo_03 import gen_pyramid
from prog_or_obj import Service,\
ServeurPhysique,\
ServeurVirtuel,\
Technicien,\
Maintenance,\
Datacenter
# Exercice 1
print("\n----- Exercice [1] -----\n")
exo_1_test_list = [-7, 4, 39, 999]
for test in exo_1_test_list:
print(persistance(test))
# Exercice 2
print("\n----- Exercice [2] -----\n")
exo_2_test_list = [-7, 16, 942, 132189, 493193]
for test in exo_2_test_list:
print(numeral_square(test))
# Exercice 3
print("\n----- Exercice [3] -----\n")
exo_3_test_list = [-7, 0, 6, 12]
for test in exo_3_test_list:
pprint(gen_pyramid(test), width= 30)
# Exercice de Programmation Orientée Objet - Centre de données
today = date.today()
two_days_ago = date.today() - timedelta(days= 2)
five_days_ago = date.today() - timedelta(days= 5)
service_01 = Service("HTTP", 80, "TCP", True)
service_02 = Service("HTTPS", "443", "TCP", True)
service_03 = Service("PostGresql", 5432, "TCP", False)
service_04 = Service("Counter-Strike LAN", 36729, "UDP", False)
server_physical_01 = ServeurPhysique("Thorium", "10.10.19.94", "Debian 13", today, "HP version 4.2", 45, True)
server_physical_02 = ServeurPhysique("Iridium", "10.10.18.94", "Arch Linux 4", two_days_ago, "HP version 4.2", 37, True)
server_physical_03 = ServeurPhysique("Polonium", "10.10.17.94", "Apple Server mdr", five_days_ago, "HP version 3.3", 445, False)
+255
View File
@@ -0,0 +1,255 @@
from datetime import date
import json
class Service:
"""
Application déployée sur un serveur.
"""
def __init__(self, name: str, port: str | int, protocol: str, is_critical: bool):
self.name = name
self.port = int(port)
self.protocol = protocol
self.is_critical = is_critical
def __eq__(self, other: "Service"):
return self.name == other.name and self.port == other.port
def serialized_services(self):
"""Converti la classe \"Services\" en dictionnaire JSONable"""
return {
"Name": self.name,
"Port": self.port,
"Protocol": self.protocol,
"Is_Critical": self.is_critical,
}
@classmethod
def deserialized_services(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe \"Services\""""
return cls(
name= dictionnary["Name"],
port= dictionnary["Port"],
protocol= dictionnary["Protocol"],
is_critical= dictionnary["Is_Critical"],
)
class Serveur:
"""
Serveur, classe maîtresse. NE PAS UTILISER DIRECTEMENT.
Préférez les classes héritées :
- ServeurPhysique
- ServeurVirtuel
"""
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date):
self.name = name
self.ip_address = ip_address
self.os_name = os_name
self.commission_date = commission_date
self.services = self.load_services()
def __str__(self) -> str:
return f"\
[Serveur] > {self.name}\n\
[Addresse IP] > {self.ip_address}\n\
[Système d'Exploitation] > {self.os_name}\n\
[Date de mise en prod] > {self.commission_date}"
def __len__(self) -> int:
return len(self.services)
def list_services(self):
return self.services
def add_service(self, service: Service):
"""Ajout d'un service à la liste des services disponibles"""
if service in self.services:
return f"Le service [{service.name.capitalize()}] est déjà présent."
self.services.append(service)
self.save_services()
return f"{service.name.capitalize()} a été ajouté."
def remove_service(self, service_str: str):
"""Retire un service de la liste des services disponibles"""
for service in self.services:
if service.name.lower() == service_str.lower()\
or str(service.port) == service_str.lower()\
or service.protocol.lower() == service_str.lower():
self.services.remove(service)
self.save_services()
return f"{service.name.capitalize} a été retiré."
return f"{service.name.capitalize()} n'est pas dans la liste."
def serialized_servers(self):
"""Converti la classe \"Services\" en dictionnaire JSONable"""
return {
"Name": self.name,
"IP_Address": self.ip_address,
"OS_Name": self.os_name,
"Commission_Date": self.commission_date,
}
@classmethod
def deserialized_servers(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe \"Services\""""
return cls(
name= dictionnary["Name"],
ip_address= dictionnary["IP_Address"],
os_name= dictionnary["OS_Name"],
commission_date= dictionnary["Commission_Date"],
)
def save_services(self):
"""
Inscris dans un fichier JSON le contenu des services disponibles
"""
services_dict = [services.serialized_services() for services in self.services]
with open("services.json", "w", encoding= "utf-8") as json_file:
json.dump(services_dict, json_file, indent= 4)
def load_services(self) -> list[Service]:
"""
Récupère le contenu d'un fichier JSON contenant les services
"""
with open("services.json", encoding= "utf-8") as json_file:
return json.load(json_file, object_hook= Service.deserialized_services)
class ServeurPhysique(Serveur):
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date, rack: str, electric_cons: int, warranty: bool):
super().__init__(name, ip_address, os_name, commission_date)
self.rack = rack
self.electric_cons = electric_cons
warranty_bools = ("Non", "Oui")
self.warranty = warranty_bools[warranty]
def __str__(self) -> str:
return f"\
{super().__str__()}\n\
[Châssis] > {self.rack}\n\
[Consommation en kWh] > {self.electric_cons}\n\
[Sous garantie] > {self.warranty}"
def __len__(self) -> int:
return super().__len__()
class ServeurVirtuel(Serveur):
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date, hypervisor: str, vcpus: int, giga_ram: float):
super().__init__(name, ip_address, os_name, commission_date)
self.hypervisor = hypervisor
self.vcpus = vcpus
self.giga_ram = giga_ram
def __str__(self) -> str:
return f"\
{super().__str__()}\n\
[Hyperviseur] > {self.hypervisor}\n\
[Coeurs virtuels] > {self.vcpus}\n\
[Mémoire vive (Go)] > {self.giga_ram}"
def __len__(self) -> int:
return super().__len__()
class Maintenance:
def __init__(self, id: int, commission_date: date, type: str, affected_technician: "Technicien", associated_server: "ServeurPhysique | ServeurVirtuel"):
self.id = id
self.commission_date = commission_date
self.type = type
self.affected_technician = affected_technician
self.associated_server = associated_server
def __str__(self) -> str:
return f"\
[ID] > {self.id}\n\
[Serveur associé] > {self.associated_server}\n\
[Date de mise en prod] > {self.commission_date}\n\
[Type de maintenance] > {self.type}\n\
[Technicien affecté] > {self.affected_technician}"
# J'ai le sentiment que ce n'est PAS ce qui est demandé. Mais il est 16h25 et je n'ai plus d'idée sur comment le faire
def link_to_server(self, server: ServeurPhysique | ServeurVirtuel):
return f"La maintenance est liée au serveur {server.name.upper()}, addresse IP {server.ip_address}."
def serialized_maintenances(self):
"""Converti la classe \"Maintenance\" en dictionnaire JSONable"""
return {
"ID": self.id,
"Associated_Server": self.associated_server,
"Commission_Date": self.commission_date,
"Type": self.type,
"Affected_Technician": self.affected_technician,
}
@classmethod
def deserialized_maintenances(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe \"Maintenance\""""
return cls(
id= dictionnary["ID"],
associated_server= dictionnary["Associated_Server"],
commission_date= dictionnary["Commission_Date"],
type= dictionnary["Type"],
affected_technician= dictionnary["Affected_Technician"],
)
class Technicien:
def __init__(self, fullname: str, speciality: str, id: int):
self.name = fullname
self.speciality = speciality
self.id = id
self.maintenances = self.load_maintenances()
def list_affected_jobs(self):
return self.maintenances
def affect_maintenance(self):
pass
def save_maintenances(self):
"""
Inscris dans un fichier JSON le contenu des maintenances disponibles
"""
maintenances_dict = [maintenances.serialized_maintenances() for maintenances in self.maintenances]
with open("maintenances.json", "w", encoding= "utf-8") as json_file:
json.dump(maintenances_dict, json_file, indent= 4)
def load_maintenances(self) -> list[Maintenance]:
"""
Récupère le contenu d'un fichier JSON contenant les maintenances
"""
with open("maintenances.json", encoding= "utf-8") as json_file:
return json.load(json_file, object_hook= Maintenance.deserialized_maintenances)
class Datacenter:
def __init__(self, name: str, location: str, id: int):
self.name = name
self.location = location
self.id = id
self.servers = self.load_servers()
def list_servers(self):
return self.servers
def list_critical_services(self):
for server in self.servers:
server.list_services()
# Là j'ai cherché à récupérer un genre de 'if server.list_services().is_critical'
# pour avoir le "True/False" et renvoyer le résultat en cas de "True" mais j'ai craqué
def list_services_number(self):
services = 0
for server in self.servers:
services += len(server)
return services
def save_servers(self):
"""
Inscris dans un fichier JSON le contenu des serveurs disponibles
"""
servers_dict = [servers.serialized_servers() for servers in self.servers]
with open("servers.json", "w", encoding= "utf-8") as json_file:
json.dump(servers_dict, json_file, indent= 4)
def load_servers(self) -> list[Serveur]:
"""
Récupère le contenu d'un fichier JSON contenant les serveurs
"""
with open("servers.json", encoding= "utf-8") as json_file:
return json.load(json_file, object_hook= Serveur.deserialized_servers)
+66
View File
@@ -0,0 +1,66 @@
# Les bases de Python
## UV (NPM de Python)
*Je suis sur Windows, les commandes divergent sur UNIX(like)
Pour installer UV, remplaçant PIP et consorts (évidemment codé en RUST) :
https://docs.astral.sh/uv/#projects
Dans le dossier de travail :
`uv init --python 3.12`
Et dans le dossier initialisé :
```sh
.venv\Scripts\activate
uv run main.py
# On peut aussi activer le .venv en l'initialisation plus avant en intervertissant les commandes, donc :
uv run main.py
.venv\Scripts\activate
```
## Quelques bases oubliées
### Fonctions
Une fonction appelle un résultat.
```py
fonction(variable)
```
Définir une fonction :
```py
def fonction():
return true
```
On peut forcer le type des variables d'une fonction :
```py
def fonction(a: int, b: int):
somme = a + b
return somme
```
Et même une valeur par défaut
```py
def fonction(a: int, b: int = 5):
somme = a + b
return somme
```
### Méthodes
Une méthode suit une variable.
```py
variable.methode("Valeur")
```
+136
View File
@@ -0,0 +1,136 @@
## Fonctions LAMBDA
## Méthodes et fonctions avancées
### Données déstructurées
dc_infos = ("Dale", "Cooper", "32")
dc_prenom = dc_infos[0]
dc_nom = dc_infos[1]
dc_age = dc_infos[2]
dc_prenom, dc_nom, dc_age = dc_infos
### Surcharge de méthode
```py
range(10) # [0,1,2,3,4,5,6,7,8,9]
range(2, 10) # [2,3,4,5,6,7,8,9]
range(2, 10, 2) # [2,4,6,8]
```
### A la place de `return` => `yield`
```py
def generator():
for i in range(10):
return i
```
Renverra [0], `return` étant un arrêt.
Alors que :
```py
def generator():
for i in range(10):
yield i
```
Va renvoyer : `<function generator at 0x000002584950E340>`
### Générateurs
La fonction `next` permet d'économiser des ressources en mettant en mémoire la fonction et sa position. Par exemple :
```py
def square_generator(n):
for i in range(n):
yield i ** 2
```
Renverra `<function square_generator at 0x000001351A12E3E0>`. Maintenant, on utilise :
```py
squares = square_generator(10)
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
```
Renverra :
```
0
1
4
9
16
25
36
49
```
### Return, Yield et Continue
```py
for square in generator:
if square > 50: # Si le carré est supérieur à 50, la boucle cesse
break
if square % 2 == 0: # Si le carré est pair, on le zappe
continue
print(square)
```
## Format String
Le classique :
```py
print("La lettre " + variable_str + " apparaît " + variable_int + " fois.")
```
Se remplace bien par :
```py
print(f"La lettre {variable_str} apparaît {variable_int} fois.")
```
Le `%s` c'est un peu démodé face au f-string, franchement.
## Listes de compréhension
Pour peupler une liste avec des formules, on peut faire du standard :
```py
liste = []
for i in range(5)
liste.append(i)
print(liste) # [0, 1, 2, 3, 4]
```
Ou, une liste compréhensive, contenant l'algo de base amenant le résultat :
```py
liste = [i for i in range(5)]
print(liste) # [0, 1, 2, 3, 4]
```
Et même inclure des conditions :
```py
liste = [i for i in range(5) if i % 2 == 0]
print(liste) # [0, 2, 4]
```
+61
View File
@@ -0,0 +1,61 @@
## Sérialisation, Dé-sérialisation
Sérialisation => On prend des objets, on transforme en JSON
Dé-sérialisation => On prend un JSON, on transforme en objets
### Exemple de sérialisation
On prend une liste classique
```py
livres = [{"titre": "1984", "auteur": "Orwell"}, {"titre": "LSDA", "auteur": "Tolkien"}]
```
On peut donc traiter un fichier JSON avec la fonction `open` et le sérialiser avec `dump` :
```py
import json
livres = [{"titre": "1984", "auteur": "Orwell"}, {"titre": "LSDA", "auteur": "Tolkien"}]
# file=/path/ , w-rite
fichier_json = open("livres.json", "w")
json.dump(livres, fichier_json)
fichier_json.close()
```
Ou, avec un `Context-Manager` au lieu d'ouvrir et de fermer :
```py
import json
livres = [{"titre": "1984", "auteur": "Orwell"}, {"titre": "LSDA", "auteur": "Tolkien"}]
with open("livres.json", "w") as fichier_json:
json.dump(livres, fichier_json, indent= 4)
```
### Exemple de dé-sérialisation
```py
import json
livres = [{"titre": "1984", "auteur": "Orwell"}, {"titre": "LSDA", "auteur": "Tolkien"}]
with open("livres.json", "w") as fichier_json:
objet = json.load(fichier_json)
print(objet)
objet.append({"titre": "Alice aux pays", "auteur": "Caroll"})
with open("livres.json", "w") as fichier_json:
json.dump(objet, fichier_json, indent= 4)
```
## Les classes
### Méthodes "Dunder"
- __init__
- __repr__
+14
View File
@@ -0,0 +1,14 @@
## Front-End facile et rapide
### QT Designer
Créer une interface
### PyQt6
```py
uv add pyqt6
.\.venv\Scripts\activate
# Ensuite on récupère le fichier .ui créé par QT Designer et on le convertie n .py
pyuic6 .\gui\library.ui -o .\gui\ui_library.py
```
+26
View File
@@ -0,0 +1,26 @@
## TYPE_CHECKING
En cas d'import circulaire de dépendance, un conflit peut apparaitre :
```py
# dans main.py :
from classes.py import dependance_01
```
```py
# dans classes.py :
from main.py import dependance_02
```
La lecture des fichiers par Python peut conduire à une boucle où chacun fichier lit l'autre et bloque sur un import. On utilise alors dans la dépendance secondaire :
```py
# dans classes.py :
if TYPE_CHECKING:
from main.py import dependance_02
```
Pour sortir de la boucle.
+1
View File
@@ -0,0 +1 @@
3.12
View File
+59
View File
@@ -0,0 +1,59 @@
import fractions
class Fraction:
numerator = 1
denominator = 1
def __init__(self, numerator, denominator):
self.numerator = numerator
self.denominator = denominator
self.simplifier()
def __mul__(self, factor: int | Self):
if isinstance(factor, int):
return Fraction(
numerator = self.numerator * factor,
denominator = self.denominator
)
return Fraction(
numerator = self.numerator * factor.numerator,
denominator = self.denominator * factor.denominator
)
def __rmul__(self, number: int):
return self.__mul__(number)
def quotient(self):
"""[Fraction] Chiffre sur Chiffre"""
return self.numerator / self.denominator
def plus(self, fraction):
"""[Fraction] Addition de deux fractions"""
num = (self.numerator * self.denominator) + (self.denominator + fraction.numerator)
den = self.denominator * fraction.denominator
return Fraction(numerator= num, denominator= den)
@staticmethod
def pgcd( a, b):
"""Calcul du PGCD de deux entiers naturels"""
if b == 0:return a
return Fraction.pgcd(a= b, b= a % b)
def simplifier(self):
a = self.numerator
b = self.denominator
pgcd = Fraction.pgcd(a, b)
self.numerator = self.numerator // pgcd # // force la division à ne PAS donner de float
self.denominator //= pgcd # C'est la même chose que dessus
def __repr__(self):
return f"Fraction({self.numerator}/{self.denominator})"
tiers = Fraction(numerator= 1, denominator= 3)
quart = Fraction(1, 4)
fraction = tiers.plus(quart)
print(fraction)
+38
View File
@@ -0,0 +1,38 @@
from pprint import pprint
prenom = "John" # crée une instance (obj) de type 'str' et l'initialise avec la valeur 'John'
nom = str('Doe') # crée une instance (obj) de type 'str' et l'initialise avec la valeur 'Doe'
adress = str() # crée une instance (obj) de type 'str'
# list, dict, tuple, set, bool => types primitives
class Fraction: # pour se differencier des types primitifs
numerateur = 1
denominateur = 1
def quotient(self): # self = tiers /quart
return self.numerateur / self.denominateur
tiers = Fraction() # crée une instance (obj) de type 'Fraction'
tiers.numerateur = 1
tiers.denominateur = 3
quart = Fraction()
quart.numerateur = 1
quart.denominateur = 4
print(tiers.__dict__)
print(quart.__dict__)
# Mapping proxy
# pprint(Fraction.__dict__)
# pprint(tiers.__dict__)
# print(tiers.denominateur)
# 2 points de vue: Fraction (classe) et tiers (objet)
print(Fraction.quotient) # <function Fraction.dire_bonjour at 0x100eec720>
print(tiers.quotient) # <bound method Fraction.dire_bonjour of <__main__.Fraction object at 0x1028937d0>>
# <bound method Fraction.dire_bonjour of tiers>
print(tiers.quotient()) # TypeError: Fraction.dire_bonjour() takes 0 positional arguments but 1 was given
# Les methodes lies aux objets ont besoin de savoir QUI les a appeler
print(quart.quotient())
View File
+7
View File
@@ -0,0 +1,7 @@
[project]
name = "progorobj"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
+8
View File
@@ -0,0 +1,8 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "progorobj"
version = "0.1.0"
source = { virtual = "." }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.