refactor: purge Quart from the codebase

Most functionality is still broken
This commit is contained in:
Stefan Stammberger 2021-08-27 20:54:42 +02:00
parent ede038976f
commit 3e5af8c1d1
No known key found for this signature in database
GPG key ID: 645FA807E935D9D5
17 changed files with 962 additions and 181 deletions

12
Pipfile
View file

@ -14,12 +14,8 @@ environs = "*"
lnurl = "==0.3.6" lnurl = "==0.3.6"
pyscss = "*" pyscss = "*"
shortuuid = "*" shortuuid = "*"
quart = "*"
quart-cors = "*"
quart-compress = "*"
typing-extensions = "*" typing-extensions = "*"
httpx = "*" httpx = "*"
quart-trio = "*"
trio = "==0.16.0" trio = "==0.16.0"
sqlalchemy-aio = "*" sqlalchemy-aio = "*"
embit = "*" embit = "*"
@ -27,6 +23,10 @@ pyqrcode = "*"
pypng = "*" pypng = "*"
sqlalchemy = "==1.3.23" sqlalchemy = "==1.3.23"
psycopg2-binary = "*" psycopg2-binary = "*"
fastapi = {ref = "anyio", git = "https://github.com/graingert/fastapi"}
trio-asyncio = "*"
hypercorn = {extras = ["trio"], version = "*"}
aiofiles = "*"
[dev-packages] [dev-packages]
black = "==20.8b1" black = "==20.8b1"
@ -35,7 +35,3 @@ pytest-cov = "*"
mypy = "latest" mypy = "latest"
pytest-trio = "*" pytest-trio = "*"
trio-typing = "*" trio-typing = "*"
[packages.hypercorn]
extras = [ "trio",]
version = "*"

810
Pipfile.lock generated Normal file
View file

@ -0,0 +1,810 @@
{
"_meta": {
"hash": {
"sha256": "ff9251889371e0cec0eda7eb792e8618ea84f6c7eb85e9b472eacf3d3552c7c4"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.7"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"aiofiles": {
"hashes": [
"sha256:a1c4fc9b2ff81568c83e21392a82f344ea9d23da906e4f6a52662764545e19d4",
"sha256:c67a6823b5f23fcab0a2595a289cec7d8c863ffcb4322fb8cd6b90400aedfdbc"
],
"index": "pypi",
"version": "==0.7.0"
},
"anyio": {
"hashes": [
"sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0",
"sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374"
],
"markers": "python_full_version >= '3.6.2'",
"version": "==3.3.0"
},
"async-generator": {
"hashes": [
"sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b",
"sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"
],
"markers": "python_version >= '3.5'",
"version": "==1.10"
},
"attrs": {
"hashes": [
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==21.2.0"
},
"bech32": {
"hashes": [
"sha256:7d6db8214603bd7871fcfa6c0826ef68b85b0abd90fa21c285a9c5e21d2bd899",
"sha256:990dc8e5a5e4feabbdf55207b5315fdd9b73db40be294a19b3752cde9e79d981"
],
"markers": "python_version >= '3.5'",
"version": "==1.2.0"
},
"bitstring": {
"hashes": [
"sha256:0de167daa6a00c9386255a7cac931b45e6e24e0ad7ea64f1f92a64ac23ad4578",
"sha256:a5848a3f63111785224dca8bb4c0a75b62ecdef56a042c8d6be74b16f7e860e7",
"sha256:e3e340e58900a948787a05e8c08772f1ccbe133f6f41fe3f0fa19a18a22bbf4f"
],
"index": "pypi",
"version": "==3.1.9"
},
"cerberus": {
"hashes": [
"sha256:d1b21b3954b2498d9a79edf16b3170a3ac1021df88d197dc2ce5928ba519237c"
],
"index": "pypi",
"version": "==1.3.4"
},
"certifi": {
"hashes": [
"sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
"sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
],
"version": "==2021.5.30"
},
"charset-normalizer": {
"hashes": [
"sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b",
"sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
],
"markers": "python_version >= '3.5'",
"version": "==2.0.4"
},
"ecdsa": {
"hashes": [
"sha256:5cf31d5b33743abe0dfc28999036c849a69d548f994b535e527ee3cb7f3ef676",
"sha256:b9f500bb439e4153d0330610f5d26baaf18d17b8ced1bc54410d189385ea68aa"
],
"index": "pypi",
"version": "==0.17.0"
},
"embit": {
"hashes": [
"sha256:19f69929caf0d2fcfd4b708dd873384dfc36267944d02d5e6dfebc835f294e1b"
],
"index": "pypi",
"version": "==0.4.6"
},
"environs": {
"hashes": [
"sha256:72b867ff7b553076cdd90f3ee01ecc1cf854987639c9c459f0ed0d3d44ae490c",
"sha256:ee5466156b50fe03aa9fec6e720feea577b5bf515d7f21b2c46608272557ba26"
],
"index": "pypi",
"version": "==9.3.3"
},
"fastapi": {
"git": "https://github.com/graingert/fastapi",
"ref": "ada7c747c05c88d37e012d32e97bcc9579f3f006"
},
"h11": {
"hashes": [
"sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6",
"sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"
],
"markers": "python_version >= '3.6'",
"version": "==0.12.0"
},
"h2": {
"hashes": [
"sha256:ac9e293a1990b339d5d71b19c5fe630e3dd4d768c620d1730d355485323f1b25",
"sha256:bb7ac7099dd67a857ed52c815a6192b6b1f5ba6b516237fc24a085341340593d"
],
"markers": "python_full_version >= '3.6.1'",
"version": "==4.0.0"
},
"hpack": {
"hashes": [
"sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c",
"sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"
],
"markers": "python_full_version >= '3.6.1'",
"version": "==4.0.0"
},
"httpcore": {
"hashes": [
"sha256:b0d16f0012ec88d8cc848f5a55f8a03158405f4bca02ee49bc4ca2c1fda49f3e",
"sha256:db4c0dcb8323494d01b8c6d812d80091a31e520033e7b0120883d6f52da649ff"
],
"markers": "python_version >= '3.6'",
"version": "==0.13.6"
},
"httpx": {
"hashes": [
"sha256:92ecd2c00c688b529eda11cedb15161eaf02dee9116712f621c70d9a40b2cdd0",
"sha256:9bd728a6c5ec0a9e243932a9983d57d3cc4a87bb4f554e1360fce407f78f9435"
],
"index": "pypi",
"version": "==0.19.0"
},
"hypercorn": {
"extras": [
"trio"
],
"hashes": [
"sha256:5ba1e719c521080abd698ff5781a2331e34ef50fc1c89a50960538115a896a9a",
"sha256:8007c10f81566920f8ae12c0e26e146f94ca70506da964b5a727ad610aa1d821"
],
"index": "pypi",
"version": "==0.11.2"
},
"hyperframe": {
"hashes": [
"sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15",
"sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"
],
"markers": "python_full_version >= '3.6.1'",
"version": "==6.0.1"
},
"idna": {
"hashes": [
"sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
"sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
],
"version": "==3.2"
},
"lnurl": {
"hashes": [
"sha256:579982fd8c4d25bc84c61c74ec45cb7999fa1fa2426f5d5aeb0160ba333b9c92",
"sha256:8af07460115a48f3122a5a9c9a6062bee3897d5f6ab4c9a60f6561a83a8234f6"
],
"index": "pypi",
"version": "==0.3.6"
},
"marshmallow": {
"hashes": [
"sha256:c67929438fd73a2be92128caa0325b1b5ed8b626d91a094d2f7f2771bf1f1c0e",
"sha256:dd4724335d3c2b870b641ffe4a2f8728a1380cd2e7e2312756715ffeaa82b842"
],
"markers": "python_version >= '3.5'",
"version": "==3.13.0"
},
"outcome": {
"hashes": [
"sha256:c7dd9375cfd3c12db9801d080a3b63d4b0a261aa996c4c13152380587288d958",
"sha256:e862f01d4e626e63e8f92c38d1f8d5546d3f9cce989263c521b2e7990d186967"
],
"markers": "python_version >= '3.6'",
"version": "==1.1.0"
},
"priority": {
"hashes": [
"sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa",
"sha256:c965d54f1b8d0d0b19479db3924c7c36cf672dbf2aec92d43fbdaf4492ba18c0"
],
"markers": "python_full_version >= '3.6.1'",
"version": "==2.0.0"
},
"psycopg2-binary": {
"hashes": [
"sha256:0b7dae87f0b729922e06f85f667de7bf16455d411971b2043bbd9577af9d1975",
"sha256:0f2e04bd2a2ab54fa44ee67fe2d002bb90cee1c0f1cc0ebc3148af7b02034cbd",
"sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616",
"sha256:1473c0215b0613dd938db54a653f68251a45a78b05f6fc21af4326f40e8360a2",
"sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90",
"sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a",
"sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e",
"sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d",
"sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed",
"sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a",
"sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140",
"sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32",
"sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31",
"sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a",
"sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917",
"sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf",
"sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7",
"sha256:a36c7eb6152ba5467fb264d73844877be8b0847874d4822b7cf2d3c0cb8cdcb0",
"sha256:aed4a9a7e3221b3e252c39d0bf794c438dc5453bc2963e8befe9d4cd324dff72",
"sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698",
"sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773",
"sha256:b4d7679a08fea64573c969f6994a2631908bb2c0e69a7235648642f3d2e39a68",
"sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76",
"sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4",
"sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f",
"sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34",
"sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce",
"sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a",
"sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e"
],
"index": "pypi",
"version": "==2.9.1"
},
"pydantic": {
"hashes": [
"sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd",
"sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739",
"sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f",
"sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840",
"sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23",
"sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287",
"sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62",
"sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b",
"sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb",
"sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820",
"sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3",
"sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b",
"sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e",
"sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3",
"sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316",
"sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b",
"sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4",
"sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20",
"sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e",
"sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505",
"sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1",
"sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"
],
"markers": "python_full_version >= '3.6.1'",
"version": "==1.8.2"
},
"pypng": {
"hashes": [
"sha256:76f8a1539ec56451da7ab7121f12a361969fe0f2d48d703d198ce2a99d6c5afd"
],
"index": "pypi",
"version": "==0.0.21"
},
"pyqrcode": {
"hashes": [
"sha256:1b2812775fa6ff5c527977c4cd2ccb07051ca7d0bc0aecf937a43864abe5eff6",
"sha256:fdbf7634733e56b72e27f9bce46e4550b75a3a2c420414035cae9d9d26b234d5"
],
"index": "pypi",
"version": "==1.2.1"
},
"pyscss": {
"hashes": [
"sha256:f1df571569021a23941a538eb154405dde80bed35dc1ea7c5f3e18e0144746bf"
],
"index": "pypi",
"version": "==1.3.7"
},
"python-dotenv": {
"hashes": [
"sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1",
"sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172"
],
"markers": "python_version >= '3.5'",
"version": "==0.19.0"
},
"represent": {
"hashes": [
"sha256:026c0de2ee8385d1255b9c2426cd4f03fe9177ac94c09979bc601946c8493aa0",
"sha256:99142650756ef1998ce0661568f54a47dac8c638fb27e3816c02536575dbba8c"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.6.0.post0"
},
"rfc3986": {
"extras": [
"idna2008"
],
"hashes": [
"sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835",
"sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"
],
"version": "==1.5.0"
},
"shortuuid": {
"hashes": [
"sha256:3c11d2007b915c43bee3e10625f068d8a349e04f0d81f08f5fa08507427ebf1f",
"sha256:492c7402ff91beb1342a5898bd61ea953985bf24a41cd9f247409aa2e03c8f77"
],
"index": "pypi",
"version": "==1.0.1"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"sniffio": {
"hashes": [
"sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663",
"sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"
],
"markers": "python_version >= '3.5'",
"version": "==1.2.0"
},
"sortedcontainers": {
"hashes": [
"sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88",
"sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"
],
"version": "==2.4.0"
},
"sqlalchemy": {
"hashes": [
"sha256:040bdfc1d76a9074717a3f43455685f781c581f94472b010cd6c4754754e1862",
"sha256:1fe5d8d39118c2b018c215c37b73fd6893c3e1d4895be745ca8ff6eb83333ed3",
"sha256:23927c3981d1ec6b4ea71eb99d28424b874d9c696a21e5fbd9fa322718be3708",
"sha256:24f9569e82a009a09ce2d263559acb3466eba2617203170e4a0af91e75b4f075",
"sha256:2578dbdbe4dbb0e5126fb37ffcd9793a25dcad769a95f171a2161030bea850ff",
"sha256:269990b3ab53cb035d662dcde51df0943c1417bdab707dc4a7e4114a710504b4",
"sha256:29cccc9606750fe10c5d0e8bd847f17a97f3850b8682aef1f56f5d5e1a5a64b1",
"sha256:37b83bf81b4b85dda273aaaed5f35ea20ad80606f672d94d2218afc565fb0173",
"sha256:63677d0c08524af4c5893c18dbe42141de7178001360b3de0b86217502ed3601",
"sha256:639940bbe1108ac667dcffc79925db2966826c270112e9159439ab6bb14f8d80",
"sha256:6a939a868fdaa4b504e8b9d4a61f21aac11e3fecc8a8214455e144939e3d2aea",
"sha256:6b8b8c80c7f384f06825612dd078e4a31f0185e8f1f6b8c19e188ff246334205",
"sha256:6c9e6cc9237de5660bcddea63f332428bb83c8e2015c26777281f7ffbd2efb84",
"sha256:6ec1044908414013ebfe363450c22f14698803ce97fbb47e53284d55c5165848",
"sha256:6fca33672578666f657c131552c4ef8979c1606e494f78cd5199742dfb26918b",
"sha256:751934967f5336a3e26fc5993ccad1e4fee982029f9317eb6153bc0bc3d2d2da",
"sha256:8be835aac18ec85351385e17b8665bd4d63083a7160a017bef3d640e8e65cadb",
"sha256:927ce09e49bff3104459e1451ce82983b0a3062437a07d883a4c66f0b344c9b5",
"sha256:94208867f34e60f54a33a37f1c117251be91a47e3bfdb9ab8a7847f20886ad06",
"sha256:94f667d86be82dd4cb17d08de0c3622e77ca865320e0b95eae6153faa7b4ecaf",
"sha256:9e9c25522933e569e8b53ccc644dc993cab87e922fb7e142894653880fdd419d",
"sha256:a0e306e9bb76fd93b29ae3a5155298e4c1b504c7cbc620c09c20858d32d16234",
"sha256:a8bfc1e1afe523e94974132d7230b82ca7fa2511aedde1f537ec54db0399541a",
"sha256:ac2244e64485c3778f012951fdc869969a736cd61375fde6096d08850d8be729",
"sha256:b4b0e44d586cd64b65b507fa116a3814a1a53d55dce4836d7c1a6eb2823ff8d1",
"sha256:baeb451ee23e264de3f577fee5283c73d9bbaa8cb921d0305c0bbf700094b65b",
"sha256:c7dc052432cd5d060d7437e217dd33c97025287f99a69a50e2dc1478dd610d64",
"sha256:d1a85dfc5dee741bf49cb9b6b6b8d2725a268e4992507cf151cba26b17d97c37",
"sha256:d90010304abb4102123d10cbad2cdf2c25a9f2e66a50974199b24b468509bad5",
"sha256:ddfb511e76d016c3a160910642d57f4587dc542ce5ee823b0d415134790eeeb9",
"sha256:e273367f4076bd7b9a8dc2e771978ef2bfd6b82526e80775a7db52bff8ca01dd",
"sha256:e5bb3463df697279e5459a7316ad5a60b04b0107f9392e88674d0ece70e9cf70",
"sha256:e8a1750b44ad6422ace82bf3466638f1aa0862dbb9689690d5f2f48cce3476c8",
"sha256:eab063a70cca4a587c28824e18be41d8ecc4457f8f15b2933584c6c6cccd30f0",
"sha256:ecce8c021894a77d89808222b1ff9687ad84db54d18e4bd0500ca766737faaf6",
"sha256:f4d972139d5000105fcda9539a76452039434013570d6059993120dc2a65e447",
"sha256:fd3b96f8c705af8e938eaa99cbd8fd1450f632d38cad55e7367c33b263bf98ec",
"sha256:fdd2ed7395df8ac2dbb10cefc44737b66c6a5cd7755c92524733d7a443e5b7e2"
],
"index": "pypi",
"version": "==1.3.23"
},
"sqlalchemy-aio": {
"hashes": [
"sha256:7f77366f55d34891c87386dd0962a28b948b684e8ea5edb7daae4187c0b291bf",
"sha256:f767320427c22c66fa5840a1f17f3261110a8ddc8560558f4fbf12d31a66b17b"
],
"index": "pypi",
"version": "==0.16.0"
},
"toml": {
"hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.2"
},
"trio": {
"hashes": [
"sha256:451ddb27b4e5215e00646fcbb8028d341fccf284e053dc376506a14bb133dbcf",
"sha256:df067dd0560c321af39d412cd81fc3a7d13f55af9150527daab980683e9fcf3c"
],
"index": "pypi",
"version": "==0.16.0"
},
"trio-asyncio": {
"hashes": [
"sha256:824be23b0c678c0df942816cdb57b92a8b94f264fffa89f04626b0ba2d009768",
"sha256:9bf678f83204ba33c395783681c69af563a84145fad2110a152a81a4a18ae7e4"
],
"index": "pypi",
"version": "==0.12.0"
},
"typing-extensions": {
"hashes": [
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
"sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
"sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
],
"index": "pypi",
"version": "==3.10.0.0"
},
"wsproto": {
"hashes": [
"sha256:868776f8456997ad0d9720f7322b746bbe9193751b5b290b7f924659377c8c38",
"sha256:d8345d1808dd599b5ffb352c25a367adb6157e664e140dbecba3f9bc007edb9f"
],
"markers": "python_full_version >= '3.6.1'",
"version": "==1.0.0"
}
},
"develop": {
"appdirs": {
"hashes": [
"sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
"sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
],
"version": "==1.4.4"
},
"async-generator": {
"hashes": [
"sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b",
"sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"
],
"markers": "python_version >= '3.5'",
"version": "==1.10"
},
"attrs": {
"hashes": [
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==21.2.0"
},
"black": {
"hashes": [
"sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"
],
"index": "pypi",
"version": "==20.8b1"
},
"click": {
"hashes": [
"sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
"sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
],
"markers": "python_version >= '3.6'",
"version": "==8.0.1"
},
"coverage": {
"hashes": [
"sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c",
"sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6",
"sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45",
"sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a",
"sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03",
"sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529",
"sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a",
"sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a",
"sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2",
"sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6",
"sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759",
"sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53",
"sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a",
"sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4",
"sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff",
"sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502",
"sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793",
"sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb",
"sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905",
"sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821",
"sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b",
"sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81",
"sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0",
"sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b",
"sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3",
"sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184",
"sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701",
"sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a",
"sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82",
"sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638",
"sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5",
"sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083",
"sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6",
"sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90",
"sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465",
"sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a",
"sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3",
"sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e",
"sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066",
"sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf",
"sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b",
"sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae",
"sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669",
"sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873",
"sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b",
"sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6",
"sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb",
"sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160",
"sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c",
"sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079",
"sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d",
"sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
"version": "==5.5"
},
"idna": {
"hashes": [
"sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
"sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
],
"version": "==3.2"
},
"importlib-metadata": {
"hashes": [
"sha256:9e04bf59076a15a9b6dd9c27806e8fcdf15280ba529c6a8cc3f4d5b4875bdd61",
"sha256:c4eb3dec5f697682e383a39701a7de11cd5c02daf8dd93534b69e3e6473f6b1b"
],
"markers": "python_version < '3.8'",
"version": "==4.7.1"
},
"iniconfig": {
"hashes": [
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
],
"version": "==1.1.1"
},
"mypy": {
"hashes": [
"sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9",
"sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a",
"sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9",
"sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e",
"sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2",
"sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212",
"sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b",
"sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885",
"sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150",
"sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703",
"sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072",
"sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457",
"sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e",
"sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0",
"sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb",
"sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97",
"sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8",
"sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811",
"sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6",
"sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de",
"sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504",
"sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921",
"sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"
],
"index": "pypi",
"version": "==0.910"
},
"mypy-extensions": {
"hashes": [
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
],
"version": "==0.4.3"
},
"outcome": {
"hashes": [
"sha256:c7dd9375cfd3c12db9801d080a3b63d4b0a261aa996c4c13152380587288d958",
"sha256:e862f01d4e626e63e8f92c38d1f8d5546d3f9cce989263c521b2e7990d186967"
],
"markers": "python_version >= '3.6'",
"version": "==1.1.0"
},
"packaging": {
"hashes": [
"sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7",
"sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"
],
"markers": "python_version >= '3.6'",
"version": "==21.0"
},
"pathspec": {
"hashes": [
"sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a",
"sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"
],
"version": "==0.9.0"
},
"pluggy": {
"hashes": [
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.13.1"
},
"py": {
"hashes": [
"sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3",
"sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.10.0"
},
"pyparsing": {
"hashes": [
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.4.7"
},
"pytest": {
"hashes": [
"sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b",
"sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"
],
"index": "pypi",
"version": "==6.2.4"
},
"pytest-cov": {
"hashes": [
"sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a",
"sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"
],
"index": "pypi",
"version": "==2.12.1"
},
"pytest-trio": {
"hashes": [
"sha256:c01b741819aec2c419555f28944e132d3c711dae1e673d63260809bf92c30c31"
],
"index": "pypi",
"version": "==0.7.0"
},
"regex": {
"hashes": [
"sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354",
"sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308",
"sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d",
"sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc",
"sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8",
"sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797",
"sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2",
"sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13",
"sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d",
"sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a",
"sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0",
"sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73",
"sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1",
"sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed",
"sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a",
"sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b",
"sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f",
"sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256",
"sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb",
"sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983",
"sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb",
"sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645",
"sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8",
"sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906",
"sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f",
"sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892",
"sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0",
"sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e",
"sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e",
"sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed",
"sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c",
"sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374",
"sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791",
"sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a",
"sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1",
"sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"
],
"version": "==2021.8.28"
},
"sniffio": {
"hashes": [
"sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663",
"sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"
],
"markers": "python_version >= '3.5'",
"version": "==1.2.0"
},
"sortedcontainers": {
"hashes": [
"sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88",
"sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"
],
"version": "==2.4.0"
},
"toml": {
"hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.2"
},
"trio": {
"hashes": [
"sha256:451ddb27b4e5215e00646fcbb8028d341fccf284e053dc376506a14bb133dbcf",
"sha256:df067dd0560c321af39d412cd81fc3a7d13f55af9150527daab980683e9fcf3c"
],
"index": "pypi",
"version": "==0.16.0"
},
"trio-typing": {
"hashes": [
"sha256:3eae317514ca18af158bd14ec55ccf20e8b1461efc3a431b87c337a9ca97180b",
"sha256:c3717f097eab29f8deb58a6976da366bd98adb81d90f38002b564932839eaa84"
],
"index": "pypi",
"version": "==0.5.1"
},
"typed-ast": {
"hashes": [
"sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace",
"sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff",
"sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266",
"sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528",
"sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6",
"sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808",
"sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4",
"sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363",
"sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341",
"sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04",
"sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41",
"sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e",
"sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3",
"sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899",
"sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805",
"sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c",
"sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c",
"sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39",
"sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a",
"sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3",
"sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7",
"sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f",
"sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075",
"sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0",
"sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40",
"sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428",
"sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927",
"sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3",
"sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f",
"sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"
],
"markers": "python_version < '3.8'",
"version": "==1.4.3"
},
"typing-extensions": {
"hashes": [
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
"sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
"sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
],
"index": "pypi",
"version": "==3.10.0.0"
},
"zipp": {
"hashes": [
"sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
"sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
],
"markers": "python_version >= '3.6'",
"version": "==3.5.0"
}
}
}

View file

@ -1,37 +1,27 @@
import jinja2
from lnbits.jinja2_templating import Jinja2Templates
import sys
import warnings
import importlib import importlib
import sys
import traceback import traceback
import trio import warnings
import trio
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware from fastapi.middleware.gzip import GZipMiddleware
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
import lnbits.settings
from .commands import db_migrate, handle_assets from .commands import db_migrate, handle_assets
from .core import core_app from .core import core_app
from .helpers import (
get_valid_extensions,
get_js_vendored,
get_css_vendored,
url_for_vendored,
)
from .proxy_fix import ASGIProxyFix
from .tasks import (
webhook_handler,
invoice_listener,
run_deferred_async,
check_pending_payments,
internal_invoice_listener,
catch_everything_and_restart,
)
from .settings import WALLET
from .requestvars import g, request_global
from .core.views.generic import core_html_routes from .core.views.generic import core_html_routes
import lnbits.settings from .helpers import (get_css_vendored, get_js_vendored, get_valid_extensions,
template_renderer, url_for_vendored)
from .requestvars import g
from .settings import WALLET
from .tasks import (check_pending_payments, internal_invoice_listener,
invoice_listener, run_deferred_async, webhook_handler)
async def create_app(config_object="lnbits.settings") -> FastAPI: async def create_app(config_object="lnbits.settings") -> FastAPI:
"""Create application factory. """Create application factory.
@ -55,7 +45,16 @@ async def create_app(config_object="lnbits.settings") -> FastAPI:
) )
g().config = lnbits.settings g().config = lnbits.settings
g().templates = build_standard_jinja_templates() g().base_url = f"http://{lnbits.settings.HOST}:{lnbits.settings.PORT}"
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return template_renderer().TemplateResponse("error.html", {"request": request, "err": f"`{exc.errors()}` is not a valid UUID."})
# return HTMLResponse(
# status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
# content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),
# )
app.add_middleware(GZipMiddleware, minimum_size=1000) app.add_middleware(GZipMiddleware, minimum_size=1000)
# app.add_middleware(ASGIProxyFix) # app.add_middleware(ASGIProxyFix)
@ -69,26 +68,6 @@ async def create_app(config_object="lnbits.settings") -> FastAPI:
return app return app
def build_standard_jinja_templates():
t = Jinja2Templates(
loader=jinja2.FileSystemLoader(["lnbits/templates", "lnbits/core/templates"]),
)
t.env.globals["SITE_TITLE"] = lnbits.settings.LNBITS_SITE_TITLE
t.env.globals["SITE_TAGLINE"] = lnbits.settings.LNBITS_SITE_TAGLINE
t.env.globals["SITE_DESCRIPTION"] = lnbits.settings.LNBITS_SITE_DESCRIPTION
t.env.globals["LNBITS_THEME_OPTIONS"] = lnbits.settings.LNBITS_THEME_OPTIONS
t.env.globals["LNBITS_VERSION"] = lnbits.settings.LNBITS_COMMIT
t.env.globals["EXTENSIONS"] = get_valid_extensions()
if g().config.DEBUG:
t.env.globals["VENDORED_JS"] = map(url_for_vendored, get_js_vendored())
t.env.globals["VENDORED_CSS"] = map(url_for_vendored, get_css_vendored())
else:
t.env.globals["VENDORED_JS"] = ["/static/bundle.js"]
t.env.globals["VENDORED_CSS"] = ["/static/bundle.css"]
return t
def check_funding_source(app: FastAPI) -> None: def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup") @app.on_event("startup")
async def check_wallet_status(): async def check_wallet_status():
@ -171,5 +150,5 @@ def register_exception_handlers(app):
etype, value, tb = sys.exc_info() etype, value, tb = sys.exc_info()
traceback.print_exception(etype, err, tb) traceback.print_exception(etype, err, tb)
exc = traceback.format_exc() exc = traceback.format_exc()
return g().templates.TemplateResponse("error.html", {"request": request, "err": err}) return template_renderer().TemplateResponse("error.html", {"request": request, "err": err})

View file

@ -1,7 +1,7 @@
import json import json
import hmac import hmac
import hashlib import hashlib
from quart import url_for from lnbits.helpers import url_for
from ecdsa import SECP256k1, SigningKey # type: ignore from ecdsa import SECP256k1, SigningKey # type: ignore
from lnurl import encode as lnurl_encode # type: ignore from lnurl import encode as lnurl_encode # type: ignore
from typing import List, NamedTuple, Optional, Dict from typing import List, NamedTuple, Optional, Dict
@ -30,11 +30,12 @@ class Wallet(BaseModel):
@property @property
def lnurlwithdraw_full(self) -> str: def lnurlwithdraw_full(self) -> str:
url = url_for( url = url_for(
"core.lnurl_full_withdraw", "/withdraw",
external=True,
usr=self.user, usr=self.user,
wal=self.id, wal=self.id,
_external=True,
) )
try: try:
return lnurl_encode(url) return lnurl_encode(url)

View file

@ -5,7 +5,6 @@ from io import BytesIO
from binascii import unhexlify from binascii import unhexlify
from typing import Optional, Tuple, Dict from typing import Optional, Tuple, Dict
from urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
from quart import g, url_for
from lnurl import LnurlErrorResponse, decode as decode_lnurl # type: ignore from lnurl import LnurlErrorResponse, decode as decode_lnurl # type: ignore
try: try:
@ -15,9 +14,10 @@ except ImportError: # pragma: nocover
from lnbits import bolt11 from lnbits import bolt11
from lnbits.db import Connection from lnbits.db import Connection
from lnbits.helpers import urlsafe_short_hash from lnbits.helpers import url_for, urlsafe_short_hash
from lnbits.settings import WALLET from lnbits.settings import WALLET
from lnbits.wallets.base import PaymentStatus, PaymentResponse from lnbits.wallets.base import PaymentStatus, PaymentResponse
from lnbits.requestvars import g
from . import db from . import db
from .crud import ( from .crud import (
@ -220,10 +220,9 @@ async def redeem_lnurl_withdraw(
try: try:
params["balanceNotify"] = url_for( params["balanceNotify"] = url_for(
"core.lnurl_balance_notify", f"/withdraw/notify/{urlparse(lnurl_request).netloc}",
service=urlparse(lnurl_request).netloc, external=True,
wal=wallet_id, wal=wallet_id,
_external=True,
) )
except Exception: except Exception:
pass pass
@ -242,7 +241,7 @@ async def perform_lnurlauth(
cb = urlparse(callback) cb = urlparse(callback)
k1 = unhexlify(parse_qs(cb.query)["k1"][0]) k1 = unhexlify(parse_qs(cb.query)["k1"][0])
key = g.wallet.lnurlauth_key(cb.netloc) key = g().wallet.lnurlauth_key(cb.netloc)
def int_to_bytes_suitable_der(x: int) -> bytes: def int_to_bytes_suitable_der(x: int) -> bytes:
"""for strict DER we need to encode the integer with some quirks""" """for strict DER we need to encode the integer with some quirks"""

View file

@ -1,3 +1,4 @@
from lnbits.helpers import url_for
from fastapi.param_functions import Depends from fastapi.param_functions import Depends
from lnbits.auth_bearer import AuthBearer from lnbits.auth_bearer import AuthBearer
from pydantic import BaseModel from pydantic import BaseModel
@ -6,7 +7,6 @@ import json
import httpx import httpx
import hashlib import hashlib
from urllib.parse import urlparse, urlunparse, urlencode, parse_qs, ParseResult from urllib.parse import urlparse, urlunparse, urlencode, parse_qs, ParseResult
from quart import current_app, make_response, url_for
from fastapi import Query from fastapi import Query
@ -121,10 +121,9 @@ async def api_payments_create_invoice(data: CreateInvoiceData):
params={ params={
"pr": payment_request, "pr": payment_request,
"balanceNotify": url_for( "balanceNotify": url_for(
"core.lnurl_balance_notify", f"/withdraw/notify/{urlparse(data.lnurl_callback).netloc}",
service=urlparse(data.lnurl_callback).netloc, external=True,
wal=g().wallet.id, wal=g().wallet.id,
_external=True,
), ),
}, },
timeout=10, timeout=10,

View file

@ -1,32 +1,24 @@
from lnbits.core.models import Wallet
from fastapi.params import Query
from fastapi.routing import APIRouter
from fastapi.responses import RedirectResponse
from fastapi import status
from lnbits.requestvars import g
from os import path
from http import HTTPStatus from http import HTTPStatus
from typing import Optional from typing import Optional
import jinja2
from fastapi import Request, status
from fastapi.param_functions import Body
from fastapi.params import Depends, Query
from fastapi.responses import FileResponse, RedirectResponse
from fastapi.routing import APIRouter
from pydantic.types import UUID4
from starlette.responses import HTMLResponse from starlette.responses import HTMLResponse
from lnbits.core import core_app, db from lnbits.core import db
from lnbits.decorators import check_user_exists, validate_uuids from lnbits.helpers import template_renderer, url_for
from lnbits.settings import LNBITS_ALLOWED_USERS, SERVICE_FEE, LNBITS_SITE_TITLE from lnbits.requestvars import g
from lnbits.settings import (LNBITS_ALLOWED_USERS, LNBITS_SITE_TITLE,
SERVICE_FEE)
from ..crud import ( from ..crud import (create_account, create_wallet, delete_wallet,
create_account, get_balance_check, get_user, save_balance_notify,
get_user, update_user_extension)
update_user_extension, from ..services import pay_invoice, redeem_lnurl_withdraw
create_wallet,
delete_wallet,
get_balance_check,
save_balance_notify,
)
from ..services import redeem_lnurl_withdraw, pay_invoice
from fastapi import FastAPI, Request
from fastapi.responses import FileResponse
core_html_routes: APIRouter = APIRouter(tags=["Core NON-API Website Routes"]) core_html_routes: APIRouter = APIRouter(tags=["Core NON-API Website Routes"])
@ -37,13 +29,13 @@ async def favicon():
@core_html_routes.get("/", response_class=HTMLResponse) @core_html_routes.get("/", response_class=HTMLResponse)
async def home(request: Request, lightning: str = None): async def home(request: Request, lightning: str = None):
return g().templates.TemplateResponse("core/index.html", {"request": request, "lnurl": lightning}) return template_renderer().TemplateResponse("core/index.html", {"request": request, "lnurl": lightning})
@core_html_routes.get("/extensions") @core_html_routes.get("/extensions")
@validate_uuids(["usr"], required=True) # @validate_uuids(["usr"], required=True)
@check_user_exists() # @check_user_exists()
async def extensions(enable: str, disable: str): async def extensions(request: Request, enable: str, disable: str):
extension_to_enable = enable extension_to_enable = enable
extension_to_disable = disable extension_to_disable = disable
@ -60,20 +52,16 @@ async def extensions(enable: str, disable: str):
await update_user_extension( await update_user_extension(
user_id=g.user.id, extension=extension_to_disable, active=False user_id=g.user.id, extension=extension_to_disable, active=False
) )
return await templates.TemplateResponse("core/extensions.html", {"request": request, "user": get_user(g.user.id)}) return template_renderer().TemplateResponse("core/extensions.html", {"request": request, "user": get_user(g.user.id)})
@core_html_routes.get("/wallet", response_class=HTMLResponse) @core_html_routes.get("/wallet", response_class=HTMLResponse)
#Not sure how to validate #Not sure how to validate
@validate_uuids(["usr", "wal"]) # @validate_uuids(["usr", "nme"])
async def wallet(request: Request, async def wallet(request: Request = Query(None), nme: Optional[str] = Query(None),
usr: Optional[str] = Query(None), usr: Optional[UUID4] = Query(None), wal: Optional[UUID4] = Query(None)):
wal: Optional[str] = Query(None), user_id = usr.hex if usr else None
nme: Optional[str] = Query(None), wallet_id = wal.hex if wal else None
):
user_id = usr
wallet_id = wal
wallet_name = nme wallet_name = nme
service_fee = int(SERVICE_FEE) if int(SERVICE_FEE) == SERVICE_FEE else SERVICE_FEE service_fee = int(SERVICE_FEE) if int(SERVICE_FEE) == SERVICE_FEE else SERVICE_FEE
@ -84,33 +72,33 @@ async def wallet(request: Request,
# nothing: create everything # nothing: create everything
if not user_id: if not user_id:
usr = await get_user((await create_account()).id) user = await get_user((await create_account()).id)
else: else:
usr = await get_user(user_id) user = await get_user(user_id)
if not usr: if not user:
return g().templates.TemplateResponse("error.html", {"request": request, "err": "User does not exist."}) return template_renderer().TemplateResponse("error.html", {"request": request, "err": "User does not exist."})
if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS: if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
return g().templates.TemplateResponse("error.html", {"request": request, "err": "User not authorized."}) return template_renderer().TemplateResponse("error.html", {"request": request, "err": "User not authorized."})
if not wallet_id: if not wallet_id:
if usr.wallets and not wallet_name: if user.wallets and not wallet_name:
wal = usr.wallets[0] wallet = user.wallets[0]
else: else:
wal = await create_wallet(user_id=usr.id, wallet_name=wallet_name) wallet = await create_wallet(user_id=user.id, wallet_name=wallet_name)
return RedirectResponse(f"/wallet?usr={usr.id}&wal={wal.id}", status_code=status.HTTP_307_TEMPORARY_REDIRECT) return RedirectResponse(f"/wallet?usr={user.id}&wal={wallet.id}", status_code=status.HTTP_307_TEMPORARY_REDIRECT)
wal = usr.get_wallet(wallet_id) wallet = user.get_wallet(wallet_id)
if not wal: if not wallet:
return g().templates.TemplateResponse("error.html", {"request": request, ...}) return template_renderer().TemplateResponse("error.html", {"request": request, "err": "Wallet not found"})
return g().templates.TemplateResponse( return template_renderer().TemplateResponse(
"core/wallet.html", {"request":request,"user":usr, "wallet":wal, "service_fee":service_fee} "core/wallet.html", {"request":request,"user":user.dict(), "wallet":wallet.dict(), "service_fee":service_fee}
) )
@core_html_routes.get("/withdraw") @core_html_routes.get("/withdraw")
@validate_uuids(["usr", "wal"], required=True) # @validate_uuids(["usr", "wal"], required=True)
async def lnurl_full_withdraw(): async def lnurl_full_withdraw(request: Request):
user = await get_user(request.args.get("usr")) user = await get_user(request.args.get("usr"))
if not user: if not user:
return {"status": "ERROR", "reason": "User does not exist."} return {"status": "ERROR", "reason": "User does not exist."}
@ -122,24 +110,22 @@ async def lnurl_full_withdraw():
return { return {
"tag": "withdrawRequest", "tag": "withdrawRequest",
"callback": url_for( "callback": url_for(
"core.lnurl_full_withdraw_callback", "/withdraw/cb",
external=True,
usr=user.id, usr=user.id,
wal=wallet.id, wal=wallet.id,
_external=True,
), ),
"k1": "0", "k1": "0",
"minWithdrawable": 1000 if wallet.withdrawable_balance else 0, "minWithdrawable": 1000 if wallet.withdrawable_balance else 0,
"maxWithdrawable": wallet.withdrawable_balance, "maxWithdrawable": wallet.withdrawable_balance,
"defaultDescription": f"{LNBITS_SITE_TITLE} balance withdraw from {wallet.id[0:5]}", "defaultDescription": f"{LNBITS_SITE_TITLE} balance withdraw from {wallet.id[0:5]}",
"balanceCheck": url_for( "balanceCheck": url_for("/withdraw", external=True, usr=user.id, wal=wallet.id),
"core.lnurl_full_withdraw", usr=user.id, wal=wallet.id, _external=True
),
} }
@core_html_routes.get("/withdraw/cb") @core_html_routes.get("/withdraw/cb")
@validate_uuids(["usr", "wal"], required=True) # @validate_uuids(["usr", "wal"], required=True)
async def lnurl_full_withdraw_callback(): async def lnurl_full_withdraw_callback(request: Request):
user = await get_user(request.args.get("usr")) user = await get_user(request.args.get("usr"))
if not user: if not user:
return {"status": "ERROR", "reason": "User does not exist."} return {"status": "ERROR", "reason": "User does not exist."}
@ -166,34 +152,35 @@ async def lnurl_full_withdraw_callback():
@core_html_routes.get("/deletewallet") @core_html_routes.get("/deletewallet")
@validate_uuids(["usr", "wal"], required=True) # @validate_uuids(["usr", "wal"], required=True)
@check_user_exists() # @check_user_exists()
async def deletewallet(): async def deletewallet(request: Request):
wallet_id = request.args.get("wal", type=str) wallet_id = request.path_params.get("wal", type=str)
user_wallet_ids = g.user.wallet_ids user_wallet_ids = g().user.wallet_ids
if wallet_id not in user_wallet_ids: if wallet_id not in user_wallet_ids:
abort(HTTPStatus.FORBIDDEN, "Not your wallet.") abort(HTTPStatus.FORBIDDEN, "Not your wallet.")
else: else:
await delete_wallet(user_id=g.user.id, wallet_id=wallet_id) await delete_wallet(user_id=g().user.id, wallet_id=wallet_id)
user_wallet_ids.remove(wallet_id) user_wallet_ids.remove(wallet_id)
if user_wallet_ids: if user_wallet_ids:
return redirect(url_for("core.wallet", usr=g.user.id, wal=user_wallet_ids[0])) return RedirectResponse(url_for("/wallet", usr=g().user.id, wal=user_wallet_ids[0]),
status_code=status.HTTP_307_TEMPORARY_REDIRECT)
return redirect(url_for("core.home")) return RedirectResponse(url_for("/"), status_code=status.HTTP_307_TEMPORARY_REDIRECT)
@core_html_routes.get("/withdraw/notify/{service}") @core_html_routes.get("/withdraw/notify/{service}")
@validate_uuids(["wal"], required=True) # @validate_uuids(["wal"], required=True)
async def lnurl_balance_notify(service: str): async def lnurl_balance_notify(request: Request, service: str):
bc = await get_balance_check(request.args.get("wal"), service) bc = await get_balance_check(request.args.get("wal"), service)
if bc: if bc:
redeem_lnurl_withdraw(bc.wallet, bc.url) redeem_lnurl_withdraw(bc.wallet, bc.url)
@core_html_routes.get("/lnurlwallet") @core_html_routes.get("/lnurlwallet")
async def lnurlwallet(): async def lnurlwallet(request: Request):
async with db.connect() as conn: async with db.connect() as conn:
account = await create_account(conn=conn) account = await create_account(conn=conn)
user = await get_user(account.id, conn=conn) user = await get_user(account.id, conn=conn)

View file

@ -1,7 +1,6 @@
import trio import trio
import datetime import datetime
from http import HTTPStatus from http import HTTPStatus
from quart import jsonify
from lnbits import bolt11 from lnbits import bolt11

View file

@ -1,5 +1,4 @@
from cerberus import Validator # type: ignore from cerberus import Validator # type: ignore
from quart import g, abort, jsonify, request
from functools import wraps from functools import wraps
from http import HTTPStatus from http import HTTPStatus
from typing import List, Union from typing import List, Union
@ -77,28 +76,4 @@ def check_user_exists(param: str = "usr"):
return wrap return wrap
def validate_uuids(
params: List[str], *, required: Union[bool, List[str]] = False, version: int = 4
):
def wrap(view):
@wraps(view)
async def wrapped_view(**kwargs):
query_params = {
param: request.args.get(param, type=str) for param in params
}
for param, value in query_params.items():
if not value and (required is True or (required and param in required)):
abort(HTTPStatus.BAD_REQUEST, f"`{param}` is required.")
if value:
try:
UUID(value, version=version)
except ValueError:
abort(HTTPStatus.BAD_REQUEST, f"`{param}` is not a valid UUID.")
return await view(**kwargs)
return wrapped_view
return wrap

View file

@ -1,5 +1,4 @@
import hashlib import hashlib
from quart import jsonify, url_for, request
from lnurl import LnurlPayResponse, LnurlPayActionResponse, LnurlErrorResponse # type: ignore from lnurl import LnurlPayResponse, LnurlPayActionResponse, LnurlErrorResponse # type: ignore
from lnbits.core.services import create_invoice from lnbits.core.services import create_invoice

View file

@ -2,7 +2,7 @@ import json
import base64 import base64
import hashlib import hashlib
from collections import OrderedDict from collections import OrderedDict
from quart import url_for
from typing import Optional, List, Dict from typing import Optional, List, Dict
from lnurl import encode as lnurl_encode # type: ignore from lnurl import encode as lnurl_encode # type: ignore
from lnurl.types import LnurlPayMetadata # type: ignore from lnurl.types import LnurlPayMetadata # type: ignore

View file

@ -1,9 +1,8 @@
import time import time
from datetime import datetime from datetime import datetime
from quart import g, render_template, request
from http import HTTPStatus from http import HTTPStatus
from lnbits.decorators import check_user_exists, validate_uuids from lnbits.decorators import check_user_exists
from lnbits.core.models import Payment from lnbits.core.models import Payment
from lnbits.core.crud import get_standalone_payment from lnbits.core.crud import get_standalone_payment
@ -15,8 +14,8 @@ from fastapi.templating import Jinja2Templates
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
@offlineshop_ext.get("/") @offlineshop_ext.get("/")
@validate_uuids(["usr"], required=True) # @validate_uuids(["usr"], required=True)
@check_user_exists() # @check_user_exists()
async def index(request: Request): async def index(request: Request):
return await templates.TemplateResponse("offlineshop/index.html", {"request": request,"user":g.user}) return await templates.TemplateResponse("offlineshop/index.html", {"request": request,"user":g.user})

View file

@ -1,11 +1,12 @@
from typing import Optional from typing import Optional
from pydantic.main import BaseModel from pydantic.main import BaseModel
from quart import g, jsonify
from http import HTTPStatus from http import HTTPStatus
from lnurl.exceptions import InvalidUrl as LnurlInvalidUrl # type: ignore from lnurl.exceptions import InvalidUrl as LnurlInvalidUrl # type: ignore
from lnbits.decorators import api_check_wallet_key, api_validate_post_request from lnbits.decorators import api_check_wallet_key, api_validate_post_request
from lnbits.utils.exchange_rates import currencies from lnbits.utils.exchange_rates import currencies
from lnbits.requestvars import g
from . import offlineshop_ext from . import offlineshop_ext
from .crud import ( from .crud import (
@ -27,7 +28,7 @@ async def api_list_currencies_available():
@offlineshop_ext.get("/api/v1/offlineshop") @offlineshop_ext.get("/api/v1/offlineshop")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_shop_from_wallet(): async def api_shop_from_wallet():
shop = await get_or_create_shop_by_wallet(g.wallet.id) shop = await get_or_create_shop_by_wallet(g().wallet.id)
items = await get_items(shop.id) items = await get_items(shop.id)
try: try:
@ -60,7 +61,7 @@ class CreateItemsData(BaseModel):
@offlineshop_ext.put("/api/v1/offlineshop/items/{item_id}") @offlineshop_ext.put("/api/v1/offlineshop/items/{item_id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_add_or_update_item(data: CreateItemsData, item_id=None): async def api_add_or_update_item(data: CreateItemsData, item_id=None):
shop = await get_or_create_shop_by_wallet(g.wallet.id) shop = await get_or_create_shop_by_wallet(g().wallet.id)
if item_id == None: if item_id == None:
await add_item( await add_item(
shop.id, shop.id,
@ -87,7 +88,7 @@ async def api_add_or_update_item(data: CreateItemsData, item_id=None):
@offlineshop_ext.delete("/api/v1/offlineshop/items/{item_id}") @offlineshop_ext.delete("/api/v1/offlineshop/items/{item_id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_delete_item(item_id): async def api_delete_item(item_id):
shop = await get_or_create_shop_by_wallet(g.wallet.id) shop = await get_or_create_shop_by_wallet(g().wallet.id)
await delete_item_from_shop(shop.id, item_id) await delete_item_from_shop(shop.id, item_id)
return "", HTTPStatus.NO_CONTENT return "", HTTPStatus.NO_CONTENT
@ -104,7 +105,7 @@ async def api_set_method(data: CreateMethodData):
wordlist = data.wordlist.split("\n") if data.wordlist else None wordlist = data.wordlist.split("\n") if data.wordlist else None
wordlist = [word.strip() for word in wordlist if word.strip()] wordlist = [word.strip() for word in wordlist if word.strip()]
shop = await get_or_create_shop_by_wallet(g.wallet.id) shop = await get_or_create_shop_by_wallet(g().wallet.id)
if not shop: if not shop:
return "", HTTPStatus.NOT_FOUND return "", HTTPStatus.NOT_FOUND

View file

@ -1,11 +1,18 @@
import glob
import json import json
import os import os
import glob from typing import Any, List, NamedTuple, Optional
import jinja2
import shortuuid # type: ignore import shortuuid # type: ignore
from typing import List, NamedTuple, Optional from lnbits.jinja2_templating import Jinja2Templates
from lnbits.requestvars import g
from .settings import LNBITS_DISABLED_EXTENSIONS, LNBITS_PATH from .settings import (DEBUG, LNBITS_COMMIT, LNBITS_DISABLED_EXTENSIONS,
LNBITS_PATH, LNBITS_SITE_DESCRIPTION,
LNBITS_SITE_TAGLINE, LNBITS_SITE_TITLE,
LNBITS_THEME_OPTIONS)
class Extension(NamedTuple): class Extension(NamedTuple):
@ -132,3 +139,35 @@ def get_vendored(ext: str, prefer_minified: bool = False) -> List[str]:
def url_for_vendored(abspath: str) -> str: def url_for_vendored(abspath: str) -> str:
return "/" + os.path.relpath(abspath, LNBITS_PATH) return "/" + os.path.relpath(abspath, LNBITS_PATH)
def url_for(
endpoint: str,
external: Optional[bool] = False,
**params: Any,
) -> str:
base = g().base_url if external else ""
url_params = "?"
for key in params:
url_params += f"{key}={params[key]}&"
url = f"{base}{endpoint}{url_params}"
return url
def template_renderer() -> Jinja2Templates:
t = Jinja2Templates(
loader=jinja2.FileSystemLoader(["lnbits/templates", "lnbits/core/templates"]),
)
t.env.globals["SITE_TITLE"] = LNBITS_SITE_TITLE
t.env.globals["SITE_TAGLINE"] = LNBITS_SITE_TAGLINE
t.env.globals["SITE_DESCRIPTION"] = LNBITS_SITE_DESCRIPTION
t.env.globals["LNBITS_THEME_OPTIONS"] = LNBITS_THEME_OPTIONS
t.env.globals["LNBITS_VERSION"] = LNBITS_COMMIT
t.env.globals["EXTENSIONS"] = get_valid_extensions()
if DEBUG:
t.env.globals["VENDORED_JS"] = map(url_for_vendored, get_js_vendored())
t.env.globals["VENDORED_CSS"] = map(url_for_vendored, get_css_vendored())
else:
t.env.globals["VENDORED_JS"] = ["/static/bundle.js"]
t.env.globals["VENDORED_CSS"] = ["/static/bundle.css"]
return t

View file

@ -2,7 +2,6 @@ import time
import trio import trio
import traceback import traceback
from http import HTTPStatus from http import HTTPStatus
from quart import current_app
from typing import List, Callable from typing import List, Callable
from lnbits.settings import WALLET from lnbits.settings import WALLET

View file

@ -4,7 +4,6 @@ import httpx
from os import getenv from os import getenv
from http import HTTPStatus from http import HTTPStatus
from typing import Optional, Dict, AsyncGenerator from typing import Optional, Dict, AsyncGenerator
from quart import request
from .base import ( from .base import (
StatusResponse, StatusResponse,

View file

@ -1,10 +1,10 @@
from lnbits.helpers import url_for
import trio import trio
import hmac import hmac
import httpx import httpx
from http import HTTPStatus from http import HTTPStatus
from os import getenv from os import getenv
from typing import Optional, AsyncGenerator from typing import Optional, AsyncGenerator
from quart import request, url_for
from .base import ( from .base import (
StatusResponse, StatusResponse,
@ -63,7 +63,7 @@ class OpenNodeWallet(Wallet):
json={ json={
"amount": amount, "amount": amount,
"description": memo or "", "description": memo or "",
"callback_url": url_for("webhook_listener", _external=True), "callback_url": url_for("/webhook_listener", _external=True),
}, },
timeout=40, timeout=40,
) )