mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-22 10:46:06 +02:00
Merge pull request #1865 from cisagov/dk/1769-epp-connections
Issue #1769: EPP connection failures
This commit is contained in:
commit
a4568a89ba
14 changed files with 647 additions and 1044 deletions
|
@ -29,7 +29,7 @@ django-login-required-middleware = "*"
|
|||
greenlet = "*"
|
||||
gevent = "*"
|
||||
fred-epplib = {git = "https://github.com/cisagov/epplib.git", ref = "master"}
|
||||
geventconnpool = {git = "https://github.com/rasky/geventconnpool.git", ref = "1bbb93a714a331a069adf27265fe582d9ba7ecd4"}
|
||||
tblib = "*"
|
||||
|
||||
[dev-packages]
|
||||
django-debug-toolbar = "*"
|
||||
|
|
583
src/Pipfile.lock
generated
583
src/Pipfile.lock
generated
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "a672aeb8951fd850e90ad87c6f03cf71e2fc2b387d56fd3942361cb0b45bb449"
|
||||
"sha256": "b5d93b1b9ccafc37019276a222957544bab3f1f46b5dab8a0f2ffc2e5c9e1678"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
|
@ -32,29 +32,29 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:65acfe7f1cf2a9b7df3d4edb87c8022e02685825bd1957e7bb678cc0d09f5e5f",
|
||||
"sha256:73f5ec89cb3ddb3ed577317889fd2f2df783f66b6502a9a4239979607e33bf74"
|
||||
"sha256:8b3f5cc7fbedcbb22271c328039df8a6ab343001e746e0cdb24774c426cadcf8",
|
||||
"sha256:f201b6a416f809283d554c652211eecec9fe3a52ed4063dab3f3e7aea7571d9c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.34.37"
|
||||
"version": "==1.34.54"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:2a5bf33aacd2d970afd3d492e179e06ea98a5469030d5cfe7a2ad9995f7bb2ef",
|
||||
"sha256:3c46ddb1679e6ef45ca78b48665398636bda532a07cd476e4b500697d13d9a99"
|
||||
"sha256:4061ff4be3efcf53547ebadf2c94d419dfc8be7beec24e9fa1819599ffd936fa",
|
||||
"sha256:bf215d93e9d5544c593962780d194e74c6ee40b883d0b885e62ef35fc0ec01e5"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.34.37"
|
||||
"version": "==1.34.54"
|
||||
},
|
||||
"cachetools": {
|
||||
"hashes": [
|
||||
"sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2",
|
||||
"sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"
|
||||
"sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945",
|
||||
"sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==5.3.2"
|
||||
"version": "==5.3.3"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
|
@ -228,41 +228,41 @@
|
|||
},
|
||||
"cryptography": {
|
||||
"hashes": [
|
||||
"sha256:087887e55e0b9c8724cf05361357875adb5c20dec27e5816b653492980d20380",
|
||||
"sha256:09a77e5b2e8ca732a19a90c5bca2d124621a1edb5438c5daa2d2738bfeb02589",
|
||||
"sha256:130c0f77022b2b9c99d8cebcdd834d81705f61c68e91ddd614ce74c657f8b3ea",
|
||||
"sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65",
|
||||
"sha256:28cb2c41f131a5758d6ba6a0504150d644054fd9f3203a1e8e8d7ac3aea7f73a",
|
||||
"sha256:2f9f14185962e6a04ab32d1abe34eae8a9001569ee4edb64d2304bf0d65c53f3",
|
||||
"sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008",
|
||||
"sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1",
|
||||
"sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2",
|
||||
"sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635",
|
||||
"sha256:4383b47f45b14459cab66048d384614019965ba6c1a1a141f11b5a551cace1b2",
|
||||
"sha256:44c95c0e96b3cb628e8452ec060413a49002a247b2b9938989e23a2c8291fc90",
|
||||
"sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee",
|
||||
"sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a",
|
||||
"sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242",
|
||||
"sha256:5ef9bc3d046ce83c4bbf4c25e1e0547b9c441c01d30922d812e887dc5f125c12",
|
||||
"sha256:5fa82a26f92871eca593b53359c12ad7949772462f887c35edaf36f87953c0e2",
|
||||
"sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d",
|
||||
"sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be",
|
||||
"sha256:841ec8af7a8491ac76ec5a9522226e287187a3107e12b7d686ad354bb78facee",
|
||||
"sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6",
|
||||
"sha256:8e88bb9eafbf6a4014d55fb222e7360eef53e613215085e65a13290577394529",
|
||||
"sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929",
|
||||
"sha256:a047682d324ba56e61b7ea7c7299d51e61fd3bca7dad2ccc39b72bd0118d60a1",
|
||||
"sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6",
|
||||
"sha256:ad28cff53f60d99a928dfcf1e861e0b2ceb2bc1f08a074fdd601b314e1cc9e0a",
|
||||
"sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446",
|
||||
"sha256:b97fe7d7991c25e6a31e5d5e795986b18fbbb3107b873d5f3ae6dc9a103278e9",
|
||||
"sha256:e0ec52ba3c7f1b7d813cd52649a5b3ef1fc0d433219dc8c93827c57eab6cf888",
|
||||
"sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4",
|
||||
"sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33",
|
||||
"sha256:fbeb725c9dc799a574518109336acccaf1303c30d45c075c665c0793c2f79a7f"
|
||||
"sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee",
|
||||
"sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576",
|
||||
"sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d",
|
||||
"sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30",
|
||||
"sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413",
|
||||
"sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb",
|
||||
"sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da",
|
||||
"sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4",
|
||||
"sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd",
|
||||
"sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc",
|
||||
"sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8",
|
||||
"sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1",
|
||||
"sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc",
|
||||
"sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e",
|
||||
"sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8",
|
||||
"sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940",
|
||||
"sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400",
|
||||
"sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7",
|
||||
"sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16",
|
||||
"sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278",
|
||||
"sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74",
|
||||
"sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec",
|
||||
"sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1",
|
||||
"sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2",
|
||||
"sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c",
|
||||
"sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922",
|
||||
"sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a",
|
||||
"sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6",
|
||||
"sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1",
|
||||
"sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e",
|
||||
"sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac",
|
||||
"sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==42.0.2"
|
||||
"version": "==42.0.5"
|
||||
},
|
||||
"defusedxml": {
|
||||
"hashes": [
|
||||
|
@ -330,11 +330,11 @@
|
|||
},
|
||||
"django-csp": {
|
||||
"hashes": [
|
||||
"sha256:01443a07723f9a479d498bd7bb63571aaa771e690f64bde515db6cdb76e8041a",
|
||||
"sha256:01eda02ad3f10261c74131cdc0b5a6a62b7c7ad4fd017fbefb7a14776e0a9727"
|
||||
"sha256:19b2978b03fcd73517d7d67acbc04fbbcaec0facc3e83baa502965892d1e0719",
|
||||
"sha256:ef0f1a9f7d8da68ae6e169c02e9ac661c0ecf04db70e0d1d85640512a68471c0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.7"
|
||||
"version": "==3.8"
|
||||
},
|
||||
"django-fsm": {
|
||||
"hashes": [
|
||||
|
@ -384,12 +384,12 @@
|
|||
},
|
||||
"faker": {
|
||||
"hashes": [
|
||||
"sha256:60e89e5c0b584e285a7db05eceba35011a241954afdab2853cb246c8a56700a2",
|
||||
"sha256:b7f76bb1b2ac4cdc54442d955e36e477c387000f31ce46887fb9722a041be60b"
|
||||
"sha256:117ce1a2805c1bc5ca753b3dc6f9d567732893b2294b827d3164261ee8f20267",
|
||||
"sha256:458d93580de34403a8dec1e8d5e6be2fee96c4deca63b95d71df7a6a80a690de"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==23.1.0"
|
||||
"version": "==23.3.0"
|
||||
},
|
||||
"fred-epplib": {
|
||||
"git": "https://github.com/cisagov/epplib.git",
|
||||
|
@ -404,61 +404,59 @@
|
|||
},
|
||||
"future": {
|
||||
"hashes": [
|
||||
"sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"
|
||||
"sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216",
|
||||
"sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.18.3"
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"gevent": {
|
||||
"hashes": [
|
||||
"sha256:272cffdf535978d59c38ed837916dfd2b5d193be1e9e5dcc60a5f4d5025dd98a",
|
||||
"sha256:2c7b5c9912378e5f5ccf180d1fdb1e83f42b71823483066eddbe10ef1a2fcaa2",
|
||||
"sha256:36a549d632c14684bcbbd3014a6ce2666c5f2a500f34d58d32df6c9ea38b6535",
|
||||
"sha256:4368f341a5f51611411ec3fc62426f52ac3d6d42eaee9ed0f9eebe715c80184e",
|
||||
"sha256:43daf68496c03a35287b8b617f9f91e0e7c0d042aebcc060cadc3f049aadd653",
|
||||
"sha256:455e5ee8103f722b503fa45dedb04f3ffdec978c1524647f8ba72b4f08490af1",
|
||||
"sha256:45792c45d60f6ce3d19651d7fde0bc13e01b56bb4db60d3f32ab7d9ec467374c",
|
||||
"sha256:4e24c2af9638d6c989caffc691a039d7c7022a31c0363da367c0d32ceb4a0648",
|
||||
"sha256:52b4abf28e837f1865a9bdeef58ff6afd07d1d888b70b6804557e7908032e599",
|
||||
"sha256:52e9f12cd1cda96603ce6b113d934f1aafb873e2c13182cf8e86d2c5c41982ea",
|
||||
"sha256:5f3c781c84794926d853d6fb58554dc0dcc800ba25c41d42f6959c344b4db5a6",
|
||||
"sha256:62d121344f7465e3739989ad6b91f53a6ca9110518231553fe5846dbe1b4518f",
|
||||
"sha256:65883ac026731ac112184680d1f0f1e39fa6f4389fd1fc0bf46cc1388e2599f9",
|
||||
"sha256:707904027d7130ff3e59ea387dddceedb133cc742b00b3ffe696d567147a9c9e",
|
||||
"sha256:72c002235390d46f94938a96920d8856d4ffd9ddf62a303a0d7c118894097e34",
|
||||
"sha256:7532c17bc6c1cbac265e751b95000961715adef35a25d2b0b1813aa7263fb397",
|
||||
"sha256:78eebaf5e73ff91d34df48f4e35581ab4c84e22dd5338ef32714264063c57507",
|
||||
"sha256:7c1abc6f25f475adc33e5fc2dbcc26a732608ac5375d0d306228738a9ae14d3b",
|
||||
"sha256:7c28e38dcde327c217fdafb9d5d17d3e772f636f35df15ffae2d933a5587addd",
|
||||
"sha256:7ccf0fd378257cb77d91c116e15c99e533374a8153632c48a3ecae7f7f4f09fe",
|
||||
"sha256:921dda1c0b84e3d3b1778efa362d61ed29e2b215b90f81d498eb4d8eafcd0b7a",
|
||||
"sha256:a2898b7048771917d85a1d548fd378e8a7b2ca963db8e17c6d90c76b495e0e2b",
|
||||
"sha256:a3c5e9b1f766a7a64833334a18539a362fb563f6c4682f9634dea72cbe24f771",
|
||||
"sha256:ada07076b380918829250201df1d016bdafb3acf352f35e5693b59dceee8dd2e",
|
||||
"sha256:b101086f109168b23fa3586fccd1133494bdb97f86920a24dc0b23984dc30b69",
|
||||
"sha256:bf456bd6b992eb0e1e869e2fd0caf817f0253e55ca7977fd0e72d0336a8c1c6a",
|
||||
"sha256:bf7af500da05363e66f122896012acb6e101a552682f2352b618e541c941a011",
|
||||
"sha256:c3e5d2fa532e4d3450595244de8ccf51f5721a05088813c1abd93ad274fe15e7",
|
||||
"sha256:c84d34256c243b0a53d4335ef0bc76c735873986d478c53073861a92566a8d71",
|
||||
"sha256:d163d59f1be5a4c4efcdd13c2177baaf24aadf721fdf2e1af9ee54a998d160f5",
|
||||
"sha256:d57737860bfc332b9b5aa438963986afe90f49645f6e053140cfa0fa1bdae1ae",
|
||||
"sha256:dbb22a9bbd6a13e925815ce70b940d1578dbe5d4013f20d23e8a11eddf8d14a7",
|
||||
"sha256:dcb8612787a7f4626aa881ff15ff25439561a429f5b303048f0fca8a1c781c39",
|
||||
"sha256:dd6c32ab977ecf7c7b8c2611ed95fa4aaebd69b74bf08f4b4960ad516861517d",
|
||||
"sha256:de350fde10efa87ea60d742901e1053eb2127ebd8b59a7d3b90597eb4e586599",
|
||||
"sha256:e1ead6863e596a8cc2a03e26a7a0981f84b6b3e956101135ff6d02df4d9a6b07",
|
||||
"sha256:ed7a048d3e526a5c1d55c44cb3bc06cfdc1947d06d45006cc4cf60dedc628904",
|
||||
"sha256:f632487c87866094546a74eefbca2c74c1d03638b715b6feb12e80120960185a",
|
||||
"sha256:fae8d5b5b8fa2a8f63b39f5447168b02db10c888a3e387ed7af2bd1b8612e543",
|
||||
"sha256:fde6402c5432b835fbb7698f1c7f2809c8d6b2bd9d047ac1f5a7c1d5aa569303"
|
||||
"sha256:03aa5879acd6b7076f6a2a307410fb1e0d288b84b03cdfd8c74db8b4bc882fc5",
|
||||
"sha256:117e5837bc74a1673605fb53f8bfe22feb6e5afa411f524c835b2ddf768db0de",
|
||||
"sha256:141a2b24ad14f7b9576965c0c84927fc85f824a9bb19f6ec1e61e845d87c9cd8",
|
||||
"sha256:14532a67f7cb29fb055a0e9b39f16b88ed22c66b96641df8c04bdc38c26b9ea5",
|
||||
"sha256:1dffb395e500613e0452b9503153f8f7ba587c67dd4a85fc7cd7aa7430cb02cc",
|
||||
"sha256:2955eea9c44c842c626feebf4459c42ce168685aa99594e049d03bedf53c2800",
|
||||
"sha256:2ae3a25ecce0a5b0cd0808ab716bfca180230112bb4bc89b46ae0061d62d4afe",
|
||||
"sha256:2e9ac06f225b696cdedbb22f9e805e2dd87bf82e8fa5e17756f94e88a9d37cf7",
|
||||
"sha256:368a277bd9278ddb0fde308e6a43f544222d76ed0c4166e0d9f6b036586819d9",
|
||||
"sha256:3adfb96637f44010be8abd1b5e73b5070f851b817a0b182e601202f20fa06533",
|
||||
"sha256:3d5325ccfadfd3dcf72ff88a92fb8fc0b56cacc7225f0f4b6dcf186c1a6eeabc",
|
||||
"sha256:432fc76f680acf7cf188c2ee0f5d3ab73b63c1f03114c7cd8a34cebbe5aa2056",
|
||||
"sha256:44098038d5e2749b0784aabb27f1fcbb3f43edebedf64d0af0d26955611be8d6",
|
||||
"sha256:5a1df555431f5cd5cc189a6ee3544d24f8c52f2529134685f1e878c4972ab026",
|
||||
"sha256:6c47ae7d1174617b3509f5d884935e788f325eb8f1a7efc95d295c68d83cce40",
|
||||
"sha256:6f947a9abc1a129858391b3d9334c45041c08a0f23d14333d5b844b6e5c17a07",
|
||||
"sha256:782a771424fe74bc7e75c228a1da671578c2ba4ddb2ca09b8f959abdf787331e",
|
||||
"sha256:7899a38d0ae7e817e99adb217f586d0a4620e315e4de577444ebeeed2c5729be",
|
||||
"sha256:7b00f8c9065de3ad226f7979154a7b27f3b9151c8055c162332369262fc025d8",
|
||||
"sha256:8f4b8e777d39013595a7740b4463e61b1cfe5f462f1b609b28fbc1e4c4ff01e5",
|
||||
"sha256:90cbac1ec05b305a1b90ede61ef73126afdeb5a804ae04480d6da12c56378df1",
|
||||
"sha256:918cdf8751b24986f915d743225ad6b702f83e1106e08a63b736e3a4c6ead789",
|
||||
"sha256:9202f22ef811053077d01f43cc02b4aaf4472792f9fd0f5081b0b05c926cca19",
|
||||
"sha256:94138682e68ec197db42ad7442d3cf9b328069c3ad8e4e5022e6b5cd3e7ffae5",
|
||||
"sha256:968581d1717bbcf170758580f5f97a2925854943c45a19be4d47299507db2eb7",
|
||||
"sha256:9d8d0642c63d453179058abc4143e30718b19a85cbf58c2744c9a63f06a1d388",
|
||||
"sha256:a7ceb59986456ce851160867ce4929edaffbd2f069ae25717150199f8e1548b8",
|
||||
"sha256:b9913c45d1be52d7a5db0c63977eebb51f68a2d5e6fd922d1d9b5e5fd758cc98",
|
||||
"sha256:bde283313daf0b34a8d1bab30325f5cb0f4e11b5869dbe5bc61f8fe09a8f66f3",
|
||||
"sha256:bf5b9c72b884c6f0c4ed26ef204ee1f768b9437330422492c319470954bc4cc7",
|
||||
"sha256:ca80b121bbec76d7794fcb45e65a7eca660a76cc1a104ed439cdbd7df5f0b060",
|
||||
"sha256:cdf66977a976d6a3cfb006afdf825d1482f84f7b81179db33941f2fc9673bb1d",
|
||||
"sha256:d4faf846ed132fd7ebfbbf4fde588a62d21faa0faa06e6f468b7faa6f436b661",
|
||||
"sha256:d7f87c2c02e03d99b95cfa6f7a776409083a9e4d468912e18c7680437b29222c",
|
||||
"sha256:dd23df885318391856415e20acfd51a985cba6919f0be78ed89f5db9ff3a31cb",
|
||||
"sha256:f5de3c676e57177b38857f6e3cdfbe8f38d1cd754b63200c0615eaa31f514b4f",
|
||||
"sha256:f5e8e8d60e18d5f7fd49983f0c4696deeddaf6e608fbab33397671e2fcc6cc91",
|
||||
"sha256:f7cac622e11b4253ac4536a654fe221249065d9a69feb6cdcd4d9af3503602e0",
|
||||
"sha256:f8a04cf0c5b7139bc6368b461257d4a757ea2fe89b3773e494d235b7dd51119f",
|
||||
"sha256:f8bb35ce57a63c9a6896c71a285818a3922d8ca05d150fd1fe49a7f57287b836",
|
||||
"sha256:fbfdce91239fe306772faab57597186710d5699213f4df099d1612da7320d682"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==23.9.1"
|
||||
},
|
||||
"geventconnpool": {
|
||||
"git": "https://github.com/rasky/geventconnpool.git",
|
||||
"ref": "1bbb93a714a331a069adf27265fe582d9ba7ecd4"
|
||||
"version": "==24.2.1"
|
||||
},
|
||||
"greenlet": {
|
||||
"hashes": [
|
||||
|
@ -710,11 +708,11 @@
|
|||
},
|
||||
"marshmallow": {
|
||||
"hashes": [
|
||||
"sha256:4c1daff273513dc5eb24b219a8035559dc573c8f322558ef85f5438ddd1236dd",
|
||||
"sha256:c21d4b98fee747c130e6bc8f45c4b3199ea66bc00c12ee1f639f0aeca034d5e9"
|
||||
"sha256:20f53be28c6e374a711a16165fb22a8dc6003e3f7cda1285e3ca777b9193885b",
|
||||
"sha256:e7997f83571c7fd476042c2c188e4ee8a78900ca5e74bd9c8097afa56624e9bd"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==3.20.2"
|
||||
"version": "==3.21.0"
|
||||
},
|
||||
"oic": {
|
||||
"hashes": [
|
||||
|
@ -742,10 +740,10 @@
|
|||
},
|
||||
"phonenumberslite": {
|
||||
"hashes": [
|
||||
"sha256:2b04a53401d01ab42564c1abc762fc9808ad398e71dacfa3b38d4321e112ecb3",
|
||||
"sha256:74e3ee63dfa2bb562ce2e6ce74ce76ae74a2f81472005b80343235fb43426db4"
|
||||
"sha256:137d53d5d78dca30bc2becf81a3e2ac74deb8f0997e9bbe44de515ece4bd92bd",
|
||||
"sha256:e1f4359bff90c86d1b52db0e726d3334df00cc7d9c9c2ef66561d5f7a774d4ba"
|
||||
],
|
||||
"version": "==8.13.29"
|
||||
"version": "==8.13.31"
|
||||
},
|
||||
"psycopg2-binary": {
|
||||
"hashes": [
|
||||
|
@ -874,104 +872,104 @@
|
|||
},
|
||||
"pydantic": {
|
||||
"hashes": [
|
||||
"sha256:0b6a909df3192245cb736509a92ff69e4fef76116feffec68e93a567347bae6f",
|
||||
"sha256:4fd5c182a2488dc63e6d32737ff19937888001e2a6d86e94b3f233104a5d1fa9"
|
||||
"sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a",
|
||||
"sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.6.1"
|
||||
"version": "==2.6.3"
|
||||
},
|
||||
"pydantic-core": {
|
||||
"hashes": [
|
||||
"sha256:02906e7306cb8c5901a1feb61f9ab5e5c690dbbeaa04d84c1b9ae2a01ebe9379",
|
||||
"sha256:0ba503850d8b8dcc18391f10de896ae51d37fe5fe43dbfb6a35c5c5cad271a06",
|
||||
"sha256:16aa02e7a0f539098e215fc193c8926c897175d64c7926d00a36188917717a05",
|
||||
"sha256:18de31781cdc7e7b28678df7c2d7882f9692ad060bc6ee3c94eb15a5d733f8f7",
|
||||
"sha256:22c5f022799f3cd6741e24f0443ead92ef42be93ffda0d29b2597208c94c3753",
|
||||
"sha256:2924b89b16420712e9bb8192396026a8fbd6d8726224f918353ac19c4c043d2a",
|
||||
"sha256:308974fdf98046db28440eb3377abba274808bf66262e042c412eb2adf852731",
|
||||
"sha256:396fdf88b1b503c9c59c84a08b6833ec0c3b5ad1a83230252a9e17b7dfb4cffc",
|
||||
"sha256:3ac426704840877a285d03a445e162eb258924f014e2f074e209d9b4ff7bf380",
|
||||
"sha256:3b052c753c4babf2d1edc034c97851f867c87d6f3ea63a12e2700f159f5c41c3",
|
||||
"sha256:3fab4e75b8c525a4776e7630b9ee48aea50107fea6ca9f593c98da3f4d11bf7c",
|
||||
"sha256:406fac1d09edc613020ce9cf3f2ccf1a1b2f57ab00552b4c18e3d5276c67eb11",
|
||||
"sha256:40a0bd0bed96dae5712dab2aba7d334a6c67cbcac2ddfca7dbcc4a8176445990",
|
||||
"sha256:41dac3b9fce187a25c6253ec79a3f9e2a7e761eb08690e90415069ea4a68ff7a",
|
||||
"sha256:459c0d338cc55d099798618f714b21b7ece17eb1a87879f2da20a3ff4c7628e2",
|
||||
"sha256:459d6be6134ce3b38e0ef76f8a672924460c455d45f1ad8fdade36796df1ddc8",
|
||||
"sha256:46b0d5520dbcafea9a8645a8164658777686c5c524d381d983317d29687cce97",
|
||||
"sha256:47924039e785a04d4a4fa49455e51b4eb3422d6eaacfde9fc9abf8fdef164e8a",
|
||||
"sha256:4bfcbde6e06c56b30668a0c872d75a7ef3025dc3c1823a13cf29a0e9b33f67e8",
|
||||
"sha256:4f9ee4febb249c591d07b2d4dd36ebcad0ccd128962aaa1801508320896575ef",
|
||||
"sha256:55749f745ebf154c0d63d46c8c58594d8894b161928aa41adbb0709c1fe78b77",
|
||||
"sha256:5864b0242f74b9dd0b78fd39db1768bc3f00d1ffc14e596fd3e3f2ce43436a33",
|
||||
"sha256:5f60f920691a620b03082692c378661947d09415743e437a7478c309eb0e4f82",
|
||||
"sha256:60eb8ceaa40a41540b9acae6ae7c1f0a67d233c40dc4359c256ad2ad85bdf5e5",
|
||||
"sha256:69a7b96b59322a81c2203be537957313b07dd333105b73db0b69212c7d867b4b",
|
||||
"sha256:6ad84731a26bcfb299f9eab56c7932d46f9cad51c52768cace09e92a19e4cf55",
|
||||
"sha256:6db58c22ac6c81aeac33912fb1af0e930bc9774166cdd56eade913d5f2fff35e",
|
||||
"sha256:70651ff6e663428cea902dac297066d5c6e5423fda345a4ca62430575364d62b",
|
||||
"sha256:72f7919af5de5ecfaf1eba47bf9a5d8aa089a3340277276e5636d16ee97614d7",
|
||||
"sha256:732bd062c9e5d9582a30e8751461c1917dd1ccbdd6cafb032f02c86b20d2e7ec",
|
||||
"sha256:7924e54f7ce5d253d6160090ddc6df25ed2feea25bfb3339b424a9dd591688bc",
|
||||
"sha256:7afb844041e707ac9ad9acad2188a90bffce2c770e6dc2318be0c9916aef1469",
|
||||
"sha256:7b883af50eaa6bb3299780651e5be921e88050ccf00e3e583b1e92020333304b",
|
||||
"sha256:7beec26729d496a12fd23cf8da9944ee338c8b8a17035a560b585c36fe81af20",
|
||||
"sha256:7bf26c2e2ea59d32807081ad51968133af3025c4ba5753e6a794683d2c91bf6e",
|
||||
"sha256:7c31669e0c8cc68400ef0c730c3a1e11317ba76b892deeefaf52dcb41d56ed5d",
|
||||
"sha256:7e6231aa5bdacda78e96ad7b07d0c312f34ba35d717115f4b4bff6cb87224f0f",
|
||||
"sha256:870dbfa94de9b8866b37b867a2cb37a60c401d9deb4a9ea392abf11a1f98037b",
|
||||
"sha256:88646cae28eb1dd5cd1e09605680c2b043b64d7481cdad7f5003ebef401a3039",
|
||||
"sha256:8aafeedb6597a163a9c9727d8a8bd363a93277701b7bfd2749fbefee2396469e",
|
||||
"sha256:8bde5b48c65b8e807409e6f20baee5d2cd880e0fad00b1a811ebc43e39a00ab2",
|
||||
"sha256:8f9142a6ed83d90c94a3efd7af8873bf7cefed2d3d44387bf848888482e2d25f",
|
||||
"sha256:936a787f83db1f2115ee829dd615c4f684ee48ac4de5779ab4300994d8af325b",
|
||||
"sha256:98dc6f4f2095fc7ad277782a7c2c88296badcad92316b5a6e530930b1d475ebc",
|
||||
"sha256:9957433c3a1b67bdd4c63717eaf174ebb749510d5ea612cd4e83f2d9142f3fc8",
|
||||
"sha256:99af961d72ac731aae2a1b55ccbdae0733d816f8bfb97b41909e143de735f522",
|
||||
"sha256:9b5f13857da99325dcabe1cc4e9e6a3d7b2e2c726248ba5dd4be3e8e4a0b6d0e",
|
||||
"sha256:9d776d30cde7e541b8180103c3f294ef7c1862fd45d81738d156d00551005784",
|
||||
"sha256:9da90d393a8227d717c19f5397688a38635afec89f2e2d7af0df037f3249c39a",
|
||||
"sha256:a3b7352b48fbc8b446b75f3069124e87f599d25afb8baa96a550256c031bb890",
|
||||
"sha256:a477932664d9611d7a0816cc3c0eb1f8856f8a42435488280dfbf4395e141485",
|
||||
"sha256:a7e41e3ada4cca5f22b478c08e973c930e5e6c7ba3588fb8e35f2398cdcc1545",
|
||||
"sha256:a90fec23b4b05a09ad988e7a4f4e081711a90eb2a55b9c984d8b74597599180f",
|
||||
"sha256:a9e523474998fb33f7c1a4d55f5504c908d57add624599e095c20fa575b8d943",
|
||||
"sha256:aa057095f621dad24a1e906747179a69780ef45cc8f69e97463692adbcdae878",
|
||||
"sha256:aa6c8c582036275997a733427b88031a32ffa5dfc3124dc25a730658c47a572f",
|
||||
"sha256:ae34418b6b389d601b31153b84dce480351a352e0bb763684a1b993d6be30f17",
|
||||
"sha256:b0d7a9165167269758145756db43a133608a531b1e5bb6a626b9ee24bc38a8f7",
|
||||
"sha256:b30b0dd58a4509c3bd7eefddf6338565c4905406aee0c6e4a5293841411a1286",
|
||||
"sha256:b8f9186ca45aee030dc8234118b9c0784ad91a0bb27fc4e7d9d6608a5e3d386c",
|
||||
"sha256:b94cbda27267423411c928208e89adddf2ea5dd5f74b9528513f0358bba019cb",
|
||||
"sha256:cc6f6c9be0ab6da37bc77c2dda5f14b1d532d5dbef00311ee6e13357a418e646",
|
||||
"sha256:ce232a6170dd6532096cadbf6185271e4e8c70fc9217ebe105923ac105da9978",
|
||||
"sha256:cf903310a34e14651c9de056fcc12ce090560864d5a2bb0174b971685684e1d8",
|
||||
"sha256:d5362d099c244a2d2f9659fb3c9db7c735f0004765bbe06b99be69fbd87c3f15",
|
||||
"sha256:dffaf740fe2e147fedcb6b561353a16243e654f7fe8e701b1b9db148242e1272",
|
||||
"sha256:e0f686549e32ccdb02ae6f25eee40cc33900910085de6aa3790effd391ae10c2",
|
||||
"sha256:e4b52776a2e3230f4854907a1e0946eec04d41b1fc64069ee774876bbe0eab55",
|
||||
"sha256:e4ba0884a91f1aecce75202473ab138724aa4fb26d7707f2e1fa6c3e68c84fbf",
|
||||
"sha256:e6294e76b0380bb7a61eb8a39273c40b20beb35e8c87ee101062834ced19c545",
|
||||
"sha256:ebb892ed8599b23fa8f1799e13a12c87a97a6c9d0f497525ce9858564c4575a4",
|
||||
"sha256:eca58e319f4fd6df004762419612122b2c7e7d95ffafc37e890252f869f3fb2a",
|
||||
"sha256:ed957db4c33bc99895f3a1672eca7e80e8cda8bd1e29a80536b4ec2153fa9804",
|
||||
"sha256:ef551c053692b1e39e3f7950ce2296536728871110e7d75c4e7753fb30ca87f4",
|
||||
"sha256:ef6113cd31411eaf9b39fc5a8848e71c72656fd418882488598758b2c8c6dfa0",
|
||||
"sha256:f685dbc1fdadb1dcd5b5e51e0a378d4685a891b2ddaf8e2bba89bd3a7144e44a",
|
||||
"sha256:f8ed79883b4328b7f0bd142733d99c8e6b22703e908ec63d930b06be3a0e7113",
|
||||
"sha256:fe56851c3f1d6f5384b3051c536cc81b3a93a73faf931f404fef95217cf1e10d",
|
||||
"sha256:ff7c97eb7a29aba230389a2661edf2e9e06ce616c7e35aa764879b6894a44b25"
|
||||
"sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a",
|
||||
"sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed",
|
||||
"sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979",
|
||||
"sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff",
|
||||
"sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5",
|
||||
"sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45",
|
||||
"sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340",
|
||||
"sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad",
|
||||
"sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23",
|
||||
"sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6",
|
||||
"sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7",
|
||||
"sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241",
|
||||
"sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda",
|
||||
"sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187",
|
||||
"sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba",
|
||||
"sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c",
|
||||
"sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2",
|
||||
"sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c",
|
||||
"sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132",
|
||||
"sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf",
|
||||
"sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972",
|
||||
"sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db",
|
||||
"sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade",
|
||||
"sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4",
|
||||
"sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8",
|
||||
"sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f",
|
||||
"sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9",
|
||||
"sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48",
|
||||
"sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec",
|
||||
"sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d",
|
||||
"sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9",
|
||||
"sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb",
|
||||
"sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4",
|
||||
"sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89",
|
||||
"sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c",
|
||||
"sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9",
|
||||
"sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da",
|
||||
"sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac",
|
||||
"sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b",
|
||||
"sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf",
|
||||
"sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e",
|
||||
"sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137",
|
||||
"sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1",
|
||||
"sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b",
|
||||
"sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8",
|
||||
"sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e",
|
||||
"sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053",
|
||||
"sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01",
|
||||
"sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe",
|
||||
"sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd",
|
||||
"sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805",
|
||||
"sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183",
|
||||
"sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8",
|
||||
"sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99",
|
||||
"sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820",
|
||||
"sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074",
|
||||
"sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256",
|
||||
"sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8",
|
||||
"sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975",
|
||||
"sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad",
|
||||
"sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e",
|
||||
"sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca",
|
||||
"sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df",
|
||||
"sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b",
|
||||
"sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a",
|
||||
"sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a",
|
||||
"sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721",
|
||||
"sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a",
|
||||
"sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f",
|
||||
"sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2",
|
||||
"sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97",
|
||||
"sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6",
|
||||
"sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed",
|
||||
"sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc",
|
||||
"sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1",
|
||||
"sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe",
|
||||
"sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120",
|
||||
"sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f",
|
||||
"sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.16.2"
|
||||
"version": "==2.16.3"
|
||||
},
|
||||
"pydantic-settings": {
|
||||
"hashes": [
|
||||
"sha256:26b1492e0a24755626ac5e6d715e9077ab7ad4fb5f19a8b7ed7011d52f36141c",
|
||||
"sha256:7621c0cb5d90d1140d2f0ef557bdf03573aac7035948109adf2574770b77605a"
|
||||
"sha256:00b9f6a5e95553590434c0fa01ead0b216c3e10bc54ae02e37f359948643c5ed",
|
||||
"sha256:0235391d26db4d2190cb9b31051c4b46882d28a51533f97440867f012d4da091"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.1.0"
|
||||
"version": "==2.2.1"
|
||||
},
|
||||
"pyjwkest": {
|
||||
"hashes": [
|
||||
|
@ -982,11 +980,11 @@
|
|||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
|
||||
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
|
||||
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
|
||||
"sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.8.2"
|
||||
"version": "==2.9.0.post0"
|
||||
},
|
||||
"python-dotenv": {
|
||||
"hashes": [
|
||||
|
@ -1015,11 +1013,11 @@
|
|||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05",
|
||||
"sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"
|
||||
"sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56",
|
||||
"sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==69.0.3"
|
||||
"version": "==69.1.1"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
@ -1037,14 +1035,23 @@
|
|||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.4.4"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"tblib": {
|
||||
"hashes": [
|
||||
"sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783",
|
||||
"sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"
|
||||
"sha256:80a6c77e59b55e83911e1e607c649836a69c103963c5f28a46cbeef44acf8129",
|
||||
"sha256:93622790a0a29e04f0346458face1e144dc4d32f493714c6c3dff82a4adb77e6"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.9.0"
|
||||
"version": "==3.0.0"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475",
|
||||
"sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.10.0"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
|
@ -1073,45 +1080,45 @@
|
|||
},
|
||||
"zope.interface": {
|
||||
"hashes": [
|
||||
"sha256:0c8cf55261e15590065039696607f6c9c1aeda700ceee40c70478552d323b3ff",
|
||||
"sha256:13b7d0f2a67eb83c385880489dbb80145e9d344427b4262c49fbf2581677c11c",
|
||||
"sha256:1f294a15f7723fc0d3b40701ca9b446133ec713eafc1cc6afa7b3d98666ee1ac",
|
||||
"sha256:239a4a08525c080ff833560171d23b249f7f4d17fcbf9316ef4159f44997616f",
|
||||
"sha256:2f8d89721834524a813f37fa174bac074ec3d179858e4ad1b7efd4401f8ac45d",
|
||||
"sha256:2fdc7ccbd6eb6b7df5353012fbed6c3c5d04ceaca0038f75e601060e95345309",
|
||||
"sha256:34c15ca9248f2e095ef2e93af2d633358c5f048c49fbfddf5fdfc47d5e263736",
|
||||
"sha256:387545206c56b0315fbadb0431d5129c797f92dc59e276b3ce82db07ac1c6179",
|
||||
"sha256:43b576c34ef0c1f5a4981163b551a8781896f2a37f71b8655fd20b5af0386abb",
|
||||
"sha256:57d0a8ce40ce440f96a2c77824ee94bf0d0925e6089df7366c2272ccefcb7941",
|
||||
"sha256:5a804abc126b33824a44a7aa94f06cd211a18bbf31898ba04bd0924fbe9d282d",
|
||||
"sha256:67be3ca75012c6e9b109860820a8b6c9a84bfb036fbd1076246b98e56951ca92",
|
||||
"sha256:6af47f10cfc54c2ba2d825220f180cc1e2d4914d783d6fc0cd93d43d7bc1c78b",
|
||||
"sha256:6dc998f6de015723196a904045e5a2217f3590b62ea31990672e31fbc5370b41",
|
||||
"sha256:70d2cef1bf529bff41559be2de9d44d47b002f65e17f43c73ddefc92f32bf00f",
|
||||
"sha256:7ebc4d34e7620c4f0da7bf162c81978fce0ea820e4fa1e8fc40ee763839805f3",
|
||||
"sha256:964a7af27379ff4357dad1256d9f215047e70e93009e532d36dcb8909036033d",
|
||||
"sha256:97806e9ca3651588c1baaebb8d0c5ee3db95430b612db354c199b57378312ee8",
|
||||
"sha256:9b9bc671626281f6045ad61d93a60f52fd5e8209b1610972cf0ef1bbe6d808e3",
|
||||
"sha256:9ffdaa5290422ac0f1688cb8adb1b94ca56cee3ad11f29f2ae301df8aecba7d1",
|
||||
"sha256:a0da79117952a9a41253696ed3e8b560a425197d4e41634a23b1507efe3273f1",
|
||||
"sha256:a41f87bb93b8048fe866fa9e3d0c51e27fe55149035dcf5f43da4b56732c0a40",
|
||||
"sha256:aa6fd016e9644406d0a61313e50348c706e911dca29736a3266fc9e28ec4ca6d",
|
||||
"sha256:ad54ed57bdfa3254d23ae04a4b1ce405954969c1b0550cc2d1d2990e8b439de1",
|
||||
"sha256:b012d023b4fb59183909b45d7f97fb493ef7a46d2838a5e716e3155081894605",
|
||||
"sha256:b51b64432eed4c0744241e9ce5c70dcfecac866dff720e746d0a9c82f371dfa7",
|
||||
"sha256:bbe81def9cf3e46f16ce01d9bfd8bea595e06505e51b7baf45115c77352675fd",
|
||||
"sha256:c9559138690e1bd4ea6cd0954d22d1e9251e8025ce9ede5d0af0ceae4a401e43",
|
||||
"sha256:e30506bcb03de8983f78884807e4fd95d8db6e65b69257eea05d13d519b83ac0",
|
||||
"sha256:e33e86fd65f369f10608b08729c8f1c92ec7e0e485964670b4d2633a4812d36b",
|
||||
"sha256:e441e8b7d587af0414d25e8d05e27040d78581388eed4c54c30c0c91aad3a379",
|
||||
"sha256:e8bb9c990ca9027b4214fa543fd4025818dc95f8b7abce79d61dc8a2112b561a",
|
||||
"sha256:ef43ee91c193f827e49599e824385ec7c7f3cd152d74cb1dfe02cb135f264d83",
|
||||
"sha256:ef467d86d3cfde8b39ea1b35090208b0447caaabd38405420830f7fd85fbdd56",
|
||||
"sha256:f89b28772fc2562ed9ad871c865f5320ef761a7fcc188a935e21fe8b31a38ca9",
|
||||
"sha256:fddbab55a2473f1d3b8833ec6b7ac31e8211b0aa608df5ab09ce07f3727326de"
|
||||
"sha256:02adbab560683c4eca3789cc0ac487dcc5f5a81cc48695ec247f00803cafe2fe",
|
||||
"sha256:14e02a6fc1772b458ebb6be1c276528b362041217b9ca37e52ecea2cbdce9fac",
|
||||
"sha256:25e0af9663eeac6b61b231b43c52293c2cb7f0c232d914bdcbfd3e3bd5c182ad",
|
||||
"sha256:2606955a06c6852a6cff4abeca38346ed01e83f11e960caa9a821b3626a4467b",
|
||||
"sha256:396f5c94654301819a7f3a702c5830f0ea7468d7b154d124ceac823e2419d000",
|
||||
"sha256:3b240883fb43160574f8f738e6d09ddbdbf8fa3e8cea051603d9edfd947d9328",
|
||||
"sha256:3b6c62813c63c543a06394a636978b22dffa8c5410affc9331ce6cdb5bfa8565",
|
||||
"sha256:4ae9793f114cee5c464cc0b821ae4d36e1eba961542c6086f391a61aee167b6f",
|
||||
"sha256:4bce517b85f5debe07b186fc7102b332676760f2e0c92b7185dd49c138734b70",
|
||||
"sha256:4d45d2ba8195850e3e829f1f0016066a122bfa362cc9dc212527fc3d51369037",
|
||||
"sha256:4dd374927c00764fcd6fe1046bea243ebdf403fba97a937493ae4be2c8912c2b",
|
||||
"sha256:506f5410b36e5ba494136d9fa04c548eaf1a0d9c442b0b0e7a0944db7620e0ab",
|
||||
"sha256:59f7374769b326a217d0b2366f1c176a45a4ff21e8f7cebb3b4a3537077eff85",
|
||||
"sha256:5ee9789a20b0081dc469f65ff6c5007e67a940d5541419ca03ef20c6213dd099",
|
||||
"sha256:6fc711acc4a1c702ca931fdbf7bf7c86f2a27d564c85c4964772dadf0e3c52f5",
|
||||
"sha256:75d2ec3d9b401df759b87bc9e19d1b24db73083147089b43ae748aefa63067ef",
|
||||
"sha256:76e0531d86523be7a46e15d379b0e975a9db84316617c0efe4af8338dc45b80c",
|
||||
"sha256:8af82afc5998e1f307d5e72712526dba07403c73a9e287d906a8aa2b1f2e33dd",
|
||||
"sha256:8f5d2c39f3283e461de3655e03faf10e4742bb87387113f787a7724f32db1e48",
|
||||
"sha256:97785604824981ec8c81850dd25c8071d5ce04717a34296eeac771231fbdd5cd",
|
||||
"sha256:a3046e8ab29b590d723821d0785598e0b2e32b636a0272a38409be43e3ae0550",
|
||||
"sha256:abb0b3f2cb606981c7432f690db23506b1db5899620ad274e29dbbbdd740e797",
|
||||
"sha256:ac7c2046d907e3b4e2605a130d162b1b783c170292a11216479bb1deb7cadebe",
|
||||
"sha256:af27b3fe5b6bf9cd01b8e1c5ddea0a0d0a1b8c37dc1c7452f1e90bf817539c6d",
|
||||
"sha256:b386b8b9d2b6a5e1e4eadd4e62335571244cb9193b7328c2b6e38b64cfda4f0e",
|
||||
"sha256:b66335bbdbb4c004c25ae01cc4a54fd199afbc1fd164233813c6d3c2293bb7e1",
|
||||
"sha256:d54f66c511ea01b9ef1d1a57420a93fbb9d48a08ec239f7d9c581092033156d0",
|
||||
"sha256:de125151a53ecdb39df3cb3deb9951ed834dd6a110a9e795d985b10bb6db4532",
|
||||
"sha256:de7916380abaef4bb4891740879b1afcba2045aee51799dfd6d6ca9bdc71f35f",
|
||||
"sha256:e2fefad268ff5c5b314794e27e359e48aeb9c8bb2cbb5748a071757a56f6bb8f",
|
||||
"sha256:e7b2bed4eea047a949296e618552d3fed00632dc1b795ee430289bdd0e3717f3",
|
||||
"sha256:e87698e2fea5ca2f0a99dff0a64ce8110ea857b640de536c76d92aaa2a91ff3a",
|
||||
"sha256:ede888382882f07b9e4cd942255921ffd9f2901684198b88e247c7eabd27a000",
|
||||
"sha256:f444de0565db46d26c9fa931ca14f497900a295bd5eba480fc3fad25af8c763e",
|
||||
"sha256:fa994e8937e8ccc7e87395b7b35092818905cf27c651e3ff3e7f29729f5ce3ce",
|
||||
"sha256:febceb04ee7dd2aef08c2ff3d6f8a07de3052fc90137c507b0ede3ea80c21440"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==6.1"
|
||||
"version": "==6.2"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
|
@ -1142,32 +1149,32 @@
|
|||
},
|
||||
"black": {
|
||||
"hashes": [
|
||||
"sha256:0269dfdea12442022e88043d2910429bed717b2d04523867a85dacce535916b8",
|
||||
"sha256:07204d078e25327aad9ed2c64790d681238686bce254c910de640c7cc4fc3aa6",
|
||||
"sha256:08b34e85170d368c37ca7bf81cf67ac863c9d1963b2c1780c39102187ec8dd62",
|
||||
"sha256:1a95915c98d6e32ca43809d46d932e2abc5f1f7d582ffbe65a5b4d1588af7445",
|
||||
"sha256:2588021038bd5ada078de606f2a804cadd0a3cc6a79cb3e9bb3a8bf581325a4c",
|
||||
"sha256:2fa6a0e965779c8f2afb286f9ef798df770ba2b6cee063c650b96adec22c056a",
|
||||
"sha256:34afe9da5056aa123b8bfda1664bfe6fb4e9c6f311d8e4a6eb089da9a9173bf9",
|
||||
"sha256:3897ae5a21ca132efa219c029cce5e6bfc9c3d34ed7e892113d199c0b1b444a2",
|
||||
"sha256:40657e1b78212d582a0edecafef133cf1dd02e6677f539b669db4746150d38f6",
|
||||
"sha256:48b5760dcbfe5cf97fd4fba23946681f3a81514c6ab8a45b50da67ac8fbc6c7b",
|
||||
"sha256:5242ecd9e990aeb995b6d03dc3b2d112d4a78f2083e5a8e86d566340ae80fec4",
|
||||
"sha256:5cdc2e2195212208fbcae579b931407c1fa9997584f0a415421748aeafff1168",
|
||||
"sha256:5d7b06ea8816cbd4becfe5f70accae953c53c0e53aa98730ceccb0395520ee5d",
|
||||
"sha256:7258c27115c1e3b5de9ac6c4f9957e3ee2c02c0b39222a24dc7aa03ba0e986f5",
|
||||
"sha256:854c06fb86fd854140f37fb24dbf10621f5dab9e3b0c29a690ba595e3d543024",
|
||||
"sha256:a21725862d0e855ae05da1dd25e3825ed712eaaccef6b03017fe0853a01aa45e",
|
||||
"sha256:a83fe522d9698d8f9a101b860b1ee154c1d25f8a82ceb807d319f085b2627c5b",
|
||||
"sha256:b3d64db762eae4a5ce04b6e3dd745dcca0fb9560eb931a5be97472e38652a161",
|
||||
"sha256:e298d588744efda02379521a19639ebcd314fba7a49be22136204d7ed1782717",
|
||||
"sha256:e2c8dfa14677f90d976f68e0c923947ae68fa3961d61ee30976c388adc0b02c8",
|
||||
"sha256:ecba2a15dfb2d97105be74bbfe5128bc5e9fa8477d8c46766505c1dda5883aac",
|
||||
"sha256:fc1ec9aa6f4d98d022101e015261c056ddebe3da6a8ccfc2c792cbe0349d48b7"
|
||||
"sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8",
|
||||
"sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8",
|
||||
"sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd",
|
||||
"sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9",
|
||||
"sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31",
|
||||
"sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92",
|
||||
"sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f",
|
||||
"sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29",
|
||||
"sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4",
|
||||
"sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693",
|
||||
"sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218",
|
||||
"sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a",
|
||||
"sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23",
|
||||
"sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0",
|
||||
"sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982",
|
||||
"sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894",
|
||||
"sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540",
|
||||
"sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430",
|
||||
"sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b",
|
||||
"sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2",
|
||||
"sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6",
|
||||
"sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==24.1.1"
|
||||
"version": "==24.2.0"
|
||||
},
|
||||
"blinker": {
|
||||
"hashes": [
|
||||
|
@ -1179,12 +1186,12 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:65acfe7f1cf2a9b7df3d4edb87c8022e02685825bd1957e7bb678cc0d09f5e5f",
|
||||
"sha256:73f5ec89cb3ddb3ed577317889fd2f2df783f66b6502a9a4239979607e33bf74"
|
||||
"sha256:8b3f5cc7fbedcbb22271c328039df8a6ab343001e746e0cdb24774c426cadcf8",
|
||||
"sha256:f201b6a416f809283d554c652211eecec9fe3a52ed4063dab3f3e7aea7571d9c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.34.37"
|
||||
"version": "==1.34.54"
|
||||
},
|
||||
"boto3-mocking": {
|
||||
"hashes": [
|
||||
|
@ -1197,28 +1204,28 @@
|
|||
},
|
||||
"boto3-stubs": {
|
||||
"hashes": [
|
||||
"sha256:97b5ca3d3145385acde5af46ca2da3fc74f433545034c36183f389e99771516e",
|
||||
"sha256:c6618c7126bac0337c05e161e9c428febc57d6a24d7ff62de46e67761f402c57"
|
||||
"sha256:7db5194e47f76e0010cd00b6ad9725db114d6a3fd04e52ceed3ef1181fe326bc",
|
||||
"sha256:c7b2e8b99f4896cf1226df47d4badaaa8df7426008c96a428bf00205695669e9"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.34.37"
|
||||
"version": "==1.34.54"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:2a5bf33aacd2d970afd3d492e179e06ea98a5469030d5cfe7a2ad9995f7bb2ef",
|
||||
"sha256:3c46ddb1679e6ef45ca78b48665398636bda532a07cd476e4b500697d13d9a99"
|
||||
"sha256:4061ff4be3efcf53547ebadf2c94d419dfc8be7beec24e9fa1819599ffd936fa",
|
||||
"sha256:bf215d93e9d5544c593962780d194e74c6ee40b883d0b885e62ef35fc0ec01e5"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.34.37"
|
||||
"version": "==1.34.54"
|
||||
},
|
||||
"botocore-stubs": {
|
||||
"hashes": [
|
||||
"sha256:087cd42973edcb5527dc97eec87fa29fffecc39691249486e02045677d4a2dbe",
|
||||
"sha256:d6bcea8a6872aa46d389027dc5c022241fd0a2047a8b858aa5005e6151ed30a7"
|
||||
"sha256:958f0084322dc9e549f73151b686fa51b15858fb2b3a573b9f4367f073fff463",
|
||||
"sha256:bcc35bfbd14d1261813681c40108f2ce85fdf082c15b0a04016d3c22dd93b73f"
|
||||
],
|
||||
"markers": "python_version >= '3.8' and python_version < '4.0'",
|
||||
"version": "==1.34.37"
|
||||
"version": "==1.34.54"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
|
@ -1427,11 +1434,11 @@
|
|||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
|
||||
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
|
||||
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
|
||||
"sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.8.2"
|
||||
"version": "==2.9.0.post0"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
|
@ -1492,11 +1499,11 @@
|
|||
},
|
||||
"rich": {
|
||||
"hashes": [
|
||||
"sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa",
|
||||
"sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"
|
||||
"sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222",
|
||||
"sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"
|
||||
],
|
||||
"markers": "python_full_version >= '3.7.0'",
|
||||
"version": "==13.7.0"
|
||||
"version": "==13.7.1"
|
||||
},
|
||||
"s3transfer": {
|
||||
"hashes": [
|
||||
|
@ -1532,11 +1539,11 @@
|
|||
},
|
||||
"stevedore": {
|
||||
"hashes": [
|
||||
"sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d",
|
||||
"sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"
|
||||
"sha256:1c15d95766ca0569cad14cb6272d4d31dae66b011a929d7c18219c176ea1b5c9",
|
||||
"sha256:46b93ca40e1114cea93d738a6c1e365396981bb6bb78c27045b7587c9473544d"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==5.1.0"
|
||||
"version": "==5.2.0"
|
||||
},
|
||||
"tomli": {
|
||||
"hashes": [
|
||||
|
@ -1548,11 +1555,11 @@
|
|||
},
|
||||
"types-awscrt": {
|
||||
"hashes": [
|
||||
"sha256:06a859189a329ca8e66d56ceeef2391488e39b878fbd2141f115eab4d416fe22",
|
||||
"sha256:f61a120d3e98ee1387bc5ca4b93437f258cc5c2af1f55f8634ec4cee5729f178"
|
||||
"sha256:61811bbf4de95248939f9276a434be93d2b95f6ccfe8aa94e56999e9778cfcc2",
|
||||
"sha256:79d5bfb01f64701b6cf442e89a37d9c4dc6dbb79a46f2f611739b2418d30ecfd"
|
||||
],
|
||||
"markers": "python_version >= '3.7' and python_version < '4.0'",
|
||||
"version": "==0.20.3"
|
||||
"version": "==0.20.5"
|
||||
},
|
||||
"types-cachetools": {
|
||||
"hashes": [
|
||||
|
@ -1580,12 +1587,12 @@
|
|||
},
|
||||
"types-requests": {
|
||||
"hashes": [
|
||||
"sha256:03a28ce1d7cd54199148e043b2079cdded22d6795d19a2c2a6791a4b2b5e2eb5",
|
||||
"sha256:9592a9a4cb92d6d75d9b491a41477272b710e021011a2a3061157e2fb1f1a5d1"
|
||||
"sha256:a82807ec6ddce8f00fe0e949da6d6bc1fbf1715420218a9640d695f70a9e5a9b",
|
||||
"sha256:f1721dba8385958f504a5386240b92de4734e047a08a40751c1654d1ac3349c5"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.31.0.20240125"
|
||||
"version": "==2.31.0.20240218"
|
||||
},
|
||||
"types-s3transfer": {
|
||||
"hashes": [
|
||||
|
@ -1597,12 +1604,12 @@
|
|||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783",
|
||||
"sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"
|
||||
"sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475",
|
||||
"sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.9.0"
|
||||
"version": "==4.10.0"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
import logging
|
||||
|
||||
from time import sleep
|
||||
from gevent import Timeout
|
||||
from epplibwrapper.utility.pool_status import PoolStatus
|
||||
|
||||
try:
|
||||
from epplib.client import Client
|
||||
from epplib import commands
|
||||
|
@ -18,8 +14,6 @@ from django.conf import settings
|
|||
|
||||
from .cert import Cert, Key
|
||||
from .errors import ErrorCode, LoginError, RegistryError
|
||||
from .socket import Socket
|
||||
from .utility.pool import EPPConnectionPool
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -43,8 +37,12 @@ class EPPLibWrapper:
|
|||
ATTN: This should not be used directly. Use `Domain` from domain.py.
|
||||
"""
|
||||
|
||||
def __init__(self, start_connection_pool=True) -> None:
|
||||
def __init__(self) -> None:
|
||||
"""Initialize settings which will be used for all connections."""
|
||||
# set _client to None initially. In the event that the __init__ fails
|
||||
# before _client initializes, app should still start and be in a state
|
||||
# that it can attempt _client initialization on send attempts
|
||||
self._client = None # type: ignore
|
||||
# prepare (but do not send) a Login command
|
||||
self._login = commands.Login(
|
||||
cl_id=settings.SECRET_REGISTRY_CL_ID,
|
||||
|
@ -54,9 +52,19 @@ class EPPLibWrapper:
|
|||
"urn:ietf:params:xml:ns:contact-1.0",
|
||||
],
|
||||
)
|
||||
try:
|
||||
self._initialize_client()
|
||||
except Exception:
|
||||
logger.warning("Unable to configure epplib. Registrar cannot contact registry.")
|
||||
|
||||
def _initialize_client(self) -> None:
|
||||
"""Initialize a client, assuming _login defined. Sets _client to initialized
|
||||
client. Raises errors if initialization fails.
|
||||
This method will be called at app initialization, and also during retries."""
|
||||
# establish a client object with a TCP socket transport
|
||||
self._client = Client(
|
||||
# note that type: ignore added in several places because linter complains
|
||||
# about _client initially being set to None, and None type doesn't match code
|
||||
self._client = Client( # type: ignore
|
||||
SocketTransport(
|
||||
settings.SECRET_REGISTRY_HOSTNAME,
|
||||
cert_file=CERT.filename,
|
||||
|
@ -64,176 +72,95 @@ class EPPLibWrapper:
|
|||
password=settings.SECRET_REGISTRY_KEY_PASSPHRASE,
|
||||
)
|
||||
)
|
||||
try:
|
||||
# use the _client object to connect
|
||||
self._client.connect() # type: ignore
|
||||
response = self._client.send(self._login) # type: ignore
|
||||
if response.code >= 2000: # type: ignore
|
||||
self._client.close() # type: ignore
|
||||
raise LoginError(response.msg) # type: ignore
|
||||
except TransportError as err:
|
||||
message = "_initialize_client failed to execute due to a connection error."
|
||||
logger.error(f"{message} Error: {err}")
|
||||
raise RegistryError(message, code=ErrorCode.TRANSPORT_ERROR) from err
|
||||
except LoginError as err:
|
||||
raise err
|
||||
except Exception as err:
|
||||
message = "_initialize_client failed to execute due to an unknown error."
|
||||
logger.error(f"{message} Error: {err}")
|
||||
raise RegistryError(message) from err
|
||||
|
||||
self.pool_options = {
|
||||
# Pool size
|
||||
"size": settings.EPP_CONNECTION_POOL_SIZE,
|
||||
# Which errors the pool should look out for.
|
||||
# Avoid changing this unless necessary,
|
||||
# it can and will break things.
|
||||
"exc_classes": (TransportError,),
|
||||
# Occasionally pings the registry to keep the connection alive.
|
||||
# Value in seconds => (keepalive / size)
|
||||
"keepalive": settings.POOL_KEEP_ALIVE,
|
||||
}
|
||||
|
||||
self._pool = None
|
||||
|
||||
# Tracks the status of the pool
|
||||
self.pool_status = PoolStatus()
|
||||
|
||||
if start_connection_pool:
|
||||
self.start_connection_pool()
|
||||
def _disconnect(self) -> None:
|
||||
"""Close the connection."""
|
||||
try:
|
||||
self._client.send(commands.Logout()) # type: ignore
|
||||
self._client.close() # type: ignore
|
||||
except Exception:
|
||||
logger.warning("Connection to registry was not cleanly closed.")
|
||||
|
||||
def _send(self, command):
|
||||
"""Helper function used by `send`."""
|
||||
cmd_type = command.__class__.__name__
|
||||
|
||||
# Start a timeout to check if the pool is hanging
|
||||
timeout = Timeout(settings.POOL_TIMEOUT)
|
||||
timeout.start()
|
||||
|
||||
try:
|
||||
if not self.pool_status.connection_success:
|
||||
raise LoginError("Couldn't connect to the registry after three attempts")
|
||||
with self._pool.get() as connection:
|
||||
response = connection.send(command)
|
||||
except Timeout as t:
|
||||
# If more than one pool exists,
|
||||
# multiple timeouts can be floating around.
|
||||
# We need to be specific as to which we are targeting.
|
||||
if t is timeout:
|
||||
# Flag that the pool is frozen,
|
||||
# then restart the pool.
|
||||
self.pool_status.pool_hanging = True
|
||||
logger.error("Pool timed out")
|
||||
self.start_connection_pool()
|
||||
# check for the condition that the _client was not initialized properly
|
||||
# at app initialization
|
||||
if self._client is None:
|
||||
self._initialize_client()
|
||||
response = self._client.send(command)
|
||||
except (ValueError, ParsingError) as err:
|
||||
message = f"{cmd_type} failed to execute due to some syntax error."
|
||||
logger.error(f"{message} Error: {err}", exc_info=True)
|
||||
logger.error(f"{message} Error: {err}")
|
||||
raise RegistryError(message) from err
|
||||
except TransportError as err:
|
||||
message = f"{cmd_type} failed to execute due to a connection error."
|
||||
logger.error(f"{message} Error: {err}", exc_info=True)
|
||||
logger.error(f"{message} Error: {err}")
|
||||
raise RegistryError(message, code=ErrorCode.TRANSPORT_ERROR) from err
|
||||
except LoginError as err:
|
||||
# For linter due to it not liking this line length
|
||||
text = "failed to execute due to a registry login error."
|
||||
message = f"{cmd_type} {text}"
|
||||
logger.error(f"{message} Error: {err}", exc_info=True)
|
||||
logger.error(f"{message} Error: {err}")
|
||||
raise RegistryError(message) from err
|
||||
except Exception as err:
|
||||
message = f"{cmd_type} failed to execute due to an unknown error."
|
||||
logger.error(f"{message} Error: {err}", exc_info=True)
|
||||
logger.error(f"{message} Error: {err}")
|
||||
raise RegistryError(message) from err
|
||||
else:
|
||||
if response.code >= 2000:
|
||||
raise RegistryError(response.msg, code=response.code)
|
||||
else:
|
||||
return response
|
||||
finally:
|
||||
# Close the timeout no matter what happens
|
||||
timeout.close()
|
||||
|
||||
def _retry(self, command):
|
||||
"""Retry sending a command through EPP by re-initializing the client
|
||||
and then sending the command."""
|
||||
# re-initialize by disconnecting and initial
|
||||
self._disconnect()
|
||||
self._initialize_client()
|
||||
return self._send(command)
|
||||
|
||||
def send(self, command, *, cleaned=False):
|
||||
"""Login, send the command, then close the connection. Tries 3 times."""
|
||||
"""Login, the send the command. Retry once if an error is found"""
|
||||
# try to prevent use of this method without appropriate safeguards
|
||||
cmd_type = command.__class__.__name__
|
||||
if not cleaned:
|
||||
raise ValueError("Please sanitize user input before sending it.")
|
||||
|
||||
# Reopen the pool if its closed
|
||||
# Only occurs when a login error is raised, after connection is successful
|
||||
if not self.pool_status.pool_running:
|
||||
# We want to reopen the connection pool,
|
||||
# but we don't want the end user to wait while it opens.
|
||||
# Raise syntax doesn't allow this, so we use a try/catch
|
||||
# block.
|
||||
try:
|
||||
logger.error("Can't contact the Registry. Pool was not running.")
|
||||
raise RegistryError("Can't contact the Registry. Pool was not running.")
|
||||
except RegistryError as err:
|
||||
try:
|
||||
return self._send(command)
|
||||
except RegistryError as err:
|
||||
if (
|
||||
err.is_transport_error()
|
||||
or err.is_connection_error()
|
||||
or err.is_session_error()
|
||||
or err.is_server_error()
|
||||
or err.should_retry()
|
||||
):
|
||||
message = f"{cmd_type} failed and will be retried"
|
||||
logger.info(f"{message} Error: {err}")
|
||||
return self._retry(command)
|
||||
else:
|
||||
raise err
|
||||
finally:
|
||||
# Code execution will halt after here.
|
||||
# The end user will need to recall .send.
|
||||
self.start_connection_pool()
|
||||
|
||||
counter = 0 # we'll try 3 times
|
||||
while True:
|
||||
try:
|
||||
return self._send(command)
|
||||
except RegistryError as err:
|
||||
if counter < 3 and (err.should_retry() or err.is_transport_error()):
|
||||
logger.info(f"Retrying transport error. Attempt #{counter+1} of 3.")
|
||||
counter += 1
|
||||
sleep((counter * 50) / 1000) # sleep 50 ms to 150 ms
|
||||
else: # don't try again
|
||||
raise err
|
||||
|
||||
def get_pool(self):
|
||||
"""Get the current pool instance"""
|
||||
return self._pool
|
||||
|
||||
def _create_pool(self, client, login, options):
|
||||
"""Creates and returns new pool instance"""
|
||||
logger.info("New pool was created")
|
||||
return EPPConnectionPool(client, login, options)
|
||||
|
||||
def start_connection_pool(self, restart_pool_if_exists=True):
|
||||
"""Starts a connection pool for the registry.
|
||||
|
||||
restart_pool_if_exists -> bool:
|
||||
If an instance of the pool already exists,
|
||||
then then that instance will be killed first.
|
||||
It is generally recommended to keep this enabled.
|
||||
"""
|
||||
# Since we reuse the same creds for each pool, we can test on
|
||||
# one socket, and if successful, then we know we can connect.
|
||||
if not self._test_registry_connection_success():
|
||||
logger.warning("start_connection_pool() -> Cannot contact the Registry")
|
||||
self.pool_status.connection_success = False
|
||||
else:
|
||||
self.pool_status.connection_success = True
|
||||
|
||||
# If this function is reinvoked, then ensure
|
||||
# that we don't have duplicate data sitting around.
|
||||
if self._pool is not None and restart_pool_if_exists:
|
||||
logger.info("Connection pool restarting...")
|
||||
self.kill_pool()
|
||||
logger.info("Old pool killed")
|
||||
|
||||
self._pool = self._create_pool(self._client, self._login, self.pool_options)
|
||||
|
||||
self.pool_status.pool_running = True
|
||||
self.pool_status.pool_hanging = False
|
||||
|
||||
logger.info("Connection pool started")
|
||||
|
||||
def kill_pool(self):
|
||||
"""Kills the existing pool. Use this instead
|
||||
of self._pool = None, as that doesn't clear
|
||||
gevent instances."""
|
||||
if self._pool is not None:
|
||||
self._pool.kill_all_connections()
|
||||
self._pool = None
|
||||
self.pool_status.pool_running = False
|
||||
return None
|
||||
logger.info("kill_pool() was invoked but there was no pool to delete")
|
||||
|
||||
def _test_registry_connection_success(self):
|
||||
"""Check that determines if our login
|
||||
credentials are valid, and/or if the Registrar
|
||||
can be contacted
|
||||
"""
|
||||
# This is closed in test_connection_success
|
||||
socket = Socket(self._client, self._login)
|
||||
can_login = False
|
||||
|
||||
# Something went wrong if this doesn't exist
|
||||
if hasattr(socket, "test_connection_success"):
|
||||
can_login = socket.test_connection_success()
|
||||
|
||||
return can_login
|
||||
|
||||
|
||||
try:
|
||||
|
@ -241,5 +168,4 @@ try:
|
|||
CLIENT = EPPLibWrapper()
|
||||
logger.info("registry client initialized")
|
||||
except Exception:
|
||||
CLIENT = None # type: ignore
|
||||
logger.warning("Unable to configure epplib. Registrar cannot contact registry.", exc_info=True)
|
||||
logger.warning("Unable to configure epplib. Registrar cannot contact registry.")
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
import logging
|
||||
from time import sleep
|
||||
|
||||
try:
|
||||
from epplib import commands
|
||||
from epplib.client import Client
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from .errors import LoginError
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Socket:
|
||||
"""Context manager which establishes a TCP connection with registry."""
|
||||
|
||||
def __init__(self, client: Client, login: commands.Login) -> None:
|
||||
"""Save the epplib client and login details."""
|
||||
self.client = client
|
||||
self.login = login
|
||||
|
||||
def __enter__(self):
|
||||
"""Runs connect(), which opens a connection with EPPLib."""
|
||||
self.connect()
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
"""Runs disconnect(), which closes a connection with EPPLib."""
|
||||
self.disconnect()
|
||||
|
||||
def connect(self):
|
||||
"""Use epplib to connect."""
|
||||
logger.info("Opening socket on connection pool")
|
||||
self.client.connect()
|
||||
response = self.client.send(self.login)
|
||||
if self.is_login_error(response.code):
|
||||
self.client.close()
|
||||
raise LoginError(response.msg)
|
||||
return self.client
|
||||
|
||||
def disconnect(self):
|
||||
"""Close the connection."""
|
||||
logger.info("Closing socket on connection pool")
|
||||
try:
|
||||
self.client.send(commands.Logout())
|
||||
self.client.close()
|
||||
except Exception as err:
|
||||
logger.warning("Connection to registry was not cleanly closed.")
|
||||
logger.error(err)
|
||||
|
||||
def send(self, command):
|
||||
"""Sends a command to the registry.
|
||||
If the RegistryError code is >= 2000,
|
||||
then this function raises a LoginError.
|
||||
The calling function should handle this."""
|
||||
response = self.client.send(command)
|
||||
if self.is_login_error(response.code):
|
||||
self.client.close()
|
||||
raise LoginError(response.msg)
|
||||
|
||||
return response
|
||||
|
||||
def is_login_error(self, code):
|
||||
"""Returns the result of code >= 2000 for RegistryError.
|
||||
This indicates that something weird happened on the Registry,
|
||||
and that we should return a LoginError."""
|
||||
return code >= 2000
|
||||
|
||||
def test_connection_success(self):
|
||||
"""Tests if a successful connection can be made with the registry.
|
||||
Tries 3 times."""
|
||||
# Something went wrong if this doesn't exist
|
||||
if not hasattr(self.client, "connect"):
|
||||
logger.warning("self.client does not have a connect attribute")
|
||||
return False
|
||||
|
||||
counter = 0 # we'll try 3 times
|
||||
while True:
|
||||
try:
|
||||
self.client.connect()
|
||||
response = self.client.send(self.login)
|
||||
except (LoginError, OSError) as err:
|
||||
logger.error(err)
|
||||
should_retry = True
|
||||
if isinstance(err, LoginError):
|
||||
should_retry = err.should_retry()
|
||||
if should_retry and counter < 3:
|
||||
counter += 1
|
||||
sleep((counter * 50) / 1000) # sleep 50 ms to 150 ms
|
||||
else: # don't try again
|
||||
return False
|
||||
else:
|
||||
# If we encounter a login error, fail
|
||||
if self.is_login_error(response.code):
|
||||
logger.warning("A login error was found in test_connection_success")
|
||||
return False
|
||||
|
||||
# Otherwise, just return true
|
||||
return True
|
||||
finally:
|
||||
self.disconnect()
|
257
src/epplibwrapper/tests/test_client.py
Normal file
257
src/epplibwrapper/tests/test_client.py
Normal file
|
@ -0,0 +1,257 @@
|
|||
from unittest.mock import MagicMock, patch
|
||||
from django.test import TestCase
|
||||
from epplibwrapper.client import EPPLibWrapper
|
||||
from epplibwrapper.errors import RegistryError, LoginError
|
||||
from .common import less_console_noise
|
||||
import logging
|
||||
|
||||
try:
|
||||
from epplib.exceptions import TransportError
|
||||
from epplib.responses import Result
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestClient(TestCase):
|
||||
"""Test the EPPlibwrapper client"""
|
||||
|
||||
def fake_result(self, code, msg):
|
||||
"""Helper function to create a fake Result object"""
|
||||
return Result(code=code, msg=msg, res_data=[], cl_tr_id="cl_tr_id", sv_tr_id="sv_tr_id")
|
||||
|
||||
@patch("epplibwrapper.client.Client")
|
||||
def test_initialize_client_success(self, mock_client):
|
||||
"""Test when the initialize_client is successful"""
|
||||
with less_console_noise():
|
||||
# Mock the Client instance and its methods
|
||||
mock_connect = MagicMock()
|
||||
# Create a mock Result instance
|
||||
mock_result = MagicMock(spec=Result)
|
||||
mock_result.code = 200
|
||||
mock_result.msg = "Success"
|
||||
mock_result.res_data = ["data1", "data2"]
|
||||
mock_result.cl_tr_id = "client_id"
|
||||
mock_result.sv_tr_id = "server_id"
|
||||
mock_send = MagicMock(return_value=mock_result)
|
||||
mock_client.return_value.connect = mock_connect
|
||||
mock_client.return_value.send = mock_send
|
||||
|
||||
# Create EPPLibWrapper instance and initialize client
|
||||
wrapper = EPPLibWrapper()
|
||||
|
||||
# Assert that connect method is called once
|
||||
mock_connect.assert_called_once()
|
||||
# Assert that _client is not None after initialization
|
||||
self.assertIsNotNone(wrapper._client)
|
||||
|
||||
@patch("epplibwrapper.client.Client")
|
||||
def test_initialize_client_transport_error(self, mock_client):
|
||||
"""Test when the send(login) step of initialize_client raises a TransportError."""
|
||||
with less_console_noise():
|
||||
# Mock the Client instance and its methods
|
||||
mock_connect = MagicMock()
|
||||
mock_send = MagicMock(side_effect=TransportError("Transport error"))
|
||||
mock_client.return_value.connect = mock_connect
|
||||
mock_client.return_value.send = mock_send
|
||||
|
||||
with self.assertRaises(RegistryError):
|
||||
# Create EPPLibWrapper instance and initialize client
|
||||
# if functioning as expected, initial __init__ should except
|
||||
# and log any Exception raised
|
||||
wrapper = EPPLibWrapper()
|
||||
# so call _initialize_client a second time directly to test
|
||||
# the raised exception
|
||||
wrapper._initialize_client()
|
||||
|
||||
@patch("epplibwrapper.client.Client")
|
||||
def test_initialize_client_login_error(self, mock_client):
|
||||
"""Test when the send(login) step of initialize_client returns (2400) comamnd failed code."""
|
||||
with less_console_noise():
|
||||
# Mock the Client instance and its methods
|
||||
mock_connect = MagicMock()
|
||||
# Create a mock Result instance
|
||||
mock_result = MagicMock(spec=Result)
|
||||
mock_result.code = 2400
|
||||
mock_result.msg = "Login failed"
|
||||
mock_result.res_data = ["data1", "data2"]
|
||||
mock_result.cl_tr_id = "client_id"
|
||||
mock_result.sv_tr_id = "server_id"
|
||||
mock_send = MagicMock(return_value=mock_result)
|
||||
mock_client.return_value.connect = mock_connect
|
||||
mock_client.return_value.send = mock_send
|
||||
|
||||
with self.assertRaises(LoginError):
|
||||
# Create EPPLibWrapper instance and initialize client
|
||||
# if functioning as expected, initial __init__ should except
|
||||
# and log any Exception raised
|
||||
wrapper = EPPLibWrapper()
|
||||
# so call _initialize_client a second time directly to test
|
||||
# the raised exception
|
||||
wrapper._initialize_client()
|
||||
|
||||
@patch("epplibwrapper.client.Client")
|
||||
def test_initialize_client_unknown_exception(self, mock_client):
|
||||
"""Test when the send(login) step of initialize_client raises an unexpected Exception."""
|
||||
with less_console_noise():
|
||||
# Mock the Client instance and its methods
|
||||
mock_connect = MagicMock()
|
||||
mock_send = MagicMock(side_effect=Exception("Unknown exception"))
|
||||
mock_client.return_value.connect = mock_connect
|
||||
mock_client.return_value.send = mock_send
|
||||
|
||||
with self.assertRaises(RegistryError):
|
||||
# Create EPPLibWrapper instance and initialize client
|
||||
# if functioning as expected, initial __init__ should except
|
||||
# and log any Exception raised
|
||||
wrapper = EPPLibWrapper()
|
||||
# so call _initialize_client a second time directly to test
|
||||
# the raised exception
|
||||
wrapper._initialize_client()
|
||||
|
||||
@patch("epplibwrapper.client.Client")
|
||||
def test_initialize_client_fails_recovers_with_send_command(self, mock_client):
|
||||
"""Test when the initialize_client fails on the connect() step. And then a subsequent
|
||||
call to send() should recover and re-initialize the client and properly return
|
||||
the successful send command.
|
||||
Flow:
|
||||
Initialization step fails at app init
|
||||
Send command fails (with 2400 code) prompting retry
|
||||
Client closes and re-initializes, and command is sent successfully"""
|
||||
with less_console_noise():
|
||||
# Mock the Client instance and its methods
|
||||
# close() should return successfully
|
||||
mock_close = MagicMock()
|
||||
mock_client.return_value.close = mock_close
|
||||
# Create success and failure results
|
||||
command_success_result = self.fake_result(1000, "Command completed successfully")
|
||||
command_failure_result = self.fake_result(2400, "Command failed")
|
||||
# side_effect for the connect() calls
|
||||
# first connect() should raise an Exception
|
||||
# subsequent connect() calls should return success
|
||||
connect_call_count = 0
|
||||
|
||||
def connect_side_effect(*args, **kwargs):
|
||||
nonlocal connect_call_count
|
||||
connect_call_count += 1
|
||||
if connect_call_count == 1:
|
||||
raise Exception("Connection failed")
|
||||
else:
|
||||
return command_success_result
|
||||
|
||||
mock_connect = MagicMock(side_effect=connect_side_effect)
|
||||
mock_client.return_value.connect = mock_connect
|
||||
# side_effect for the send() calls
|
||||
# first send will be the send("InfoDomainCommand") and should fail
|
||||
# subsequend send() calls should return success
|
||||
send_call_count = 0
|
||||
|
||||
def send_side_effect(*args, **kwargs):
|
||||
nonlocal send_call_count
|
||||
send_call_count += 1
|
||||
if send_call_count == 1:
|
||||
return command_failure_result
|
||||
else:
|
||||
return command_success_result
|
||||
|
||||
mock_send = MagicMock(side_effect=send_side_effect)
|
||||
mock_client.return_value.send = mock_send
|
||||
# Create EPPLibWrapper instance and call send command
|
||||
wrapper = EPPLibWrapper()
|
||||
wrapper.send("InfoDomainCommand", cleaned=True)
|
||||
# two connect() calls should be made, the initial failed connect()
|
||||
# and the successful connect() during retry()
|
||||
self.assertEquals(mock_connect.call_count, 2)
|
||||
# close() should only be called once, during retry()
|
||||
mock_close.assert_called_once()
|
||||
# send called 4 times: failed send("InfoDomainCommand"), passed send(logout),
|
||||
# passed send(login), passed send("InfoDomainCommand")
|
||||
self.assertEquals(mock_send.call_count, 4)
|
||||
|
||||
@patch("epplibwrapper.client.Client")
|
||||
def test_send_command_failed_retries_and_fails_again(self, mock_client):
|
||||
"""Test when the send("InfoDomainCommand) call fails with a 2400, prompting a retry
|
||||
and the subsequent send("InfoDomainCommand) call also fails with a 2400, raise
|
||||
a RegistryError
|
||||
Flow:
|
||||
Initialization succeeds
|
||||
Send command fails (with 2400 code) prompting retry
|
||||
Client closes and re-initializes, and command fails again with 2400"""
|
||||
with less_console_noise():
|
||||
# Mock the Client instance and its methods
|
||||
# connect() and close() should succeed throughout
|
||||
mock_connect = MagicMock()
|
||||
mock_close = MagicMock()
|
||||
# Create a mock Result instance
|
||||
send_command_success_result = self.fake_result(1000, "Command completed successfully")
|
||||
send_command_failure_result = self.fake_result(2400, "Command failed")
|
||||
|
||||
# side_effect for send command, passes for all other sends (login, logout), but
|
||||
# fails for send("InfoDomainCommand")
|
||||
def side_effect(*args, **kwargs):
|
||||
if args[0] == "InfoDomainCommand":
|
||||
return send_command_failure_result
|
||||
else:
|
||||
return send_command_success_result
|
||||
|
||||
mock_send = MagicMock(side_effect=side_effect)
|
||||
mock_client.return_value.connect = mock_connect
|
||||
mock_client.return_value.close = mock_close
|
||||
mock_client.return_value.send = mock_send
|
||||
|
||||
with self.assertRaises(RegistryError):
|
||||
# Create EPPLibWrapper instance and initialize client
|
||||
wrapper = EPPLibWrapper()
|
||||
# call send, which should throw a RegistryError (after retry)
|
||||
wrapper.send("InfoDomainCommand", cleaned=True)
|
||||
# connect() should be called twice, once during initialization, second time
|
||||
# during retry
|
||||
self.assertEquals(mock_connect.call_count, 2)
|
||||
# close() is called once during retry
|
||||
mock_close.assert_called_once()
|
||||
# send() is called 5 times: send(login), send(command) fails, send(logout)
|
||||
# send(login), send(command)
|
||||
self.assertEquals(mock_send.call_count, 5)
|
||||
|
||||
@patch("epplibwrapper.client.Client")
|
||||
def test_send_command_failure_prompts_successful_retry(self, mock_client):
|
||||
"""Test when the send("InfoDomainCommand) call fails with a 2400, prompting a retry
|
||||
and the subsequent send("InfoDomainCommand) call succeeds
|
||||
Flow:
|
||||
Initialization succeeds
|
||||
Send command fails (with 2400 code) prompting retry
|
||||
Client closes and re-initializes, and command succeeds"""
|
||||
with less_console_noise():
|
||||
# Mock the Client instance and its methods
|
||||
# connect() and close() should succeed throughout
|
||||
mock_connect = MagicMock()
|
||||
mock_close = MagicMock()
|
||||
# create success and failure result messages
|
||||
send_command_success_result = self.fake_result(1000, "Command completed successfully")
|
||||
send_command_failure_result = self.fake_result(2400, "Command failed")
|
||||
# side_effect for send call, initial send(login) succeeds during initialization, next send(command)
|
||||
# fails, subsequent sends (logout, login, command) all succeed
|
||||
send_call_count = 0
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
nonlocal send_call_count
|
||||
send_call_count += 1
|
||||
if send_call_count == 2:
|
||||
return send_command_failure_result
|
||||
else:
|
||||
return send_command_success_result
|
||||
|
||||
mock_send = MagicMock(side_effect=side_effect)
|
||||
mock_client.return_value.connect = mock_connect
|
||||
mock_client.return_value.close = mock_close
|
||||
mock_client.return_value.send = mock_send
|
||||
# Create EPPLibWrapper instance and initialize client
|
||||
wrapper = EPPLibWrapper()
|
||||
wrapper.send("InfoDomainCommand", cleaned=True)
|
||||
# connect() is called twice, once during initialization of app, once during retry
|
||||
self.assertEquals(mock_connect.call_count, 2)
|
||||
# close() is called once, during retry
|
||||
mock_close.assert_called_once()
|
||||
# send() is called 5 times: send(login), send(command) fail, send(logout), send(login), send(command)
|
||||
self.assertEquals(mock_send.call_count, 5)
|
|
@ -1,262 +0,0 @@
|
|||
import datetime
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
from dateutil.tz import tzlocal # type: ignore
|
||||
from django.test import TestCase
|
||||
from epplibwrapper.client import EPPLibWrapper
|
||||
from epplibwrapper.errors import RegistryError
|
||||
from epplibwrapper.socket import Socket
|
||||
from epplibwrapper.utility.pool import EPPConnectionPool
|
||||
from registrar.models.domain import registry
|
||||
from contextlib import ExitStack
|
||||
from .common import less_console_noise
|
||||
import logging
|
||||
|
||||
try:
|
||||
from epplib import commands
|
||||
from epplib.client import Client
|
||||
from epplib.exceptions import TransportError
|
||||
from epplib.transport import SocketTransport
|
||||
from epplib.models import common, info
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestConnectionPool(TestCase):
|
||||
"""Tests for our connection pooling behaviour"""
|
||||
|
||||
def setUp(self):
|
||||
# Mimic the settings added to settings.py
|
||||
self.pool_options = {
|
||||
# Current pool size
|
||||
"size": 1,
|
||||
# Which errors the pool should look out for
|
||||
"exc_classes": (TransportError,),
|
||||
# Occasionally pings the registry to keep the connection alive.
|
||||
# Value in seconds => (keepalive / size)
|
||||
"keepalive": 60,
|
||||
}
|
||||
|
||||
def fake_socket(self, login, client):
|
||||
# Linter reasons
|
||||
pw = "none"
|
||||
# Create a fake client object
|
||||
fake_client = Client(
|
||||
SocketTransport(
|
||||
"none",
|
||||
cert_file="path/to/cert_file",
|
||||
key_file="path/to/key_file",
|
||||
password=pw,
|
||||
)
|
||||
)
|
||||
|
||||
return Socket(fake_client, MagicMock())
|
||||
|
||||
def patch_success(self):
|
||||
return True
|
||||
|
||||
def fake_send(self, command, cleaned=None):
|
||||
mock = MagicMock(
|
||||
code=1000,
|
||||
msg="Command completed successfully",
|
||||
res_data=None,
|
||||
cl_tr_id="xkw1uo#2023-10-17T15:29:09.559376",
|
||||
sv_tr_id="5CcH4gxISuGkq8eqvr1UyQ==-35a",
|
||||
extensions=[],
|
||||
msg_q=None,
|
||||
)
|
||||
return mock
|
||||
|
||||
def fake_client(mock_client):
|
||||
pw = "none"
|
||||
client = Client(
|
||||
SocketTransport(
|
||||
"none",
|
||||
cert_file="path/to/cert_file",
|
||||
key_file="path/to/key_file",
|
||||
password=pw,
|
||||
)
|
||||
)
|
||||
return client
|
||||
|
||||
@patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success)
|
||||
def test_pool_sends_data(self):
|
||||
"""A .send is invoked on the pool successfully"""
|
||||
expected_result = {
|
||||
"cl_tr_id": None,
|
||||
"code": 1000,
|
||||
"extensions": [],
|
||||
"msg": "Command completed successfully",
|
||||
"msg_q": None,
|
||||
"res_data": [
|
||||
info.InfoDomainResultData(
|
||||
roid="DF1340360-GOV",
|
||||
statuses=[
|
||||
common.Status(
|
||||
state="serverTransferProhibited",
|
||||
description=None,
|
||||
lang="en",
|
||||
),
|
||||
common.Status(state="inactive", description=None, lang="en"),
|
||||
],
|
||||
cl_id="gov2023-ote",
|
||||
cr_id="gov2023-ote",
|
||||
cr_date=datetime.datetime(2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()),
|
||||
up_id="gov2023-ote",
|
||||
up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()),
|
||||
tr_date=None,
|
||||
name="test3.gov",
|
||||
registrant="TuaWnx9hnm84GCSU",
|
||||
admins=[],
|
||||
nsset=None,
|
||||
keyset=None,
|
||||
ex_date=datetime.date(2024, 8, 15),
|
||||
auth_info=info.DomainAuthInfo(pw="2fooBAR123fooBaz"),
|
||||
)
|
||||
],
|
||||
"sv_tr_id": "wRRNVhKhQW2m6wsUHbo/lA==-29a",
|
||||
}
|
||||
|
||||
# Mock a response from EPP
|
||||
def fake_receive(command, cleaned=None):
|
||||
location = Path(__file__).parent / "utility" / "infoDomain.xml"
|
||||
xml = (location).read_bytes()
|
||||
return xml
|
||||
|
||||
def do_nothing(command):
|
||||
pass
|
||||
|
||||
# Mock what happens inside the "with"
|
||||
with ExitStack() as stack:
|
||||
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
|
||||
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
||||
stack.enter_context(patch.object(EPPConnectionPool, "kill_all_connections", do_nothing))
|
||||
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
|
||||
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
|
||||
with less_console_noise():
|
||||
# Restart the connection pool
|
||||
registry.start_connection_pool()
|
||||
# Pool should be running, and be the right size
|
||||
self.assertEqual(registry.pool_status.connection_success, True)
|
||||
self.assertEqual(registry.pool_status.pool_running, True)
|
||||
|
||||
# Send a command
|
||||
result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)
|
||||
|
||||
# Should this ever fail, it either means that the schema has changed,
|
||||
# or the pool is broken.
|
||||
# If the schema has changed: Update the associated infoDomain.xml file
|
||||
self.assertEqual(result.__dict__, expected_result)
|
||||
|
||||
# The number of open pools should match the number of requested ones.
|
||||
# If it is 0, then they failed to open
|
||||
self.assertEqual(len(registry._pool.conn), self.pool_options["size"])
|
||||
# Kill the connection pool
|
||||
registry.kill_pool()
|
||||
|
||||
@patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success)
|
||||
def test_pool_restarts_on_send(self):
|
||||
"""A .send is invoked, but the pool isn't running.
|
||||
The pool should restart."""
|
||||
expected_result = {
|
||||
"cl_tr_id": None,
|
||||
"code": 1000,
|
||||
"extensions": [],
|
||||
"msg": "Command completed successfully",
|
||||
"msg_q": None,
|
||||
"res_data": [
|
||||
info.InfoDomainResultData(
|
||||
roid="DF1340360-GOV",
|
||||
statuses=[
|
||||
common.Status(
|
||||
state="serverTransferProhibited",
|
||||
description=None,
|
||||
lang="en",
|
||||
),
|
||||
common.Status(state="inactive", description=None, lang="en"),
|
||||
],
|
||||
cl_id="gov2023-ote",
|
||||
cr_id="gov2023-ote",
|
||||
cr_date=datetime.datetime(2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()),
|
||||
up_id="gov2023-ote",
|
||||
up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()),
|
||||
tr_date=None,
|
||||
name="test3.gov",
|
||||
registrant="TuaWnx9hnm84GCSU",
|
||||
admins=[],
|
||||
nsset=None,
|
||||
keyset=None,
|
||||
ex_date=datetime.date(2024, 8, 15),
|
||||
auth_info=info.DomainAuthInfo(pw="2fooBAR123fooBaz"),
|
||||
)
|
||||
],
|
||||
"sv_tr_id": "wRRNVhKhQW2m6wsUHbo/lA==-29a",
|
||||
}
|
||||
|
||||
# Mock a response from EPP
|
||||
def fake_receive(command, cleaned=None):
|
||||
location = Path(__file__).parent / "utility" / "infoDomain.xml"
|
||||
xml = (location).read_bytes()
|
||||
return xml
|
||||
|
||||
def do_nothing(command):
|
||||
pass
|
||||
|
||||
# Mock what happens inside the "with"
|
||||
with ExitStack() as stack:
|
||||
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
|
||||
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
||||
stack.enter_context(patch.object(EPPConnectionPool, "kill_all_connections", do_nothing))
|
||||
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
|
||||
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
|
||||
with less_console_noise():
|
||||
# Start the connection pool
|
||||
registry.start_connection_pool()
|
||||
# Kill the connection pool
|
||||
registry.kill_pool()
|
||||
|
||||
self.assertEqual(registry.pool_status.pool_running, False)
|
||||
|
||||
# An exception should be raised as end user will be informed
|
||||
# that they cannot connect to EPP
|
||||
with self.assertRaises(RegistryError):
|
||||
expected = "InfoDomain failed to execute due to a connection error."
|
||||
result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
# A subsequent command should be successful, as the pool restarts
|
||||
result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)
|
||||
# Should this ever fail, it either means that the schema has changed,
|
||||
# or the pool is broken.
|
||||
# If the schema has changed: Update the associated infoDomain.xml file
|
||||
self.assertEqual(result.__dict__, expected_result)
|
||||
|
||||
# The number of open pools should match the number of requested ones.
|
||||
# If it is 0, then they failed to open
|
||||
self.assertEqual(len(registry._pool.conn), self.pool_options["size"])
|
||||
# Kill the connection pool
|
||||
registry.kill_pool()
|
||||
|
||||
@patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success)
|
||||
def test_raises_connection_error(self):
|
||||
"""A .send is invoked on the pool, but registry connection is lost
|
||||
right as we send a command."""
|
||||
|
||||
with ExitStack() as stack:
|
||||
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
|
||||
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
||||
with less_console_noise():
|
||||
# Start the connection pool
|
||||
registry.start_connection_pool()
|
||||
|
||||
# Pool should be running
|
||||
self.assertEqual(registry.pool_status.connection_success, True)
|
||||
self.assertEqual(registry.pool_status.pool_running, True)
|
||||
|
||||
# Try to send a command out - should fail
|
||||
with self.assertRaises(RegistryError):
|
||||
expected = "InfoDomain failed to execute due to a connection error."
|
||||
result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)
|
||||
self.assertEqual(result, expected)
|
|
@ -1,151 +0,0 @@
|
|||
import logging
|
||||
from typing import List
|
||||
import gevent
|
||||
from geventconnpool import ConnectionPool
|
||||
from epplibwrapper.socket import Socket
|
||||
from epplibwrapper.utility.pool_error import PoolError, PoolErrorCodes
|
||||
|
||||
try:
|
||||
from epplib.commands import Hello
|
||||
from epplib.exceptions import TransportError
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from gevent.lock import BoundedSemaphore
|
||||
from collections import deque
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EPPConnectionPool(ConnectionPool):
|
||||
"""A connection pool for EPPLib.
|
||||
|
||||
Args:
|
||||
client (Client): The client
|
||||
login (commands.Login): Login creds
|
||||
options (dict): Options for the ConnectionPool
|
||||
base class
|
||||
"""
|
||||
|
||||
def __init__(self, client, login, options: dict):
|
||||
# For storing shared credentials
|
||||
self._client = client
|
||||
self._login = login
|
||||
|
||||
# Keep track of each greenlet
|
||||
self.greenlets: List[gevent.Greenlet] = []
|
||||
|
||||
# Define optional pool settings.
|
||||
# Kept in a dict so that the parent class,
|
||||
# client.py, can maintain seperation/expandability
|
||||
self.size = 1
|
||||
if "size" in options:
|
||||
self.size = options["size"]
|
||||
|
||||
self.exc_classes = tuple((TransportError,))
|
||||
if "exc_classes" in options:
|
||||
self.exc_classes = options["exc_classes"]
|
||||
|
||||
self.keepalive = None
|
||||
if "keepalive" in options:
|
||||
self.keepalive = options["keepalive"]
|
||||
|
||||
# Determines the period in which new
|
||||
# gevent threads are spun up.
|
||||
# This time period is in seconds. So for instance, .1 would be .1 seconds.
|
||||
self.spawn_frequency = 0.1
|
||||
if "spawn_frequency" in options:
|
||||
self.spawn_frequency = options["spawn_frequency"]
|
||||
|
||||
self.conn: deque = deque()
|
||||
self.lock = BoundedSemaphore(self.size)
|
||||
|
||||
self.populate_all_connections()
|
||||
|
||||
def _new_connection(self):
|
||||
socket = self._create_socket(self._client, self._login)
|
||||
try:
|
||||
connection = socket.connect()
|
||||
return connection
|
||||
except Exception as err:
|
||||
message = f"Failed to execute due to a registry error: {err}"
|
||||
logger.error(message, exc_info=True)
|
||||
# We want to raise a pool error rather than a LoginError here
|
||||
# because if this occurs internally, we should handle this
|
||||
# differently than we otherwise would for LoginError.
|
||||
raise PoolError(code=PoolErrorCodes.NEW_CONNECTION_FAILED) from err
|
||||
|
||||
def _keepalive(self, c):
|
||||
"""Sends a command to the server to keep the connection alive."""
|
||||
try:
|
||||
# Sends a ping to the registry via EPPLib
|
||||
c.send(Hello())
|
||||
except Exception as err:
|
||||
message = "Failed to keep the connection alive."
|
||||
logger.error(message, exc_info=True)
|
||||
raise PoolError(code=PoolErrorCodes.KEEP_ALIVE_FAILED) from err
|
||||
|
||||
def _keepalive_periodic(self):
|
||||
"""Overriding _keepalive_periodic from geventconnpool so that PoolErrors
|
||||
are properly handled, as opposed to printing to stdout"""
|
||||
delay = float(self.keepalive) / self.size
|
||||
while 1:
|
||||
try:
|
||||
with self.get() as c:
|
||||
self._keepalive(c)
|
||||
except PoolError as err:
|
||||
logger.error(err.message, exc_info=True)
|
||||
except self.exc_classes:
|
||||
# Nothing to do, the pool will generate a new connection later
|
||||
pass
|
||||
gevent.sleep(delay)
|
||||
|
||||
def _create_socket(self, client, login) -> Socket:
|
||||
"""Creates and returns a socket instance"""
|
||||
socket = Socket(client, login)
|
||||
return socket
|
||||
|
||||
def get_connections(self):
|
||||
"""Returns the connection queue"""
|
||||
return self.conn
|
||||
|
||||
def kill_all_connections(self):
|
||||
"""Kills all active connections in the pool."""
|
||||
try:
|
||||
if len(self.conn) > 0 or len(self.greenlets) > 0:
|
||||
logger.info("Attempting to kill connections")
|
||||
gevent.killall(self.greenlets)
|
||||
|
||||
self.greenlets.clear()
|
||||
for connection in self.conn:
|
||||
connection.disconnect()
|
||||
self.conn.clear()
|
||||
|
||||
# Clear the semaphore
|
||||
self.lock = BoundedSemaphore(self.size)
|
||||
logger.info("Finished killing connections")
|
||||
else:
|
||||
logger.info("No connections to kill.")
|
||||
except Exception as err:
|
||||
logger.error("Could not kill all connections.")
|
||||
raise PoolError(code=PoolErrorCodes.KILL_ALL_FAILED) from err
|
||||
|
||||
def populate_all_connections(self):
|
||||
"""Generates the connection pool.
|
||||
If any connections exist, kill them first.
|
||||
Based off of the __init__ definition for geventconnpool.
|
||||
"""
|
||||
if len(self.conn) > 0 or len(self.greenlets) > 0:
|
||||
self.kill_all_connections()
|
||||
|
||||
# Setup the lock
|
||||
for i in range(self.size):
|
||||
self.lock.acquire()
|
||||
|
||||
# Open multiple connections
|
||||
for i in range(self.size):
|
||||
self.greenlets.append(gevent.spawn_later(self.spawn_frequency * i, self._addOne))
|
||||
|
||||
# Open a "keepalive" thread if we want to ping open connections
|
||||
if self.keepalive:
|
||||
self.greenlets.append(gevent.spawn(self._keepalive_periodic))
|
|
@ -1,46 +0,0 @@
|
|||
from enum import IntEnum
|
||||
|
||||
|
||||
class PoolErrorCodes(IntEnum):
|
||||
"""Used in the PoolError class for
|
||||
error mapping.
|
||||
|
||||
Overview of contact error codes:
|
||||
- 2000 KILL_ALL_FAILED
|
||||
- 2001 NEW_CONNECTION_FAILED
|
||||
- 2002 KEEP_ALIVE_FAILED
|
||||
"""
|
||||
|
||||
KILL_ALL_FAILED = 2000
|
||||
NEW_CONNECTION_FAILED = 2001
|
||||
KEEP_ALIVE_FAILED = 2002
|
||||
|
||||
|
||||
class PoolError(Exception):
|
||||
"""
|
||||
Overview of contact error codes:
|
||||
- 2000 KILL_ALL_FAILED
|
||||
- 2001 NEW_CONNECTION_FAILED
|
||||
- 2002 KEEP_ALIVE_FAILED
|
||||
|
||||
Note: These are separate from the error codes returned from EppLib
|
||||
"""
|
||||
|
||||
# Used variables due to linter requirements
|
||||
kill_failed = "Could not kill all connections. Are multiple pools running?"
|
||||
conn_failed = "Failed to execute due to a registry error. See previous logs to determine the cause of the error."
|
||||
alive_failed = "Failed to keep the connection alive. It is likely that the registry returned a LoginError."
|
||||
_error_mapping = {
|
||||
PoolErrorCodes.KILL_ALL_FAILED: kill_failed,
|
||||
PoolErrorCodes.NEW_CONNECTION_FAILED: conn_failed,
|
||||
PoolErrorCodes.KEEP_ALIVE_FAILED: alive_failed,
|
||||
}
|
||||
|
||||
def __init__(self, *args, code=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.code = code
|
||||
if self.code in self._error_mapping:
|
||||
self.message = self._error_mapping.get(self.code)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.message}"
|
|
@ -1,12 +0,0 @@
|
|||
class PoolStatus:
|
||||
"""A list of Booleans to keep track of Pool Status.
|
||||
|
||||
pool_running -> bool: Tracks if the pool itself is active or not.
|
||||
connection_success -> bool: Tracks if connection is possible with the registry.
|
||||
pool_hanging -> pool: Tracks if the pool has exceeded its timeout period.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.pool_running = False
|
||||
self.connection_success = False
|
||||
self.pool_hanging = False
|
|
@ -601,20 +601,6 @@ SECRET_REGISTRY_KEY = secret_registry_key
|
|||
SECRET_REGISTRY_KEY_PASSPHRASE = secret_registry_key_passphrase
|
||||
SECRET_REGISTRY_HOSTNAME = secret_registry_hostname
|
||||
|
||||
# Use this variable to set the size of our connection pool in client.py
|
||||
# WARNING: Setting this value too high could cause frequent app crashes!
|
||||
# Having too many connections open could cause the sandbox to timeout,
|
||||
# as the spinup time could exceed the timeout time.
|
||||
EPP_CONNECTION_POOL_SIZE = 1
|
||||
|
||||
# Determines the interval in which we ping open connections in seconds
|
||||
# Calculated as POOL_KEEP_ALIVE / EPP_CONNECTION_POOL_SIZE
|
||||
POOL_KEEP_ALIVE = 60
|
||||
|
||||
# Determines how long we try to keep a pool alive for,
|
||||
# before restarting it.
|
||||
POOL_TIMEOUT = 60
|
||||
|
||||
# endregion
|
||||
# region: Security and Privacy----------------------------------------------###
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import phonenumber_field.modelfields
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("registrar", "0070_domainapplication_rejection_reason"),
|
||||
]
|
||||
|
|
|
@ -475,7 +475,6 @@ class AuditedAdminMockData:
|
|||
def mock_user():
|
||||
"""A simple user."""
|
||||
user_kwargs = dict(
|
||||
id=4,
|
||||
first_name="Jeff",
|
||||
last_name="Lebowski",
|
||||
)
|
||||
|
|
|
@ -1542,6 +1542,8 @@ class DomainInvitationAdminTest(TestCase):
|
|||
def tearDown(self):
|
||||
"""Delete all DomainInvitation objects"""
|
||||
DomainInvitation.objects.all().delete()
|
||||
User.objects.all().delete()
|
||||
Contact.objects.all().delete()
|
||||
|
||||
def test_get_filters(self):
|
||||
"""Ensures that our filters are displaying correctly"""
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
-i https://pypi.python.org/simple
|
||||
annotated-types==0.6.0; python_version >= '3.8'
|
||||
asgiref==3.7.2; python_version >= '3.7'
|
||||
boto3==1.34.37; python_version >= '3.8'
|
||||
botocore==1.34.37; python_version >= '3.8'
|
||||
cachetools==5.3.2; python_version >= '3.7'
|
||||
boto3==1.34.54; python_version >= '3.8'
|
||||
botocore==1.34.54; python_version >= '3.8'
|
||||
cachetools==5.3.3; python_version >= '3.7'
|
||||
certifi==2024.2.2; python_version >= '3.6'
|
||||
cfenv==0.5.3
|
||||
cffi==1.16.0; platform_python_implementation != 'PyPy'
|
||||
charset-normalizer==3.3.2; python_full_version >= '3.7.0'
|
||||
cryptography==42.0.2; python_version >= '3.7'
|
||||
cryptography==42.0.5; python_version >= '3.7'
|
||||
defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
dj-database-url==2.1.0
|
||||
dj-email-url==1.0.6
|
||||
|
@ -17,18 +17,17 @@ django-allow-cidr==0.7.1
|
|||
django-auditlog==2.3.0; python_version >= '3.7'
|
||||
django-cache-url==3.4.5
|
||||
django-cors-headers==4.3.1; python_version >= '3.8'
|
||||
django-csp==3.7
|
||||
django-csp==3.8
|
||||
django-fsm==2.8.1
|
||||
django-login-required-middleware==0.9.0
|
||||
django-phonenumber-field[phonenumberslite]==7.3.0; python_version >= '3.8'
|
||||
django-widget-tweaks==1.5.0; python_version >= '3.8'
|
||||
environs[django]==10.3.0; python_version >= '3.8'
|
||||
faker==23.1.0; python_version >= '3.8'
|
||||
faker==23.3.0; python_version >= '3.8'
|
||||
fred-epplib@ git+https://github.com/cisagov/epplib.git@d56d183f1664f34c40ca9716a3a9a345f0ef561c
|
||||
furl==2.1.3
|
||||
future==0.18.3; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
gevent==23.9.1; python_version >= '3.8'
|
||||
geventconnpool@ git+https://github.com/rasky/geventconnpool.git@1bbb93a714a331a069adf27265fe582d9ba7ecd4
|
||||
future==1.0.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
gevent==24.2.1; python_version >= '3.8'
|
||||
greenlet==3.0.3; python_version >= '3.7'
|
||||
gunicorn==21.2.0; python_version >= '3.5'
|
||||
idna==3.6; python_version >= '3.5'
|
||||
|
@ -36,27 +35,28 @@ jmespath==1.0.1; python_version >= '3.7'
|
|||
lxml==5.1.0; python_version >= '3.6'
|
||||
mako==1.3.2; python_version >= '3.8'
|
||||
markupsafe==2.1.5; python_version >= '3.7'
|
||||
marshmallow==3.20.2; python_version >= '3.8'
|
||||
marshmallow==3.21.0; python_version >= '3.8'
|
||||
oic==1.6.1; python_version ~= '3.7'
|
||||
orderedmultidict==1.0.1
|
||||
packaging==23.2; python_version >= '3.7'
|
||||
phonenumberslite==8.13.29
|
||||
phonenumberslite==8.13.31
|
||||
psycopg2-binary==2.9.9; python_version >= '3.7'
|
||||
pycparser==2.21
|
||||
pycryptodomex==3.20.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
pydantic==2.6.1; python_version >= '3.8'
|
||||
pydantic-core==2.16.2; python_version >= '3.8'
|
||||
pydantic-settings==2.1.0; python_version >= '3.8'
|
||||
pydantic==2.6.3; python_version >= '3.8'
|
||||
pydantic-core==2.16.3; python_version >= '3.8'
|
||||
pydantic-settings==2.2.1; python_version >= '3.8'
|
||||
pyjwkest==1.4.2
|
||||
python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
python-dateutil==2.9.0.post0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
python-dotenv==1.0.1; python_version >= '3.8'
|
||||
requests==2.31.0; python_version >= '3.7'
|
||||
s3transfer==0.10.0; python_version >= '3.8'
|
||||
setuptools==69.0.3; python_version >= '3.8'
|
||||
setuptools==69.1.1; python_version >= '3.8'
|
||||
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
sqlparse==0.4.4; python_version >= '3.5'
|
||||
typing-extensions==4.9.0; python_version >= '3.8'
|
||||
tblib==3.0.0; python_version >= '3.8'
|
||||
typing-extensions==4.10.0; python_version >= '3.8'
|
||||
urllib3==2.0.7; python_version >= '3.7'
|
||||
whitenoise==6.6.0; python_version >= '3.8'
|
||||
zope.event==5.0; python_version >= '3.7'
|
||||
zope.interface==6.1; python_version >= '3.7'
|
||||
zope.interface==6.2; python_version >= '3.7'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue