diff --git a/gentle_gnomes/poetry.lock b/gentle_gnomes/poetry.lock index 66d8c91f..5eaad087 100644 --- a/gentle_gnomes/poetry.lock +++ b/gentle_gnomes/poetry.lock @@ -1,3 +1,26 @@ +[[package]] +category = "main" +description = "File support for asyncio." +name = "aiofiles" +optional = false +python-versions = "*" +version = "0.4.0" + +[[package]] +category = "main" +description = "Async http client/server framework (asyncio)" +name = "aiohttp" +optional = false +python-versions = ">=3.5.3" +version = "3.5.4" + +[package.dependencies] +async-timeout = ">=3.0,<4.0" +attrs = ">=17.3.0" +chardet = ">=2.0,<4.0" +multidict = ">=4.0,<5.0" +yarl = ">=1.0,<2.0" + [[package]] category = "dev" description = "A few extensions to pyyaml." @@ -9,6 +32,14 @@ version = "1.3.0" [package.dependencies] pyyaml = "*" +[[package]] +category = "main" +description = "Timeout context manager for asyncio programs" +name = "async-timeout" +optional = false +python-versions = ">=3.5.3" +version = "3.0.1" + [[package]] category = "dev" description = "Atomic file writes." @@ -18,7 +49,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "1.3.0" [[package]] -category = "dev" +category = "main" description = "Classes Without Boilerplate" name = "attrs" optional = false @@ -27,11 +58,11 @@ version = "19.1.0" [[package]] category = "main" -description = "Python package for providing Mozilla's CA Bundle." -name = "certifi" +description = "Fast, simple object-to-object and broadcast signaling" +name = "blinker" optional = false python-versions = "*" -version = "2019.6.16" +version = "1.4" [[package]] category = "dev" @@ -146,17 +177,54 @@ flake8 = "!=3.2.0" [[package]] category = "main" -description = "A simple framework for building complex web applications." -name = "flask" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +name = "h11" +optional = false +python-versions = "*" +version = "0.9.0" + +[[package]] +category = "main" +description = "HTTP/2 State-Machine based protocol implementation" +name = "h2" optional = false python-versions = "*" -version = "1.0.3" +version = "3.1.0" [package.dependencies] -Jinja2 = ">=2.10" -Werkzeug = ">=0.14" -click = ">=5.1" -itsdangerous = ">=0.24" +hpack = ">=2.3,<4" +hyperframe = ">=5.2.0,<6" + +[[package]] +category = "main" +description = "Pure-Python HPACK header compression" +name = "hpack" +optional = false +python-versions = "*" +version = "3.0.0" + +[[package]] +category = "main" +description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn." +name = "hypercorn" +optional = false +python-versions = ">=3.7" +version = "0.6.0" + +[package.dependencies] +h11 = "*" +h2 = ">=3.1.0" +pytoml = "*" +typing-extensions = "*" +wsproto = ">=0.14.0" + +[[package]] +category = "main" +description = "HTTP/2 framing layer for Python" +name = "hyperframe" +optional = false +python-versions = "*" +version = "5.2.0" [[package]] category = "dev" @@ -229,6 +297,14 @@ optional = false python-versions = ">=3.4" version = "7.1.0" +[[package]] +category = "main" +description = "multidict implementation" +name = "multidict" +optional = false +python-versions = ">=3.4.1" +version = "4.5.2" + [[package]] category = "dev" description = "Node.js virtual environment builder" @@ -325,7 +401,7 @@ description = "pytest: simple powerful testing with Python" name = "pytest" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "4.6.3" +version = "4.6.4" [package.dependencies] atomicwrites = ">=1.0" @@ -342,6 +418,17 @@ wcwidth = "*" python = ">=2.8" version = ">=4.0.0" +[[package]] +category = "dev" +description = "Pytest support for asyncio." +name = "pytest-asyncio" +optional = false +python-versions = ">= 3.5" +version = "0.10.0" + +[package.dependencies] +pytest = ">=3.0.6" + [[package]] category = "main" description = "Add .env support to your django/flask apps in development and deployments" @@ -350,6 +437,14 @@ optional = false python-versions = "*" version = "0.10.3" +[[package]] +category = "main" +description = "A parser for TOML-0.4.0" +name = "pytoml" +optional = false +python-versions = "*" +version = "0.1.20" + [[package]] category = "dev" description = "YAML parser and emitter for Python" @@ -360,17 +455,21 @@ version = "5.1.1" [[package]] category = "main" -description = "Python HTTP for Humans." -name = "requests" +description = "A Python ASGI web microframework with the same API as Flask" +name = "quart" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.22.0" +python-versions = ">=3.7.0" +version = "0.9.1" [package.dependencies] -certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.9" -urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" +aiofiles = "*" +blinker = "*" +click = "*" +hypercorn = ">=0.6.0" +itsdangerous = "*" +jinja2 = "*" +multidict = "*" +sortedcontainers = "*" [[package]] category = "main" @@ -391,6 +490,14 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" version = "1.12.0" +[[package]] +category = "main" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +name = "sortedcontainers" +optional = false +python-versions = "*" +version = "2.1.0" + [[package]] category = "dev" description = "Python Library for Tom's Obvious, Minimal Language" @@ -401,11 +508,30 @@ version = "0.10.0" [[package]] category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." -name = "urllib3" +description = "Type Hints for Python" +name = "typing" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -version = "1.25.3" +python-versions = "*" +version = "3.7.4" + +[[package]] +category = "main" +description = "Backported and Experimental Type Hints for Python 3.5+" +name = "typing-extensions" +optional = false +python-versions = "*" +version = "3.7.4" + +[package.dependencies] +typing = ">=3.7.4" + +[[package]] +category = "main" +description = "Fast implementation of asyncio event loop on top of libuv" +name = "uvloop" +optional = false +python-versions = "*" +version = "0.12.2" [[package]] category = "dev" @@ -425,11 +551,26 @@ version = "0.1.7" [[package]] category = "main" -description = "The comprehensive WSGI web application library." -name = "werkzeug" +description = "WebSockets state-machine based protocol implementation" +name = "wsproto" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.15.4" +python-versions = "*" +version = "0.14.1" + +[package.dependencies] +h11 = ">=0.8.1" + +[[package]] +category = "main" +description = "Yet another URL library" +name = "yarl" +optional = false +python-versions = ">=3.5.3" +version = "1.3.0" + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" [[package]] category = "dev" @@ -440,14 +581,17 @@ python-versions = ">=2.7" version = "0.5.1" [metadata] -content-hash = "a828e6aa0dbbd2901511ac64d52f53dd9229c19469d894f0b8c420f1b21b79e3" +content-hash = "fa98d5370c24f7325d923996c490f790c5e04bcc994880914c69087617e849c6" python-versions = "^3.7" [metadata.hashes] +aiofiles = ["021ea0ba314a86027c166ecc4b4c07f2d40fc0f4b3a950d1868a0f2571c2bbee", "1e644c2573f953664368de28d2aa4c89dfd64550429d0c27c4680ccd3aa4985d"] +aiohttp = ["00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55", "0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed", "09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10", "199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5", "296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1", "368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939", "40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390", "629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa", "6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc", "87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5", "9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d", "9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf", "9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6", "a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72", "a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12", "a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366", "acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4", "b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300", "c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d", "cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303", "d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6", "e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889"] "aspy.yaml" = ["463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc", "e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45"] +async-timeout = ["0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", "4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"] atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"] attrs = ["69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", "f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"] -certifi = ["046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", "945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"] +blinker = ["471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"] cfgv = ["32edbe09de6f4521224b87822103a8c16a614d31a894735f7a5b3bcf0eb3c37e", "3bd31385cd2bebddbba8012200aaf15aa208539f1b33973759b4d02fc2148da5"] chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"] click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"] @@ -459,7 +603,11 @@ flake8-bugbear = ["5070774b668be92c4312e5ca82748ddf4ecaa7a24ff062662681bb745c789 flake8-quotes = ["10c9af6b472d4302a8e721c5260856c3f985c5c082b04841aefd2f808ac02038"] flake8-string-format = ["68ea72a1a5b75e7018cae44d14f32473c798cf73d75cbaed86c6a9a907b770b2", "774d56103d9242ed968897455ef49b7d6de272000cfa83de5814273a868832f1"] flake8-tidy-imports = ["1c476aabc6e8db26dc75278464a3a392dba0ea80562777c5f13fd5cdf2646154", "b3f5b96affd0f57cacb6621ed28286ce67edaca807757b51227043ebf7b136a1"] -flask = ["ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3", "e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61"] +h11 = ["33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1", "4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"] +h2 = ["c8f387e0e4878904d4978cd688a3195f6b169d49b1ffa572a3d347d7adc5e09f", "fd07e865a3272ac6ef195d8904de92dc7b38dc28297ec39cfa22716b6d62e6eb"] +hpack = ["0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89", "8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"] +hypercorn = ["9ab2d6b686e5a9a455433144a269d3004ad0aa079d15ed291554858a9b8dbd38", "9afb874f8332645a00b77311d1975ac6690fe37e3c268d9d65f5250a3134ee29"] +hyperframe = ["5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40", "a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"] identify = ["0a11379b46d06529795442742a043dc2fa14cd8c995ae81d1febbc5f1c014c87", "43a5d24ffdb07bc7e21faf68b08e9f526a1f41f0056073f480291539ef961dfd"] idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"] importlib-metadata = ["6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7", "cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db"] @@ -468,6 +616,7 @@ jinja2 = ["065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", "1 markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"] mccabe = ["ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", "dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"] more-itertools = ["3ad685ff8512bf6dc5a8b82ebf73543999b657eded8c11803d9ba6b648986f4d", "8bb43d1f51ecef60d81854af61a3a880555a14643691cc4b64a6ee269c78f09a"] +multidict = ["024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f", "041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3", "045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef", "047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b", "068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73", "148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc", "1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3", "1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd", "31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351", "34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941", "3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d", "4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1", "4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b", "4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a", "5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3", "61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7", "6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0", "76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0", "7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014", "7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5", "7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036", "8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d", "8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a", "c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce", "c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1", "ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a", "d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9", "d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7", "db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b"] nodeenv = ["ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a"] numpy = ["0778076e764e146d3078b17c24c4d89e0ecd4ac5401beff8e1c87879043a0633", "141c7102f20abe6cf0d54c4ced8d565b86df4d3077ba2343b61a6db996cefec7", "14270a1ee8917d11e7753fb54fc7ffd1934f4d529235beec0b275e2ccf00333b", "27e11c7a8ec9d5838bc59f809bfa86efc8a4fd02e58960fa9c49d998e14332d5", "2a04dda79606f3d2f760384c38ccd3d5b9bb79d4c8126b67aff5eb09a253763e", "3c26010c1b51e1224a3ca6b8df807de6e95128b0908c7e34f190e7775455b0ca", "52c40f1a4262c896420c6ea1c6fda62cf67070e3947e3307f5562bd783a90336", "6e4f8d9e8aa79321657079b9ac03f3cf3fd067bf31c1cca4f56d49543f4356a5", "7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7", "7dc253b542bfd4b4eb88d9dbae4ca079e7bf2e2afd819ee18891a43db66c60c7", "94f5bd885f67bbb25c82d80184abbf7ce4f6c3c3a41fbaa4182f034bba803e69", "a89e188daa119ffa0d03ce5123dee3f8ffd5115c896c2a9d4f0dbb3d8b95bfa3", "ad3399da9b0ca36e2f24de72f67ab2854a62e623274607e37e0ce5f5d5fa9166", "b0348be89275fd1d4c44ffa39530c41a21062f52299b1e3ee7d1c61f060044b8", "b5554368e4ede1856121b0dfa35ce71768102e4aa55e526cb8de7f374ff78722", "cbddc56b2502d3f87fda4f98d948eb5b11f36ff3902e17cb6cc44727f2200525", "d79f18f41751725c56eceab2a886f021d70fd70a6188fd386e29a045945ffc10", "dc2ca26a19ab32dc475dbad9dfe723d3a64c835f4c23f625c2b6566ca32b9f29", "dd9bcd4f294eb0633bb33d1a74febdd2b9018b8b8ed325f861fffcd2c7660bb8", "e8baab1bc7c9152715844f1faca6744f2416929de10d7639ed49555a85549f52", "ec31fe12668af687b99acf1567399632a7c47b0e17cfb9ae47c098644ef36797", "f12b4f7e2d8f9da3141564e6737d79016fe5336cc92de6814eba579744f65b0a", "f58ac38d5ca045a377b3b377c84df8175ab992c970a53332fa8ac2373df44ff7"] packaging = ["0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af", "9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3"] @@ -477,15 +626,21 @@ py = ["64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", "dc639 pycodestyle = ["95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", "e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"] pyflakes = ["17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", "d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"] pyparsing = ["1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", "9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"] -pytest = ["4a784f1d4f2ef198fe9b7aef793e9fa1a3b2f84e822d9b3a64a181293a572d45", "926855726d8ae8371803f7b2e6ec0a69953d9c6311fa7c3b6c1b929ff92d27da"] +pytest = ["6aa9bc2f6f6504d7949e9df2a756739ca06e58ffda19b5e53c725f7b03fb4aae", "b77ae6f2d1a760760902a7676887b665c086f71e3461c64ed2a312afcedc00d6"] +pytest-asyncio = ["9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", "d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b"] python-dotenv = ["debd928b49dbc2bf68040566f55cdb3252458036464806f4094487244e2a4093", "f157d71d5fec9d4bd5f51c82746b6344dffa680ee85217c123f4a0c8117c4544"] +pytoml = ["ca2d0cb127c938b8b76a9a0d0f855cf930c1d50cc3a0af6d3595b566519a1013"] pyyaml = ["57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", "588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043", "68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7", "70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265", "86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391", "a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778", "a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225", "b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955", "cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e", "ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190", "fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"] -requests = ["11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", "9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"] +quart = ["3122d7dd3535301d0f4075657b71842bbef9044a3086091e82637eade72c2f2a", "3b3e1207bdecbbae35b9aeef137abcf273768034423df77c9ad1034a105ddde3"] scipy = ["03b1e0775edbe6a4c64effb05fff2ce1429b76d29d754aa5ee2d848b60033351", "09d008237baabf52a5d4f5a6fcf9b3c03408f3f61a69c404472a16861a73917e", "10325f0ffac2400b1ec09537b7e403419dcd25d9fee602a44e8a32119af9079e", "1db9f964ed9c52dc5bd6127f0dd90ac89791daa690a5665cc01eae185912e1ba", "409846be9d6bdcbd78b9e5afe2f64b2da5a923dd7c1cd0615ce589489533fdbb", "4907040f62b91c2e170359c3d36c000af783f0fa1516a83d6c1517cde0af5340", "6c0543f2fdd38dee631fb023c0f31c284a532d205590b393d72009c14847f5b1", "826b9f5fbb7f908a13aa1efd4b7321e36992f5868d5d8311c7b40cf9b11ca0e7", "a7695a378c2ce402405ea37b12c7a338a8755e081869bd6b95858893ceb617ae", "a84c31e8409b420c3ca57fd30c7589378d6fdc8d155d866a7f8e6e80dec6fd06", "adadeeae5500de0da2b9e8dd478520d0a9945b577b2198f2462555e68f58e7ef", "b283a76a83fe463c9587a2c88003f800e08c3929dfbeba833b78260f9c209785", "c19a7389ab3cd712058a8c3c9ffd8d27a57f3d84b9c91a931f542682bb3d269d", "c3bb4bd2aca82fb498247deeac12265921fe231502a6bc6edea3ee7fe6c40a7a", "c5ea60ece0c0c1c849025bfc541b60a6751b491b6f11dd9ef37ab5b8c9041921", "db61a640ca20f237317d27bc658c1fc54c7581ff7f6502d112922dc285bdabee"] six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"] +sortedcontainers = ["974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a", "d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60"] toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"] -urllib3 = ["b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", "dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"] +typing = ["38566c558a0a94d6531012c8e917b1b8518a41e418f7f15f00e129cc80162ad3", "53765ec4f83a2b720214727e319607879fec4acde22c4fbb54fa2604e79e44ce", "84698954b4e6719e912ef9a42a2431407fe3755590831699debda6fba92aac55"] +typing-extensions = ["2ed632b30bb54fc3941c382decfd0ee4148f5c591651c9272473fea2c6397d95", "b1edbbf0652660e32ae780ac9433f4231e7339c7f9a8057d0f042fcbcea49b87", "d8179012ec2c620d3791ca6fe2bf7979d979acdbef1fca0bc56b37411db682ed"] +uvloop = ["0fcd894f6fc3226a962ee7ad895c4f52e3f5c3c55098e21efb17c071849a0573", "2f31de1742c059c96cb76b91c5275b22b22b965c886ee1fced093fa27dde9e64", "459e4649fcd5ff719523de33964aa284898e55df62761e7773d088823ccbd3e0", "67867aafd6e0bc2c30a079603a85d83b94f23c5593b3cc08ec7e58ac18bf48e5", "8c200457e6847f28d8bb91c5e5039d301716f5f2fce25646f5fb3fd65eda4a26", "958906b9ca39eb158414fbb7d6b8ef1b7aee4db5c8e8e5d00fcbb69a1ce9dca7", "ac1dca3d8f3ef52806059e81042ee397ac939e5a86c8a3cea55d6b087db66115", "b284c22d8938866318e3b9d178142b8be316c52d16fcfe1560685a686718a021", "c48692bf4587ce281d641087658eca275a5ad3b63c78297bbded96570ae9ce8f", "fefc3b2b947c99737c348887db2c32e539160dcbeb7af9aa6b53db7a283538fe"] virtualenv = ["b7335cddd9260a3dd214b73a2521ffc09647bde3e9457fcca31dc3be3999d04a", "d28ca64c0f3f125f59cabf13e0a150e1c68e5eea60983cc4395d88c584495783"] wcwidth = ["3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", "f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"] -werkzeug = ["865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c", "a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"] +wsproto = ["2b870f5b5b4a6d23dce080a4ee1cbb119b2378f82593bd6d66ae2cbd72a7c0ad", "ed222c812aaea55d72d18a87df429cfd602e15b6c992a07a53b495858f083a14"] +yarl = ["024ecdc12bc02b321bc66b41327f930d1c2c543fa9a561b39861da9388ba7aa9", "2f3010703295fbe1aec51023740871e64bb9664c789cba5a6bdf404e93f7568f", "3890ab952d508523ef4881457c4099056546593fa05e93da84c7250516e632eb", "3e2724eb9af5dc41648e5bb304fcf4891adc33258c6e14e2a7414ea32541e320", "5badb97dd0abf26623a9982cd448ff12cb39b8e4c94032ccdedf22ce01a64842", "73f447d11b530d860ca1e6b582f947688286ad16ca42256413083d13f260b7a0", "7ab825726f2940c16d92aaec7d204cfc34ac26c0040da727cf8ba87255a33829", "b25de84a8c20540531526dfbb0e2d2b648c13fd5dd126728c496d7c3fea33310", "c6e341f5a6562af74ba55205dbd56d248daf1b5748ec48a0200ba227bb9e33f4", "c9bb7c249c4432cd47e75af3864bc02d26c9594f49c82e2a28624417f0ae63b8", "e060906c0c585565c718d1c3841747b61c5439af2211e185f6739a9412dfbde1"] zipp = ["8c1019c6aad13642199fbe458275ad6a84907634cc9f0989877ccc4a2840139d", "ca943a7e809cc12257001ccfb99e3563da9af99d52f261725e96dfe0f9275bc3"] diff --git a/gentle_gnomes/pyproject.toml b/gentle_gnomes/pyproject.toml index e4cfb087..2f6acadf 100644 --- a/gentle_gnomes/pyproject.toml +++ b/gentle_gnomes/pyproject.toml @@ -8,15 +8,17 @@ packages = [ { include = "src" } ] [tool.poetry.dependencies] python = "^3.7" -flask = "^1.0" python-dotenv = "^0.10.3" -requests = "^2.22" scipy = "^1.3" +aiohttp = "^3.5" +quart = "^0.9.1" +uvloop = "^0.12.2" [tool.poetry.dev-dependencies] pytest = "^4.6" coverage = "^4.5" flake8 = "^3.7" +pytest-asyncio = "^0.10.0" pre-commit = "^1.17" flake8-bugbear = "^19.3" flake8-quotes = "^2.0" diff --git a/gentle_gnomes/src/__init__.py b/gentle_gnomes/src/__init__.py index 72971b62..3fece404 100644 --- a/gentle_gnomes/src/__init__.py +++ b/gentle_gnomes/src/__init__.py @@ -1,19 +1,25 @@ -from flask import Flask +import uvloop +from quart import Quart from . import azavea from . import view +uvloop.install() def create_app(test_config=None): - app = Flask(__name__, instance_relative_config=True) + app = Quart(__name__, instance_relative_config=True) app.config.from_mapping(SECRET_KEY='dev') + app.config.from_pyfile('config.py', silent=True) - if test_config is None: - app.config.from_pyfile('config.py', silent=True) - else: + if test_config is not None: app.config.from_mapping(test_config) + app.register_blueprint(view.bp) + app.azavea = azavea.Client(app.config['AZAVEA_TOKEN']) - app.register_blueprint(view.bp) + @app.teardown_appcontext + async def teardown(*args): + await app.azavea.teardown() + return app diff --git a/gentle_gnomes/src/azavea.py b/gentle_gnomes/src/azavea.py index e80ac7d3..01f0acc1 100644 --- a/gentle_gnomes/src/azavea.py +++ b/gentle_gnomes/src/azavea.py @@ -1,6 +1,6 @@ +import aiohttp import typing as t - -import requests +import asyncio as aio BASE_URL = 'https://app.climate.azavea.com/api' @@ -17,23 +17,31 @@ def __str__(self): class Client: """Client for interacting with the Azavea Climate API.""" + # Wait for async event loop to instanstiate + session: aiohttp.ClientSession = None + def __init__(self, token: str): - self.session = requests.Session() - self.session.headers = {'Authorization': f'Token {token}'} + self.headers = {'Authorization': f'Token {token}'} + + async def _get(self, endpoint: str, **kwargs) -> t.Union[t.Dict, t.List]: + if self.session is None: + self.session = aiohttp.ClientSession(headers=self.headers) + + async with self.session.get(BASE_URL + endpoint, **kwargs) as response: + return await response.json() - def _get(self, endpoint: str, **kwargs) -> t.Union[t.Dict, t.List]: - response = self.session.get(BASE_URL + endpoint, ** kwargs) - response.raise_for_status() + async def teardown(self): + if self.session is not None: + await self.session.close() - return response.json() - def get_cities(self, **kwargs) -> t.Iterator[City]: + async def get_cities(self, **kwargs) -> t.Iterator[City]: """Return all available cities.""" params = {'page': 1} params.update(kwargs.get('params', {})) while True: - cities = self._get('/city', params=params, **kwargs) + cities = await self._get('/city', params=params, **kwargs) if not cities.get('next'): break @@ -43,7 +51,7 @@ def get_cities(self, **kwargs) -> t.Iterator[City]: for city in cities['features']: yield City(city['properties']['name'], city['properties']['admin'], city['id']) - def get_nearest_city( + async def get_nearest_city( self, lat: float, lon: float, @@ -57,24 +65,24 @@ def get_nearest_city( 'limit': limit, } - cities = self._get('/city/nearest', params=params, **kwargs) + cities = await self._get('/city/nearest', params=params, **kwargs) if cities['count'] > 0: city = cities['features'][0] return City(city['properties']['name'], city['properties']['admin'], city['id']) - def get_scenarios(self, **kwargs) -> t.List: + async def get_scenarios(self, **kwargs) -> t.List: """Return all available scenarios.""" - return self._get('/scenario', **kwargs) + return await self._get('/scenario', **kwargs) - def get_indicators(self, **kwargs) -> t.Dict: + async def get_indicators(self, **kwargs) -> t.Dict: """Return the full list of indicators.""" - return self._get('/indicator', **kwargs) + return await self._get('/indicator', **kwargs) - def get_indicator_details(self, indicator: str, **kwargs) -> t.Dict: + async def get_indicator_details(self, indicator: str, **kwargs) -> t.Dict: """Return the description and parameters of a specified indicator.""" - return self._get(f'/indicator/{indicator}', **kwargs) + return await self._get(f'/indicator/{indicator}', **kwargs) - def get_indicator_data(self, city: int, scenario: str, indicator: str, **kwargs) -> t.Dict: + async def get_indicator_data(self, city: int, scenario: str, indicator: str, **kwargs) -> t.Dict: """Return derived climate indicator data for the requested indicator.""" - return self._get(f'/climate-data/{city}/{scenario}/indicator/{indicator}', **kwargs) + return await self._get(f'/climate-data/{city}/{scenario}/indicator/{indicator}', **kwargs) diff --git a/gentle_gnomes/src/indicator.py b/gentle_gnomes/src/indicator.py index ee9f7492..6a16108a 100644 --- a/gentle_gnomes/src/indicator.py +++ b/gentle_gnomes/src/indicator.py @@ -3,7 +3,7 @@ from typing import Tuple import numpy as np -from flask import current_app as app +from quart import current_app as app from scipy import stats from .azavea import City @@ -19,14 +19,13 @@ class Indicator: def __init__(self, name: str, city: City): self.name = name self.city = city - self._populate_data() - def _populate_data(self): + async def _populate_data(self): items = [] count = 0 for scenario in ('historical', 'RCP85'): - response = app.azavea.get_indicator_data(self.city.id, scenario, self.name) + response = await app.azavea.get_indicator_data(self.city.id, scenario, self.name) self.label = response['indicator']['label'] self.description = response['indicator']['description'] self.units = response['units'] @@ -50,13 +49,14 @@ def _calc_slope(x: np.ndarray, y: np.ndarray) -> float: return slope -def get_top_indicators(city: City, n: int = 5) -> Tuple[Indicator, ...]: +async def get_top_indicators(city: City, n: int = 5) -> Tuple[Indicator, ...]: """Return the top n indicators with the highest rate of change.""" rates = Counter() indicators = {} for name in INDICATORS: indicator = Indicator(name, city) + await self._populate_data() rates[name] = indicator.rate indicators[name] = indicator diff --git a/gentle_gnomes/src/view.py b/gentle_gnomes/src/view.py index dc913223..b100a568 100644 --- a/gentle_gnomes/src/view.py +++ b/gentle_gnomes/src/view.py @@ -1,32 +1,33 @@ import json -import flask -from flask import current_app as app -from flask import render_template +import quart +from quart import current_app as app +from quart import render_template from . import indicator -bp = flask.Blueprint('view', __name__, url_prefix='/') +bp = quart.Blueprint('view', __name__, url_prefix='/') @bp.route('/') -def index(): - return render_template('view/index.html') +async def index(): + return await render_template('view/index.html') @bp.route('/search', methods=['POST']) -def search(): +async def search(): try: - location = json.loads(flask.request.form['location']) + form = await quart.request.form + location = json.loads(form['location']) latitude = location['lat'] longitude = location['lng'] except (json.JSONDecodeError, KeyError): return render_template('view/results.html') - city = app.azavea.get_nearest_city(latitude, longitude) + city = await app.azavea.get_nearest_city(latitude, longitude) if city: with app.app_context(): - results = indicator.get_top_indicators(city) + results = await indicator.get_top_indicators(city) else: results = None diff --git a/gentle_gnomes/tests/conftest.py b/gentle_gnomes/tests/conftest.py index b99af980..10ed05b8 100644 --- a/gentle_gnomes/tests/conftest.py +++ b/gentle_gnomes/tests/conftest.py @@ -1,6 +1,7 @@ import pytest from src import create_app +from src.azavea import Client @pytest.fixture @@ -17,3 +18,8 @@ def client(app): @pytest.fixture def runner(app): return app.test_cli_runner() + + +@pytest.fixture +def azavea(app): + return Client(app.config['AZAVEA_TOKEN']) diff --git a/gentle_gnomes/tests/test_azavea.py b/gentle_gnomes/tests/test_azavea.py new file mode 100644 index 00000000..02562ee2 --- /dev/null +++ b/gentle_gnomes/tests/test_azavea.py @@ -0,0 +1,6 @@ +import pytest + + +@pytest.mark.asyncio +async def test_request_data_exists(azavea): + assert await azavea.get_indicators() diff --git a/gentle_gnomes/tests/test_view.py b/gentle_gnomes/tests/test_view.py index 275cd62a..b67cccb8 100644 --- a/gentle_gnomes/tests/test_view.py +++ b/gentle_gnomes/tests/test_view.py @@ -1,2 +1,7 @@ -def test_index_response_200(client): - assert client.get('/').status_code == 200 +import pytest + + +@pytest.mark.asyncio +async def test_index_response_200(client): + res = await client.get('/') + assert res.status_code == 200