From c762c9c549f693eced8165cb8f9e54a4f440ea55 Mon Sep 17 00:00:00 2001 From: Nat Noordanus Date: Sun, 12 Apr 2020 19:33:23 +0200 Subject: [PATCH 01/16] Add test for generated service stub - Create one simple test for generated Service stubs in preparation for making more changes in this area. - Add dev dependency on pytest-asyncio in order to use ChannelFor from grpclib.testing more easily. - Create a new example proto containing a minimal rpc example. --- Pipfile | 1 + Pipfile.lock | 464 +++++++++++++++++++++++++ betterproto/tests/service.proto | 15 + betterproto/tests/test_service_stub.py | 35 ++ 4 files changed, 515 insertions(+) create mode 100644 Pipfile.lock create mode 100644 betterproto/tests/service.proto create mode 100644 betterproto/tests/test_service_stub.py diff --git a/Pipfile b/Pipfile index 964b0f9..11ba0f9 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,7 @@ flake8 = "*" mypy = "*" isort = "*" pytest = "*" +pytest-asyncio = "*" rope = "*" v = {editable = true,version = "*"} diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..f3ee3ba --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,464 @@ +{ + "_meta": { + "hash": { + "sha256": "b8fc738d4e14598e36269ce0d849489f95562ba047e5663caca9ac02550893ef" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.6" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "appdirs": { + "hashes": [ + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" + ], + "version": "==1.4.3" + }, + "attrs": { + "hashes": [ + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" + ], + "version": "==19.3.0" + }, + "backports-datetime-fromisoformat": { + "hashes": [ + "sha256:9577a2a9486cd7383a5f58b23bb8e81cf0821dbbc0eb7c87d3fa198c1df40f5c" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "black": { + "hashes": [ + "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b", + "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539" + ], + "index": "pypi", + "version": "==19.10b0" + }, + "click": { + "hashes": [ + "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", + "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + ], + "version": "==7.1.1" + }, + "dataclasses": { + "hashes": [ + "sha256:454a69d788c7fda44efd71e259be79577822f5e3f53f029a22d08004e951dc9f", + "sha256:6988bd2b895eef432d562370bb707d540f32f7360ab13da45340101bc2307d84" + ], + "index": "pypi", + "version": "==0.6" + }, + "grpclib": { + "hashes": [ + "sha256:b27d56c987b89023d5640fe9668943e49b46703fc85d8182a58c9f3b19120cdc" + ], + "index": "pypi", + "version": "==0.3.2rc1" + }, + "h2": { + "hashes": [ + "sha256:61e0f6601fa709f35cdb730863b4e5ec7ad449792add80d1410d4174ed139af5", + "sha256:875f41ebd6f2c44781259005b157faed1a5031df3ae5aa7bcb4628a6c0782f14" + ], + "version": "==3.2.0" + }, + "hpack": { + "hashes": [ + "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89", + "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2" + ], + "version": "==3.0.0" + }, + "hyperframe": { + "hashes": [ + "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40", + "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f" + ], + "version": "==5.2.0" + }, + "jinja2": { + "hashes": [ + "sha256:c10142f819c2d22bdcd17548c46fa9b77cf4fda45097854c689666bf425e7484", + "sha256:c922560ac46888d47384de1dbdc3daaa2ea993af4b26a436dec31fa2c19ec668" + ], + "index": "pypi", + "version": "==3.0.0a1" + }, + "markupsafe": { + "hashes": [ + "sha256:06358015a4dee8ee23ae426bf885616ab3963622defd829eb45b44e3dee3515f", + "sha256:0b0c4fc852c5f02c6277ef3b33d23fcbe89b1b227460423e3335374da046b6db", + "sha256:267677fc42afed5094fc5ea1c4236bbe4b6a00fe4b08e93451e65ae9048139c7", + "sha256:303cb70893e2c345588fb5d5b86e0ca369f9bb56942f03064c5e3e75fa7a238a", + "sha256:3c9b624a0d9ed5a5093ac4edc4e823e6b125441e60ef35d36e6f4a6fdacd5054", + "sha256:42033e14cae1f6c86fc0c3e90d04d08ce73ac8e46ba420a0d22d545c2abd4977", + "sha256:4e4a99b6af7bdc0856b50020c095848ec050356a001e1f751510aef6ab14d0e0", + "sha256:4eb07faad54bb07427d848f31030a65a49ebb0cec0b30674f91cf1ddd456bfe4", + "sha256:63a7161cd8c2bc563feeda45df62f42c860dd0675e2b8da2667f25bb3c95eaba", + "sha256:68e0fd039b68d2945b4beb947d4023ca7f8e95b708031c345762efba214ea761", + "sha256:8092a63397025c2f655acd42784b2a1528339b90b987beb9253f22e8cdbb36c3", + "sha256:841218860683c0f2223e24756843d84cc49cccdae6765e04962607754a52d3e0", + "sha256:94076b2314bd2f6cfae508ad65b4d493e3a58a50112b7a2cbb6287bdbc404ae8", + "sha256:9d22aff1c5322e402adfb3ce40839a5056c353e711c033798cf4f02eb9f5124d", + "sha256:b0e4584f62b3e5f5c1a7bcefd2b52f236505e6ef032cc508caa4f4c8dc8d3af1", + "sha256:b1163ffc1384d242964426a8164da12dbcdbc0de18ea36e2c34b898ed38c3b45", + "sha256:beac28ed60c8e838301226a7a85841d0af2068eba2dcb1a58c2d32d6c05e440e", + "sha256:c29f096ce79c03054a1101d6e5fe6bf04b0bb489165d5e0e9653fb4fe8048ee1", + "sha256:c58779966d53e5f14ba393d64e2402a7926601d1ac8adeb4e83893def79d0428", + "sha256:cfe14b37908eaf7d5506302987228bff69e1b8e7071ccd4e70fd0283b1b47f0b", + "sha256:e834249c45aa9837d0753351cdca61a4b8b383cc9ad0ff2325c97ff7b69e72a6", + "sha256:eed1b234c4499811ee85bcefa22ef5e466e75d132502226ed29740d593316c1f" + ], + "version": "==2.0.0a1" + }, + "multidict": { + "hashes": [ + "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1", + "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35", + "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928", + "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969", + "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e", + "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78", + "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1", + "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136", + "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8", + "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2", + "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e", + "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4", + "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5", + "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd", + "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab", + "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20", + "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3" + ], + "version": "==4.7.5" + }, + "pathspec": { + "hashes": [ + "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0", + "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061" + ], + "version": "==0.8.0" + }, + "protobuf": { + "hashes": [ + "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab", + "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f", + "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a", + "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0", + "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4", + "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2", + "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee", + "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07", + "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151", + "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a", + "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f", + "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7", + "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956", + "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306", + "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961", + "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481", + "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a", + "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80" + ], + "index": "pypi", + "version": "==3.11.3" + }, + "regex": { + "hashes": [ + "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b", + "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8", + "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3", + "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e", + "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683", + "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1", + "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142", + "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3", + "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468", + "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e", + "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3", + "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a", + "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f", + "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6", + "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156", + "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b", + "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db", + "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd", + "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a", + "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948", + "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89" + ], + "version": "==2020.4.4" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "stringcase": { + "hashes": [ + "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008" + ], + "index": "pypi", + "version": "==1.2.0" + }, + "toml": { + "hashes": [ + "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", + "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" + ], + "version": "==0.10.0" + }, + "typed-ast": { + "hashes": [ + "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", + "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", + "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", + "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", + "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", + "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", + "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", + "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", + "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", + "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", + "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", + "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", + "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", + "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", + "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", + "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", + "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", + "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", + "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", + "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", + "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" + ], + "version": "==1.4.1" + } + }, + "develop": { + "attrs": { + "hashes": [ + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" + ], + "version": "==19.3.0" + }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" + }, + "flake8": { + "hashes": [ + "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", + "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" + ], + "index": "pypi", + "version": "==3.7.9" + }, + "importlib-metadata": { + "hashes": [ + "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", + "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" + ], + "markers": "python_version < '3.8'", + "version": "==1.6.0" + }, + "isort": { + "hashes": [ + "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", + "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" + ], + "index": "pypi", + "version": "==4.3.21" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", + "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" + ], + "version": "==8.2.0" + }, + "mypy": { + "hashes": [ + "sha256:15b948e1302682e3682f11f50208b726a246ab4e6c1b39f9264a8796bb416aa2", + "sha256:219a3116ecd015f8dca7b5d2c366c973509dfb9a8fc97ef044a36e3da66144a1", + "sha256:3b1fc683fb204c6b4403a1ef23f0b1fac8e4477091585e0c8c54cbdf7d7bb164", + "sha256:3beff56b453b6ef94ecb2996bea101a08f1f8a9771d3cbf4988a61e4d9973761", + "sha256:7687f6455ec3ed7649d1ae574136835a4272b65b3ddcf01ab8704ac65616c5ce", + "sha256:7ec45a70d40ede1ec7ad7f95b3c94c9cf4c186a32f6bacb1795b60abd2f9ef27", + "sha256:86c857510a9b7c3104cf4cde1568f4921762c8f9842e987bc03ed4f160925754", + "sha256:8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae", + "sha256:8dfb69fbf9f3aeed18afffb15e319ca7f8da9642336348ddd6cab2713ddcf8f9", + "sha256:a34b577cdf6313bf24755f7a0e3f3c326d5c1f4fe7422d1d06498eb25ad0c600", + "sha256:a8ffcd53cb5dfc131850851cc09f1c44689c2812d0beb954d8138d4f5fc17f65", + "sha256:b90928f2d9eb2f33162405f32dde9f6dcead63a0971ca8a1b50eb4ca3e35ceb8", + "sha256:c56ffe22faa2e51054c5f7a3bc70a370939c2ed4de308c690e7949230c995913", + "sha256:f91c7ae919bbc3f96cd5e5b2e786b2b108343d1d7972ea130f7de27fdd547cf3" + ], + "index": "pypi", + "version": "==0.770" + }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" + }, + "packaging": { + "hashes": [ + "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3", + "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752" + ], + "version": "==20.3" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "version": "==0.13.1" + }, + "py": { + "hashes": [ + "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", + "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" + ], + "version": "==1.8.1" + }, + "pycodestyle": { + "hashes": [ + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + ], + "version": "==2.5.0" + }, + "pyflakes": { + "hashes": [ + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + ], + "version": "==2.1.1" + }, + "pyparsing": { + "hashes": [ + "sha256:67199f0c41a9c702154efb0e7a8cc08accf830eb003b4d9fa42c4059002e2492", + "sha256:700d17888d441604b0bd51535908dcb297561b040819cccde647a92439db5a2a" + ], + "version": "==3.0.0a1" + }, + "pytest": { + "hashes": [ + "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172", + "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970" + ], + "index": "pypi", + "version": "==5.4.1" + }, + "pytest-asyncio": { + "hashes": [ + "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", + "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b" + ], + "index": "pypi", + "version": "==0.10.0" + }, + "rope": { + "hashes": [ + "sha256:52423a7eebb5306a6d63bdc91a7c657db51ac9babfb8341c9a1440831ecf3203", + "sha256:ae1fa2fd56f64f4cc9be46493ce54bed0dd12dee03980c61a4393d89d84029ad", + "sha256:d2830142c2e046f5fc26a022fe680675b6f48f81c7fc1f03a950706e746e9dfe" + ], + "index": "pypi", + "version": "==0.16.0" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "typed-ast": { + "hashes": [ + "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", + "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", + "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", + "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", + "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", + "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", + "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", + "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", + "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", + "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", + "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", + "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", + "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", + "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", + "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", + "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", + "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", + "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", + "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", + "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", + "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" + ], + "version": "==1.4.1" + }, + "typing-extensions": { + "hashes": [ + "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5", + "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae", + "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392" + ], + "version": "==3.7.4.2" + }, + "v": { + "hashes": [ + "sha256:2d5a8f79a36aaebe62ef2c7068e3ec7f86656078202edabfdbf74715dc822d36", + "sha256:cd6b6b20b4a611f209c88bcdfb7211321f85662efb2bdd53a7b40314d0a84618" + ], + "index": "pypi", + "version": "==0.0.0" + }, + "wcwidth": { + "hashes": [ + "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1", + "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" + ], + "version": "==0.1.9" + }, + "zipp": { + "hashes": [ + "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", + "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" + ], + "version": "==3.1.0" + } + } +} diff --git a/betterproto/tests/service.proto b/betterproto/tests/service.proto new file mode 100644 index 0000000..aaf4254 --- /dev/null +++ b/betterproto/tests/service.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package service; + +message DoThingRequest { + int32 iterations = 1; +} + +message DoThingResponse { + int32 successfulIterations = 1; +} + +service ExampleService { + rpc DoThing (DoThingRequest) returns (DoThingResponse); +} diff --git a/betterproto/tests/test_service_stub.py b/betterproto/tests/test_service_stub.py new file mode 100644 index 0000000..84de7b6 --- /dev/null +++ b/betterproto/tests/test_service_stub.py @@ -0,0 +1,35 @@ +import betterproto +import grpclib +from grpclib.testing import ChannelFor +import pytest +from typing import Dict +from .service import DoThingResponse, DoThingRequest, ExampleServiceStub + + +class ExampleService: + + async def DoThing(self, stream: 'grpclib.server.Stream[DoThingRequest, DoThingResponse]'): + request = await stream.recv_message() + for iteration in range(request.iterations): + pass + await stream.send_message(DoThingResponse(request.iterations)) + + + def __mapping__(self) -> Dict[str, grpclib.const.Handler]: + return { + '/service.ExampleService/DoThing': grpclib.const.Handler( + self.DoThing, + grpclib.const.Cardinality.UNARY_UNARY, + DoThingRequest, + DoThingResponse, + ), + } + + +@pytest.mark.asyncio +async def test_simple_service_call(): + ITERATIONS = 42 + async with ChannelFor([ExampleService()]) as channel: + stub = ExampleServiceStub(channel) + response = await stub.do_thing(iterations=ITERATIONS) + assert response.successful_iterations == ITERATIONS From 5759e323bd4827040fce267be1564689ce9ae9ec Mon Sep 17 00:00:00 2001 From: Nat Noordanus Date: Sun, 12 Apr 2020 22:23:10 +0200 Subject: [PATCH 02/16] Add ability to provide metadata, timeout & deadline args to requests This is an enhancement of the ServiceStub abstract class that makes it more useful by making it possible to pass all arguments supported by the underlying grpclib request function. It extends to the existing high level API by allowing values to be set on the stub instance, and the low level API by allowing values to be set per call. --- betterproto/__init__.py | 60 +++++++++++++-- betterproto/tests/test_service_stub.py | 100 +++++++++++++++++++++++-- 2 files changed, 149 insertions(+), 11 deletions(-) diff --git a/betterproto/__init__.py b/betterproto/__init__.py index f082fa6..dc2566c 100644 --- a/betterproto/__init__.py +++ b/betterproto/__init__.py @@ -11,10 +11,12 @@ from typing import ( Any, AsyncGenerator, Callable, + Collection, Dict, Generator, Iterable, List, + Mapping, Optional, SupportsBytes, Tuple, @@ -1000,20 +1002,57 @@ def _get_wrapper(proto_type: str) -> Type: }[proto_type] +_Value = Union[str, bytes] +_MetadataLike = Union[Mapping[str, _Value], Collection[Tuple[str, _Value]]] + + class ServiceStub(ABC): """ Base class for async gRPC service stubs. """ - def __init__(self, channel: grpclib.client.Channel) -> None: + def __init__( + self, + channel: grpclib.client.Channel, + *, + timeout: Optional[float] = None, + deadline: Optional[grpclib.metadata.Deadline] = None, + metadata: Optional[_MetadataLike] = None, + ) -> None: self.channel = channel + self.timeout = timeout + self.deadline = deadline + self.metadata = metadata + + def __resolve_request_kwargs( + self, + timeout: Optional[float], + deadline: Optional[grpclib.metadata.Deadline], + metadata: Optional[_MetadataLike], + ): + return { + "timeout": self.timeout if timeout is None else timeout, + "deadline": self.deadline if deadline is None else deadline, + "metadata": self.metadata if metadata is None else metadata, + } async def _unary_unary( - self, route: str, request: "IProtoMessage", response_type: Type[T] + self, + route: str, + request: "IProtoMessage", + response_type: Type[T], + *, + timeout: Optional[float] = None, + deadline: Optional[grpclib.metadata.Deadline] = None, + metadata: Optional[_MetadataLike] = None, ) -> T: """Make a unary request and return the response.""" async with self.channel.request( - route, grpclib.const.Cardinality.UNARY_UNARY, type(request), response_type + route, + grpclib.const.Cardinality.UNARY_UNARY, + type(request), + response_type, + **self.__resolve_request_kwargs(timeout, deadline, metadata), ) as stream: await stream.send_message(request, end=True) response = await stream.recv_message() @@ -1021,11 +1060,22 @@ class ServiceStub(ABC): return response async def _unary_stream( - self, route: str, request: "IProtoMessage", response_type: Type[T] + self, + route: str, + request: "IProtoMessage", + response_type: Type[T], + *, + timeout: Optional[float] = None, + deadline: Optional[grpclib.metadata.Deadline] = None, + metadata: Optional[_MetadataLike] = None, ) -> AsyncGenerator[T, None]: """Make a unary request and return the stream response iterator.""" async with self.channel.request( - route, grpclib.const.Cardinality.UNARY_STREAM, type(request), response_type + route, + grpclib.const.Cardinality.UNARY_STREAM, + type(request), + response_type, + **self.__resolve_request_kwargs(timeout, deadline, metadata), ) as stream: await stream.send_message(request, end=True) async for message in stream: diff --git a/betterproto/tests/test_service_stub.py b/betterproto/tests/test_service_stub.py index 84de7b6..a5ba200 100644 --- a/betterproto/tests/test_service_stub.py +++ b/betterproto/tests/test_service_stub.py @@ -7,17 +7,24 @@ from .service import DoThingResponse, DoThingRequest, ExampleServiceStub class ExampleService: + def __init__(self, test_hook=None): + # This lets us pass assertions to the servicer ;) + self.test_hook = test_hook - async def DoThing(self, stream: 'grpclib.server.Stream[DoThingRequest, DoThingResponse]'): + async def DoThing( + self, stream: "grpclib.server.Stream[DoThingRequest, DoThingResponse]" + ): request = await stream.recv_message() + print("self.test_hook", self.test_hook) + if self.test_hook is not None: + self.test_hook(stream) for iteration in range(request.iterations): pass await stream.send_message(DoThingResponse(request.iterations)) - def __mapping__(self) -> Dict[str, grpclib.const.Handler]: return { - '/service.ExampleService/DoThing': grpclib.const.Handler( + "/service.ExampleService/DoThing": grpclib.const.Handler( self.DoThing, grpclib.const.Cardinality.UNARY_UNARY, DoThingRequest, @@ -26,10 +33,91 @@ class ExampleService: } +async def _test_stub(stub, iterations=42, **kwargs): + response = await stub.do_thing(iterations=iterations) + assert response.successful_iterations == iterations + + +def _get_server_side_test(deadline, metadata): + def server_side_test(stream): + assert stream.deadline._timestamp == pytest.approx( + deadline._timestamp, 1 + ), "The provided deadline should be recieved serverside" + assert ( + stream.metadata["authorization"] == metadata["authorization"] + ), "The provided authorization metadata should be recieved serverside" + + return server_side_test + + @pytest.mark.asyncio async def test_simple_service_call(): - ITERATIONS = 42 async with ChannelFor([ExampleService()]) as channel: - stub = ExampleServiceStub(channel) - response = await stub.do_thing(iterations=ITERATIONS) + await _test_stub(ExampleServiceStub(channel)) + + +@pytest.mark.asyncio +async def test_service_call_with_upfront_request_params(): + # Setting deadline + deadline = grpclib.metadata.Deadline.from_timeout(22) + metadata = {"authorization": "12345"} + async with ChannelFor( + [ExampleService(test_hook=_get_server_side_test(deadline, metadata))] + ) as channel: + await _test_stub( + ExampleServiceStub(channel, deadline=deadline, metadata=metadata) + ) + + # Setting timeout + timeout = 99 + deadline = grpclib.metadata.Deadline.from_timeout(timeout) + metadata = {"authorization": "12345"} + async with ChannelFor( + [ExampleService(test_hook=_get_server_side_test(deadline, metadata))] + ) as channel: + await _test_stub( + ExampleServiceStub(channel, timeout=timeout, metadata=metadata) + ) + + +@pytest.mark.asyncio +async def test_service_call_lower_level_with_overrides(): + ITERATIONS = 99 + + # Setting deadline + deadline = grpclib.metadata.Deadline.from_timeout(22) + metadata = {"authorization": "12345"} + kwarg_deadline = grpclib.metadata.Deadline.from_timeout(28) + kwarg_metadata = {"authorization": "12345"} + async with ChannelFor( + [ExampleService(test_hook=_get_server_side_test(deadline, metadata))] + ) as channel: + stub = ExampleServiceStub(channel, deadline=deadline, metadata=metadata) + response = await stub._unary_unary( + "/service.ExampleService/DoThing", DoThingRequest(ITERATIONS), DoThingResponse, + deadline=kwarg_deadline, + metadata=kwarg_metadata, + ) + assert response.successful_iterations == ITERATIONS + + # Setting timeout + timeout = 99 + deadline = grpclib.metadata.Deadline.from_timeout(timeout) + metadata = {"authorization": "12345"} + kwarg_timeout = 9000 + kwarg_deadline = grpclib.metadata.Deadline.from_timeout(kwarg_timeout) + kwarg_metadata = {"authorization": "09876"} + async with ChannelFor( + [ + ExampleService( + test_hook=_get_server_side_test(kwarg_deadline, kwarg_metadata) + ) + ] + ) as channel: + stub = ExampleServiceStub(channel, deadline=deadline, metadata=metadata) + response = await stub._unary_unary( + "/service.ExampleService/DoThing", DoThingRequest(ITERATIONS), DoThingResponse, + timeout=kwarg_timeout, + metadata=kwarg_metadata, + ) assert response.successful_iterations == ITERATIONS From b12f1e4e6179766398af0433614002dd0d81bbfc Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 12:54:01 +0200 Subject: [PATCH 03/16] Organize test-cases into folders, extract compatibility test into proper test, support adding test-case specific tests --- Pipfile | 2 + Pipfile.lock | 284 +++++++++++------- betterproto/plugin.bat | 2 + betterproto/tests/generate.py | 84 ------ betterproto/tests/{ => inputs/bool}/bool.json | 0 .../tests/{ => inputs/bool}/bool.proto | 0 betterproto/tests/inputs/bool/test.py | 8 + .../tests/{ => inputs/bytes}/bytes.json | 0 .../tests/{ => inputs/bytes}/bytes.proto | 0 .../tests/{ => inputs/casing}/casing.json | 0 .../tests/{ => inputs/casing}/casing.proto | 5 + .../{ => inputs/double}/double-negative.json | 0 .../tests/{ => inputs/double}/double.json | 0 .../tests/{ => inputs/double}/double.proto | 0 .../tests/{ => inputs/enums}/enums.json | 0 .../tests/{ => inputs/enums}/enums.proto | 0 .../googletypes}/googletypes-missing.json | 0 .../{ => inputs/googletypes}/googletypes.json | 0 .../googletypes}/googletypes.proto | 0 .../googletypes_response.proto | 18 ++ .../test_googletypes_response.py | 18 ++ .../{ => inputs/int32}/int32-negative.json | 0 .../tests/{ => inputs/int32}/int32.json | 0 .../tests/{ => inputs/int32}/int32.proto | 0 .../tests/{ => inputs/keywords}/keywords.json | 0 .../{ => inputs/keywords}/keywords.proto | 0 betterproto/tests/{ => inputs/map}/map.json | 0 betterproto/tests/{ => inputs/map}/map.proto | 0 .../{ => inputs/mapmessage}/mapmessage.json | 0 .../{ => inputs/mapmessage}/mapmessage.proto | 0 .../tests/{ => inputs/nested}/nested.json | 0 .../tests/{ => inputs/nested}/nested.proto | 0 .../{ => inputs/nestedtwice}/nestedtwice.json | 0 .../nestedtwice}/nestedtwice.proto | 0 .../tests/{ => inputs/oneof}/oneof-name.json | 0 .../tests/{ => inputs/oneof}/oneof.json | 0 .../tests/{ => inputs/oneof}/oneof.proto | 0 betterproto/tests/{ => inputs/ref}/ref.json | 0 betterproto/tests/{ => inputs/ref}/ref.proto | 0 .../{ => inputs/ref}/repeatedmessage.proto | 0 .../tests/{ => inputs/repeated}/repeated.json | 0 .../{ => inputs/repeated}/repeated.proto | 0 .../repeatedmessage}/repeatedmessage.json | 0 .../repeatedmessage/repeatedmessage.proto | 11 + .../repeatedpacked}/repeatedpacked.json | 0 .../repeatedpacked}/repeatedpacked.proto | 0 .../tests/{ => inputs/service}/service.proto | 0 .../{ => inputs/signed}/signed-negative.json | 0 .../tests/{ => inputs/signed}/signed.json | 0 .../tests/{ => inputs/signed}/signed.proto | 0 betterproto/tests/test_inputs.py | 111 +++++-- betterproto/tests/test_service_stub.py | 2 +- pytest.ini | 5 + 53 files changed, 332 insertions(+), 218 deletions(-) create mode 100644 betterproto/plugin.bat delete mode 100644 betterproto/tests/generate.py rename betterproto/tests/{ => inputs/bool}/bool.json (100%) rename betterproto/tests/{ => inputs/bool}/bool.proto (100%) create mode 100644 betterproto/tests/inputs/bool/test.py rename betterproto/tests/{ => inputs/bytes}/bytes.json (100%) rename betterproto/tests/{ => inputs/bytes}/bytes.proto (100%) rename betterproto/tests/{ => inputs/casing}/casing.json (100%) rename betterproto/tests/{ => inputs/casing}/casing.proto (64%) rename betterproto/tests/{ => inputs/double}/double-negative.json (100%) rename betterproto/tests/{ => inputs/double}/double.json (100%) rename betterproto/tests/{ => inputs/double}/double.proto (100%) rename betterproto/tests/{ => inputs/enums}/enums.json (100%) rename betterproto/tests/{ => inputs/enums}/enums.proto (100%) rename betterproto/tests/{ => inputs/googletypes}/googletypes-missing.json (100%) rename betterproto/tests/{ => inputs/googletypes}/googletypes.json (100%) rename betterproto/tests/{ => inputs/googletypes}/googletypes.proto (100%) create mode 100644 betterproto/tests/inputs/googletypes_response/googletypes_response.proto create mode 100644 betterproto/tests/inputs/googletypes_response/test_googletypes_response.py rename betterproto/tests/{ => inputs/int32}/int32-negative.json (100%) rename betterproto/tests/{ => inputs/int32}/int32.json (100%) rename betterproto/tests/{ => inputs/int32}/int32.proto (100%) rename betterproto/tests/{ => inputs/keywords}/keywords.json (100%) rename betterproto/tests/{ => inputs/keywords}/keywords.proto (100%) rename betterproto/tests/{ => inputs/map}/map.json (100%) rename betterproto/tests/{ => inputs/map}/map.proto (100%) rename betterproto/tests/{ => inputs/mapmessage}/mapmessage.json (100%) rename betterproto/tests/{ => inputs/mapmessage}/mapmessage.proto (100%) rename betterproto/tests/{ => inputs/nested}/nested.json (100%) rename betterproto/tests/{ => inputs/nested}/nested.proto (100%) rename betterproto/tests/{ => inputs/nestedtwice}/nestedtwice.json (100%) rename betterproto/tests/{ => inputs/nestedtwice}/nestedtwice.proto (100%) rename betterproto/tests/{ => inputs/oneof}/oneof-name.json (100%) rename betterproto/tests/{ => inputs/oneof}/oneof.json (100%) rename betterproto/tests/{ => inputs/oneof}/oneof.proto (100%) rename betterproto/tests/{ => inputs/ref}/ref.json (100%) rename betterproto/tests/{ => inputs/ref}/ref.proto (100%) rename betterproto/tests/{ => inputs/ref}/repeatedmessage.proto (100%) rename betterproto/tests/{ => inputs/repeated}/repeated.json (100%) rename betterproto/tests/{ => inputs/repeated}/repeated.proto (100%) rename betterproto/tests/{ => inputs/repeatedmessage}/repeatedmessage.json (100%) create mode 100644 betterproto/tests/inputs/repeatedmessage/repeatedmessage.proto rename betterproto/tests/{ => inputs/repeatedpacked}/repeatedpacked.json (100%) rename betterproto/tests/{ => inputs/repeatedpacked}/repeatedpacked.proto (100%) rename betterproto/tests/{ => inputs/service}/service.proto (100%) rename betterproto/tests/{ => inputs/signed}/signed-negative.json (100%) rename betterproto/tests/{ => inputs/signed}/signed.json (100%) rename betterproto/tests/{ => inputs/signed}/signed.proto (100%) create mode 100644 pytest.ini diff --git a/Pipfile b/Pipfile index 11ba0f9..18ed9c4 100644 --- a/Pipfile +++ b/Pipfile @@ -20,6 +20,8 @@ stringcase = "*" black = "*" backports-datetime-fromisoformat = "*" dataclasses = "*" +betterproto = {editable = true,path = "."} +pytest-asyncio = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index f3ee3ba..5021cbe 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b8fc738d4e14598e36269ce0d849489f95562ba047e5663caca9ac02550893ef" + "sha256": "9d2ee95f2c962097d22375cb461ceaefc40467919d53d80f7ed2541794d8fd6b" }, "pipfile-spec": 6, "requires": { @@ -18,10 +18,10 @@ "default": { "appdirs": { "hashes": [ - "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", - "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" + "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", + "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" ], - "version": "==1.4.3" + "version": "==1.4.4" }, "attrs": { "hashes": [ @@ -37,6 +37,10 @@ "index": "pypi", "version": "==1.0.0" }, + "betterproto": { + "editable": true, + "path": "." + }, "black": { "hashes": [ "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b", @@ -47,18 +51,18 @@ }, "click": { "hashes": [ - "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", - "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], - "version": "==7.1.1" + "version": "==7.1.2" }, "dataclasses": { "hashes": [ - "sha256:454a69d788c7fda44efd71e259be79577822f5e3f53f029a22d08004e951dc9f", - "sha256:6988bd2b895eef432d562370bb707d540f32f7360ab13da45340101bc2307d84" + "sha256:3459118f7ede7c8bea0fe795bff7c6c2ce287d01dd226202f7c9ebc0610a7836", + "sha256:494a6dcae3b8bcf80848eea2ef64c0cc5cd307ffc263e17cdf42f3e5420808e6" ], "index": "pypi", - "version": "==0.6" + "version": "==0.7" }, "grpclib": { "hashes": [ @@ -88,6 +92,14 @@ ], "version": "==5.2.0" }, + "importlib-metadata": { + "hashes": [ + "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", + "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" + ], + "markers": "python_version < '3.8'", + "version": "==1.6.0" + }, "jinja2": { "hashes": [ "sha256:c10142f819c2d22bdcd17548c46fa9b77cf4fda45097854c689666bf425e7484", @@ -123,27 +135,41 @@ ], "version": "==2.0.0a1" }, + "more-itertools": { + "hashes": [ + "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be", + "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982" + ], + "version": "==8.3.0" + }, "multidict": { "hashes": [ - "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1", - "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35", - "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928", - "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969", - "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e", - "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78", - "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1", - "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136", - "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8", - "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2", - "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e", - "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4", - "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5", - "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd", - "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab", - "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20", - "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3" + "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a", + "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000", + "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2", + "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507", + "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5", + "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7", + "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d", + "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463", + "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19", + "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3", + "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b", + "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c", + "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87", + "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7", + "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430", + "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255", + "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d" ], - "version": "==4.7.5" + "version": "==4.7.6" + }, + "packaging": { + "hashes": [ + "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", + "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + ], + "version": "==20.4" }, "pathspec": { "hashes": [ @@ -152,62 +178,95 @@ ], "version": "==0.8.0" }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "version": "==0.13.1" + }, "protobuf": { "hashes": [ - "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab", - "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f", - "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a", - "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0", - "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4", - "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2", - "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee", - "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07", - "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151", - "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a", - "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f", - "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7", - "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956", - "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306", - "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961", - "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481", - "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a", - "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80" + "sha256:04d0b2bd99050d09393875a5a25fd12337b17f3ac2e29c0c1b8e65b277cbfe72", + "sha256:05288e44638e91498f13127a3699a6528dec6f9d3084d60959d721bfb9ea5b98", + "sha256:175d85370947f89e33b3da93f4ccdda3f326bebe3e599df5915ceb7f804cd9df", + "sha256:440a8c77531b3652f24999b249256ed01fd44c498ab0973843066681bd276685", + "sha256:49fb6fab19cd3f30fa0e976eeedcbf2558e9061e5fa65b4fe51ded1f4002e04d", + "sha256:4c7cae1f56056a4a2a2e3b00b26ab8550eae738bd9548f4ea0c2fcb88ed76ae5", + "sha256:519abfacbb421c3591d26e8daf7a4957763428db7267f7207e3693e29f6978db", + "sha256:60f32af25620abc4d7928d8197f9f25d49d558c5959aa1e08c686f974ac0b71a", + "sha256:613ac49f6db266fba243daf60fb32af107cfe3678e5c003bb40a381b6786389d", + "sha256:954bb14816edd24e746ba1a6b2d48c43576393bbde2fb8e1e3bd6d4504c7feac", + "sha256:9b1462c033a2cee7f4e8eb396905c69de2c532c3b835ff8f71f8e5fb77c38023", + "sha256:c0767f4d93ce4288475afe0571663c78870924f1f8881efd5406c10f070c75e4", + "sha256:c45f5980ce32879391144b5766120fd7b8803129f127ce36bd060dd38824801f", + "sha256:eeb7502f59e889a88bcb59f299493e215d1864f3d75335ea04a413004eb4fe24", + "sha256:fdb1742f883ee4662e39fcc5916f2725fec36a5191a52123fec60f8c53b70495", + "sha256:fe554066c4962c2db0a1d4752655223eb948d2bfa0fb1c4a7f2c00ec07324f1c" ], "index": "pypi", - "version": "==3.11.3" + "version": "==3.12.1" + }, + "py": { + "hashes": [ + "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", + "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" + ], + "version": "==1.8.1" + }, + "pyparsing": { + "hashes": [ + "sha256:67199f0c41a9c702154efb0e7a8cc08accf830eb003b4d9fa42c4059002e2492", + "sha256:700d17888d441604b0bd51535908dcb297561b040819cccde647a92439db5a2a" + ], + "version": "==3.0.0a1" + }, + "pytest": { + "hashes": [ + "sha256:95c710d0a72d91c13fae35dce195633c929c3792f54125919847fdcdf7caa0d3", + "sha256:eb2b5e935f6a019317e455b6da83dd8650ac9ffd2ee73a7b657a30873d67a698" + ], + "version": "==5.4.2" + }, + "pytest-asyncio": { + "hashes": [ + "sha256:475bd2f3dc0bc11d2463656b3cbaafdbec5a47b47508ea0b329ee693040eebd2" + ], + "index": "pypi", + "version": "==0.12.0" }, "regex": { "hashes": [ - "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b", - "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8", - "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3", - "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e", - "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683", - "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1", - "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142", - "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3", - "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468", - "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e", - "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3", - "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a", - "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f", - "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6", - "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156", - "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b", - "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db", - "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd", - "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a", - "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948", - "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89" + "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927", + "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561", + "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3", + "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe", + "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c", + "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad", + "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1", + "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108", + "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929", + "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4", + "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994", + "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4", + "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd", + "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577", + "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7", + "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5", + "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f", + "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a", + "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd", + "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e", + "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01" ], - "version": "==2020.4.4" + "version": "==2020.5.14" }, "six": { "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], - "version": "==1.14.0" + "version": "==1.15.0" }, "stringcase": { "hashes": [ @@ -218,10 +277,10 @@ }, "toml": { "hashes": [ - "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", - "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" + "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f", + "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88" ], - "version": "==0.10.0" + "version": "==0.10.1" }, "typed-ast": { "hashes": [ @@ -248,6 +307,20 @@ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" ], "version": "==1.4.1" + }, + "wcwidth": { + "hashes": [ + "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1", + "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" + ], + "version": "==0.1.9" + }, + "zipp": { + "hashes": [ + "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", + "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" + ], + "version": "==3.1.0" } }, "develop": { @@ -258,20 +331,13 @@ ], "version": "==19.3.0" }, - "entrypoints": { - "hashes": [ - "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", - "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" - ], - "version": "==0.3" - }, "flake8": { "hashes": [ - "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", - "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" + "sha256:6c1193b0c3f853ef763969238f6c81e9e63ace9d024518edc020d5f1d6d93195", + "sha256:ea6623797bf9a52f4c9577d780da0bb17d65f870213f7b5bcc9fca82540c31d5" ], "index": "pypi", - "version": "==3.7.9" + "version": "==3.8.1" }, "importlib-metadata": { "hashes": [ @@ -298,10 +364,10 @@ }, "more-itertools": { "hashes": [ - "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", - "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" + "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be", + "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982" ], - "version": "==8.2.0" + "version": "==8.3.0" }, "mypy": { "hashes": [ @@ -332,10 +398,10 @@ }, "packaging": { "hashes": [ - "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3", - "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752" + "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", + "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" ], - "version": "==20.3" + "version": "==20.4" }, "pluggy": { "hashes": [ @@ -353,17 +419,17 @@ }, "pycodestyle": { "hashes": [ - "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", - "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", + "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" ], - "version": "==2.5.0" + "version": "==2.6.0" }, "pyflakes": { "hashes": [ - "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", - "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92", + "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8" ], - "version": "==2.1.1" + "version": "==2.2.0" }, "pyparsing": { "hashes": [ @@ -374,35 +440,31 @@ }, "pytest": { "hashes": [ - "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172", - "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970" + "sha256:95c710d0a72d91c13fae35dce195633c929c3792f54125919847fdcdf7caa0d3", + "sha256:eb2b5e935f6a019317e455b6da83dd8650ac9ffd2ee73a7b657a30873d67a698" ], - "index": "pypi", - "version": "==5.4.1" + "version": "==5.4.2" }, "pytest-asyncio": { "hashes": [ - "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", - "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b" + "sha256:475bd2f3dc0bc11d2463656b3cbaafdbec5a47b47508ea0b329ee693040eebd2" ], "index": "pypi", - "version": "==0.10.0" + "version": "==0.12.0" }, "rope": { "hashes": [ - "sha256:52423a7eebb5306a6d63bdc91a7c657db51ac9babfb8341c9a1440831ecf3203", - "sha256:ae1fa2fd56f64f4cc9be46493ce54bed0dd12dee03980c61a4393d89d84029ad", - "sha256:d2830142c2e046f5fc26a022fe680675b6f48f81c7fc1f03a950706e746e9dfe" + "sha256:658ad6705f43dcf3d6df379da9486529cf30e02d9ea14c5682aa80eb33b649e1" ], "index": "pypi", - "version": "==0.16.0" + "version": "==0.17.0" }, "six": { "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], - "version": "==1.14.0" + "version": "==1.15.0" }, "typed-ast": { "hashes": [ diff --git a/betterproto/plugin.bat b/betterproto/plugin.bat new file mode 100644 index 0000000..9b837d7 --- /dev/null +++ b/betterproto/plugin.bat @@ -0,0 +1,2 @@ +@SET plugin_dir=%~dp0 +@python %plugin_dir%/plugin.py %* \ No newline at end of file diff --git a/betterproto/tests/generate.py b/betterproto/tests/generate.py deleted file mode 100644 index 987f2d9..0000000 --- a/betterproto/tests/generate.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python -import os - -# Force pure-python implementation instead of C++, otherwise imports -# break things because we can't properly reset the symbol database. -os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python" - -import importlib -import json -import subprocess -import sys -from typing import Generator, Tuple - -from google.protobuf import symbol_database -from google.protobuf.descriptor_pool import DescriptorPool -from google.protobuf.json_format import MessageToJson, Parse - - -root = os.path.dirname(os.path.realpath(__file__)) - - -def get_files(end: str) -> Generator[str, None, None]: - for r, dirs, files in os.walk(root): - for filename in [f for f in files if f.endswith(end)]: - yield os.path.join(r, filename) - - -def get_base(filename: str) -> str: - return os.path.splitext(os.path.basename(filename))[0] - - -def ensure_ext(filename: str, ext: str) -> str: - if not filename.endswith(ext): - return filename + ext - return filename - - -if __name__ == "__main__": - os.chdir(root) - - if len(sys.argv) > 1: - proto_files = [ensure_ext(f, ".proto") for f in sys.argv[1:]] - bases = {get_base(f) for f in proto_files} - json_files = [ - f for f in get_files(".json") if get_base(f).split("-")[0] in bases - ] - else: - proto_files = get_files(".proto") - json_files = get_files(".json") - - for filename in proto_files: - print(f"Generating code for {os.path.basename(filename)}") - subprocess.run( - f"protoc --python_out=. {os.path.basename(filename)}", shell=True - ) - subprocess.run( - f"protoc --plugin=protoc-gen-custom=../plugin.py --custom_out=. {os.path.basename(filename)}", - shell=True, - ) - - for filename in json_files: - # Reset the internal symbol database so we can import the `Test` message - # multiple times. Ugh. - sym = symbol_database.Default() - sym.pool = DescriptorPool() - - parts = get_base(filename).split("-") - out = filename.replace(".json", ".bin") - print(f"Using {parts[0]}_pb2 to generate {os.path.basename(out)}") - - imported = importlib.import_module(f"{parts[0]}_pb2") - input_json = open(filename).read() - parsed = Parse(input_json, imported.Test()) - serialized = parsed.SerializeToString() - preserve = "casing" not in filename - serialized_json = MessageToJson(parsed, preserving_proto_field_name=preserve) - - s_loaded = json.loads(serialized_json) - in_loaded = json.loads(input_json) - - if s_loaded != in_loaded: - raise AssertionError("Expected JSON to be equal:", s_loaded, in_loaded) - - open(out, "wb").write(serialized) diff --git a/betterproto/tests/bool.json b/betterproto/tests/inputs/bool/bool.json similarity index 100% rename from betterproto/tests/bool.json rename to betterproto/tests/inputs/bool/bool.json diff --git a/betterproto/tests/bool.proto b/betterproto/tests/inputs/bool/bool.proto similarity index 100% rename from betterproto/tests/bool.proto rename to betterproto/tests/inputs/bool/bool.proto diff --git a/betterproto/tests/inputs/bool/test.py b/betterproto/tests/inputs/bool/test.py new file mode 100644 index 0000000..846d522 --- /dev/null +++ b/betterproto/tests/inputs/bool/test.py @@ -0,0 +1,8 @@ +from betterproto.tests.output_betterproto.bool.bool import Test +from betterproto.tests.util import read_relative + + +def test_value(): + message = Test().from_json(read_relative(__file__, 'bool.json')) + assert message.value + diff --git a/betterproto/tests/bytes.json b/betterproto/tests/inputs/bytes/bytes.json similarity index 100% rename from betterproto/tests/bytes.json rename to betterproto/tests/inputs/bytes/bytes.json diff --git a/betterproto/tests/bytes.proto b/betterproto/tests/inputs/bytes/bytes.proto similarity index 100% rename from betterproto/tests/bytes.proto rename to betterproto/tests/inputs/bytes/bytes.proto diff --git a/betterproto/tests/casing.json b/betterproto/tests/inputs/casing/casing.json similarity index 100% rename from betterproto/tests/casing.json rename to betterproto/tests/inputs/casing/casing.json diff --git a/betterproto/tests/casing.proto b/betterproto/tests/inputs/casing/casing.proto similarity index 64% rename from betterproto/tests/casing.proto rename to betterproto/tests/inputs/casing/casing.proto index 4ab37ae..ad0c427 100644 --- a/betterproto/tests/casing.proto +++ b/betterproto/tests/inputs/casing/casing.proto @@ -9,4 +9,9 @@ enum my_enum { message Test { int32 camelCase = 1; my_enum snake_case = 2; + snake_case_message snake_case_message = 3; } + +message snake_case_message { + +} \ No newline at end of file diff --git a/betterproto/tests/double-negative.json b/betterproto/tests/inputs/double/double-negative.json similarity index 100% rename from betterproto/tests/double-negative.json rename to betterproto/tests/inputs/double/double-negative.json diff --git a/betterproto/tests/double.json b/betterproto/tests/inputs/double/double.json similarity index 100% rename from betterproto/tests/double.json rename to betterproto/tests/inputs/double/double.json diff --git a/betterproto/tests/double.proto b/betterproto/tests/inputs/double/double.proto similarity index 100% rename from betterproto/tests/double.proto rename to betterproto/tests/inputs/double/double.proto diff --git a/betterproto/tests/enums.json b/betterproto/tests/inputs/enums/enums.json similarity index 100% rename from betterproto/tests/enums.json rename to betterproto/tests/inputs/enums/enums.json diff --git a/betterproto/tests/enums.proto b/betterproto/tests/inputs/enums/enums.proto similarity index 100% rename from betterproto/tests/enums.proto rename to betterproto/tests/inputs/enums/enums.proto diff --git a/betterproto/tests/googletypes-missing.json b/betterproto/tests/inputs/googletypes/googletypes-missing.json similarity index 100% rename from betterproto/tests/googletypes-missing.json rename to betterproto/tests/inputs/googletypes/googletypes-missing.json diff --git a/betterproto/tests/googletypes.json b/betterproto/tests/inputs/googletypes/googletypes.json similarity index 100% rename from betterproto/tests/googletypes.json rename to betterproto/tests/inputs/googletypes/googletypes.json diff --git a/betterproto/tests/googletypes.proto b/betterproto/tests/inputs/googletypes/googletypes.proto similarity index 100% rename from betterproto/tests/googletypes.proto rename to betterproto/tests/inputs/googletypes/googletypes.proto diff --git a/betterproto/tests/inputs/googletypes_response/googletypes_response.proto b/betterproto/tests/inputs/googletypes_response/googletypes_response.proto new file mode 100644 index 0000000..4bdca68 --- /dev/null +++ b/betterproto/tests/inputs/googletypes_response/googletypes_response.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +import "google/protobuf/wrappers.proto"; + +service Test { + rpc GetInt32 (Input) returns (google.protobuf.Int32Value); + rpc GetAnotherInt32 (Input) returns (google.protobuf.Int32Value); + rpc GetInt64 (Input) returns (google.protobuf.Int64Value); + rpc GetOutput (Input) returns (Output); +} + +message Input { + +} + +message Output { + google.protobuf.Int64Value int64 = 1; +} \ No newline at end of file diff --git a/betterproto/tests/inputs/googletypes_response/test_googletypes_response.py b/betterproto/tests/inputs/googletypes_response/test_googletypes_response.py new file mode 100644 index 0000000..9e8e454 --- /dev/null +++ b/betterproto/tests/inputs/googletypes_response/test_googletypes_response.py @@ -0,0 +1,18 @@ +from typing import Optional + +import pytest + +from betterproto.tests.output_betterproto.googletypes_response.googletypes_response import TestStub + + +class TestStubChild(TestStub): + async def _unary_unary(self, route, request, response_type, **kwargs): + self.response_type = response_type + + +@pytest.mark.asyncio +async def test(): + pytest.skip('todo') + stub = TestStubChild(None) + await stub.get_int64() + assert stub.response_type != Optional[int] diff --git a/betterproto/tests/int32-negative.json b/betterproto/tests/inputs/int32/int32-negative.json similarity index 100% rename from betterproto/tests/int32-negative.json rename to betterproto/tests/inputs/int32/int32-negative.json diff --git a/betterproto/tests/int32.json b/betterproto/tests/inputs/int32/int32.json similarity index 100% rename from betterproto/tests/int32.json rename to betterproto/tests/inputs/int32/int32.json diff --git a/betterproto/tests/int32.proto b/betterproto/tests/inputs/int32/int32.proto similarity index 100% rename from betterproto/tests/int32.proto rename to betterproto/tests/inputs/int32/int32.proto diff --git a/betterproto/tests/keywords.json b/betterproto/tests/inputs/keywords/keywords.json similarity index 100% rename from betterproto/tests/keywords.json rename to betterproto/tests/inputs/keywords/keywords.json diff --git a/betterproto/tests/keywords.proto b/betterproto/tests/inputs/keywords/keywords.proto similarity index 100% rename from betterproto/tests/keywords.proto rename to betterproto/tests/inputs/keywords/keywords.proto diff --git a/betterproto/tests/map.json b/betterproto/tests/inputs/map/map.json similarity index 100% rename from betterproto/tests/map.json rename to betterproto/tests/inputs/map/map.json diff --git a/betterproto/tests/map.proto b/betterproto/tests/inputs/map/map.proto similarity index 100% rename from betterproto/tests/map.proto rename to betterproto/tests/inputs/map/map.proto diff --git a/betterproto/tests/mapmessage.json b/betterproto/tests/inputs/mapmessage/mapmessage.json similarity index 100% rename from betterproto/tests/mapmessage.json rename to betterproto/tests/inputs/mapmessage/mapmessage.json diff --git a/betterproto/tests/mapmessage.proto b/betterproto/tests/inputs/mapmessage/mapmessage.proto similarity index 100% rename from betterproto/tests/mapmessage.proto rename to betterproto/tests/inputs/mapmessage/mapmessage.proto diff --git a/betterproto/tests/nested.json b/betterproto/tests/inputs/nested/nested.json similarity index 100% rename from betterproto/tests/nested.json rename to betterproto/tests/inputs/nested/nested.json diff --git a/betterproto/tests/nested.proto b/betterproto/tests/inputs/nested/nested.proto similarity index 100% rename from betterproto/tests/nested.proto rename to betterproto/tests/inputs/nested/nested.proto diff --git a/betterproto/tests/nestedtwice.json b/betterproto/tests/inputs/nestedtwice/nestedtwice.json similarity index 100% rename from betterproto/tests/nestedtwice.json rename to betterproto/tests/inputs/nestedtwice/nestedtwice.json diff --git a/betterproto/tests/nestedtwice.proto b/betterproto/tests/inputs/nestedtwice/nestedtwice.proto similarity index 100% rename from betterproto/tests/nestedtwice.proto rename to betterproto/tests/inputs/nestedtwice/nestedtwice.proto diff --git a/betterproto/tests/oneof-name.json b/betterproto/tests/inputs/oneof/oneof-name.json similarity index 100% rename from betterproto/tests/oneof-name.json rename to betterproto/tests/inputs/oneof/oneof-name.json diff --git a/betterproto/tests/oneof.json b/betterproto/tests/inputs/oneof/oneof.json similarity index 100% rename from betterproto/tests/oneof.json rename to betterproto/tests/inputs/oneof/oneof.json diff --git a/betterproto/tests/oneof.proto b/betterproto/tests/inputs/oneof/oneof.proto similarity index 100% rename from betterproto/tests/oneof.proto rename to betterproto/tests/inputs/oneof/oneof.proto diff --git a/betterproto/tests/ref.json b/betterproto/tests/inputs/ref/ref.json similarity index 100% rename from betterproto/tests/ref.json rename to betterproto/tests/inputs/ref/ref.json diff --git a/betterproto/tests/ref.proto b/betterproto/tests/inputs/ref/ref.proto similarity index 100% rename from betterproto/tests/ref.proto rename to betterproto/tests/inputs/ref/ref.proto diff --git a/betterproto/tests/repeatedmessage.proto b/betterproto/tests/inputs/ref/repeatedmessage.proto similarity index 100% rename from betterproto/tests/repeatedmessage.proto rename to betterproto/tests/inputs/ref/repeatedmessage.proto diff --git a/betterproto/tests/repeated.json b/betterproto/tests/inputs/repeated/repeated.json similarity index 100% rename from betterproto/tests/repeated.json rename to betterproto/tests/inputs/repeated/repeated.json diff --git a/betterproto/tests/repeated.proto b/betterproto/tests/inputs/repeated/repeated.proto similarity index 100% rename from betterproto/tests/repeated.proto rename to betterproto/tests/inputs/repeated/repeated.proto diff --git a/betterproto/tests/repeatedmessage.json b/betterproto/tests/inputs/repeatedmessage/repeatedmessage.json similarity index 100% rename from betterproto/tests/repeatedmessage.json rename to betterproto/tests/inputs/repeatedmessage/repeatedmessage.json diff --git a/betterproto/tests/inputs/repeatedmessage/repeatedmessage.proto b/betterproto/tests/inputs/repeatedmessage/repeatedmessage.proto new file mode 100644 index 0000000..0ffacaf --- /dev/null +++ b/betterproto/tests/inputs/repeatedmessage/repeatedmessage.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package repeatedmessage; + +message Test { + repeated Sub greetings = 1; +} + +message Sub { + string greeting = 1; +} \ No newline at end of file diff --git a/betterproto/tests/repeatedpacked.json b/betterproto/tests/inputs/repeatedpacked/repeatedpacked.json similarity index 100% rename from betterproto/tests/repeatedpacked.json rename to betterproto/tests/inputs/repeatedpacked/repeatedpacked.json diff --git a/betterproto/tests/repeatedpacked.proto b/betterproto/tests/inputs/repeatedpacked/repeatedpacked.proto similarity index 100% rename from betterproto/tests/repeatedpacked.proto rename to betterproto/tests/inputs/repeatedpacked/repeatedpacked.proto diff --git a/betterproto/tests/service.proto b/betterproto/tests/inputs/service/service.proto similarity index 100% rename from betterproto/tests/service.proto rename to betterproto/tests/inputs/service/service.proto diff --git a/betterproto/tests/signed-negative.json b/betterproto/tests/inputs/signed/signed-negative.json similarity index 100% rename from betterproto/tests/signed-negative.json rename to betterproto/tests/inputs/signed/signed-negative.json diff --git a/betterproto/tests/signed.json b/betterproto/tests/inputs/signed/signed.json similarity index 100% rename from betterproto/tests/signed.json rename to betterproto/tests/inputs/signed/signed.json diff --git a/betterproto/tests/signed.proto b/betterproto/tests/inputs/signed/signed.proto similarity index 100% rename from betterproto/tests/signed.proto rename to betterproto/tests/inputs/signed/signed.proto diff --git a/betterproto/tests/test_inputs.py b/betterproto/tests/test_inputs.py index e8bc66c..5088b41 100644 --- a/betterproto/tests/test_inputs.py +++ b/betterproto/tests/test_inputs.py @@ -1,32 +1,99 @@ import importlib import json - +import os +import sys import pytest -from .generate import get_base, get_files +# Force pure-python implementation instead of C++, otherwise imports +# break things because we can't properly reset the symbol database. +os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python" -inputs = get_files(".bin") +from google.protobuf import symbol_database +from google.protobuf.descriptor_pool import DescriptorPool +from google.protobuf.json_format import Parse + +import betterproto +from betterproto.tests.util import get_directories, inputs_path + +excluded_test_cases = {'googletypes_response', 'service'} +test_case_names = {*get_directories(inputs_path)} - excluded_test_cases + +plugin_output_package = 'betterproto.tests.output_betterproto' +reference_output_package = 'betterproto.tests.output_reference' -@pytest.mark.parametrize("filename", inputs) -def test_sample(filename: str) -> None: - module = get_base(filename).split("-")[0] - imported = importlib.import_module(f"betterproto.tests.{module}") - data_binary = open(filename, "rb").read() - data_dict = json.loads(open(filename.replace(".bin", ".json")).read()) - t1 = imported.Test().parse(data_binary) - t2 = imported.Test().from_dict(data_dict) - print(t1) - print(t2) +@pytest.mark.parametrize("test_case_name", test_case_names) +def test_message_can_be_imported(test_case_name: str) -> None: + importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") - # Equality should automagically work for dataclasses! - assert t1 == t2 - # Generally this can't be relied on, but here we are aiming to match the - # existing Python implementation and aren't doing anything tricky. - # https://developers.google.com/protocol-buffers/docs/encoding#implications - assert bytes(t1) == data_binary - assert bytes(t2) == data_binary +@pytest.mark.parametrize("test_case_name", test_case_names) +def test_message_can_instantiated(test_case_name: str) -> None: + plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + plugin_module.Test() - assert t1.to_dict() == data_dict - assert t2.to_dict() == data_dict + +@pytest.mark.parametrize("test_case_name", test_case_names) +def test_message_equality(test_case_name: str) -> None: + plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + message1 = plugin_module.Test() + message2 = plugin_module.Test() + assert message1 == message2 + + +@pytest.mark.parametrize("test_case_name", test_case_names) +def test_message_json(test_case_name: str) -> None: + plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + message: betterproto.Message = plugin_module.Test() + reference_json_data = get_test_case_json_data(test_case_name) + + message.from_json(reference_json_data) + message_json = message.to_json(0) + + assert json.loads(message_json) == json.loads(reference_json_data) + + +@pytest.mark.parametrize("test_case_name", test_case_names) +def test_binary_compatibility(test_case_name: str) -> None: + # Reset the internal symbol database so we can import the `Test` message + # multiple times. Ugh. + sym = symbol_database.Default() + sym.pool = DescriptorPool() + + reference_module_root = os.path.join(*reference_output_package.split('.'), test_case_name) + + print(f'Appending {reference_module_root}') + sys.path.append(reference_module_root) + + # import reference message + reference_module = importlib.import_module(f"{reference_output_package}.{test_case_name}.{test_case_name}_pb2") + plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + + test_data = get_test_case_json_data(test_case_name) + + reference_instance = Parse(test_data, reference_module.Test()) + reference_binary_output = reference_instance.SerializeToString() + + plugin_instance_from_json: betterproto.Message = plugin_module.Test().from_json(test_data) + plugin_instance_from_binary = plugin_module.Test.FromString(reference_binary_output) + + # # Generally this can't be relied on, but here we are aiming to match the + # # existing Python implementation and aren't doing anything tricky. + # # https://developers.google.com/protocol-buffers/docs/encoding#implications + assert plugin_instance_from_json == plugin_instance_from_binary + assert plugin_instance_from_json.to_dict() == plugin_instance_from_binary.to_dict() + + sys.path.remove(reference_module_root) + + +''' +helper methods +''' + +def get_test_case_json_data(test_case_name): + test_data_path = os.path.join(inputs_path, test_case_name, f'{test_case_name}.json') + if not os.path.exists(test_data_path): + return None + + with open(test_data_path) as fh: + return fh.read() diff --git a/betterproto/tests/test_service_stub.py b/betterproto/tests/test_service_stub.py index a5ba200..86377e2 100644 --- a/betterproto/tests/test_service_stub.py +++ b/betterproto/tests/test_service_stub.py @@ -3,8 +3,8 @@ import grpclib from grpclib.testing import ChannelFor import pytest from typing import Dict -from .service import DoThingResponse, DoThingRequest, ExampleServiceStub +from betterproto.tests.output_betterproto.service.service import DoThingResponse, DoThingRequest, ExampleServiceStub class ExampleService: def __init__(self, test_hook=None): diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..5a120c0 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +python_files = test*.py +python_classes = +norecursedirs = **/output_* +addopts = -p no:warnings \ No newline at end of file From 6775632f77901eeea24ce39103c37cfff832c9fc Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 13:03:52 +0200 Subject: [PATCH 04/16] Undo unintentional pipfile update --- Pipfile | 2 - Pipfile.lock | 284 ++++++++++++++++++++------------------------------- 2 files changed, 111 insertions(+), 175 deletions(-) diff --git a/Pipfile b/Pipfile index 18ed9c4..11ba0f9 100644 --- a/Pipfile +++ b/Pipfile @@ -20,8 +20,6 @@ stringcase = "*" black = "*" backports-datetime-fromisoformat = "*" dataclasses = "*" -betterproto = {editable = true,path = "."} -pytest-asyncio = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 5021cbe..f3ee3ba 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "9d2ee95f2c962097d22375cb461ceaefc40467919d53d80f7ed2541794d8fd6b" + "sha256": "b8fc738d4e14598e36269ce0d849489f95562ba047e5663caca9ac02550893ef" }, "pipfile-spec": 6, "requires": { @@ -18,10 +18,10 @@ "default": { "appdirs": { "hashes": [ - "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", - "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" ], - "version": "==1.4.4" + "version": "==1.4.3" }, "attrs": { "hashes": [ @@ -37,10 +37,6 @@ "index": "pypi", "version": "==1.0.0" }, - "betterproto": { - "editable": true, - "path": "." - }, "black": { "hashes": [ "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b", @@ -51,18 +47,18 @@ }, "click": { "hashes": [ - "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", - "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" + "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", + "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" ], - "version": "==7.1.2" + "version": "==7.1.1" }, "dataclasses": { "hashes": [ - "sha256:3459118f7ede7c8bea0fe795bff7c6c2ce287d01dd226202f7c9ebc0610a7836", - "sha256:494a6dcae3b8bcf80848eea2ef64c0cc5cd307ffc263e17cdf42f3e5420808e6" + "sha256:454a69d788c7fda44efd71e259be79577822f5e3f53f029a22d08004e951dc9f", + "sha256:6988bd2b895eef432d562370bb707d540f32f7360ab13da45340101bc2307d84" ], "index": "pypi", - "version": "==0.7" + "version": "==0.6" }, "grpclib": { "hashes": [ @@ -92,14 +88,6 @@ ], "version": "==5.2.0" }, - "importlib-metadata": { - "hashes": [ - "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", - "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" - ], - "markers": "python_version < '3.8'", - "version": "==1.6.0" - }, "jinja2": { "hashes": [ "sha256:c10142f819c2d22bdcd17548c46fa9b77cf4fda45097854c689666bf425e7484", @@ -135,41 +123,27 @@ ], "version": "==2.0.0a1" }, - "more-itertools": { - "hashes": [ - "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be", - "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982" - ], - "version": "==8.3.0" - }, "multidict": { "hashes": [ - "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a", - "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000", - "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2", - "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507", - "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5", - "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7", - "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d", - "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463", - "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19", - "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3", - "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b", - "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c", - "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87", - "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7", - "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430", - "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255", - "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d" + "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1", + "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35", + "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928", + "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969", + "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e", + "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78", + "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1", + "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136", + "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8", + "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2", + "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e", + "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4", + "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5", + "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd", + "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab", + "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20", + "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3" ], - "version": "==4.7.6" - }, - "packaging": { - "hashes": [ - "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", - "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" - ], - "version": "==20.4" + "version": "==4.7.5" }, "pathspec": { "hashes": [ @@ -178,95 +152,62 @@ ], "version": "==0.8.0" }, - "pluggy": { - "hashes": [ - "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", - "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" - ], - "version": "==0.13.1" - }, "protobuf": { "hashes": [ - "sha256:04d0b2bd99050d09393875a5a25fd12337b17f3ac2e29c0c1b8e65b277cbfe72", - "sha256:05288e44638e91498f13127a3699a6528dec6f9d3084d60959d721bfb9ea5b98", - "sha256:175d85370947f89e33b3da93f4ccdda3f326bebe3e599df5915ceb7f804cd9df", - "sha256:440a8c77531b3652f24999b249256ed01fd44c498ab0973843066681bd276685", - "sha256:49fb6fab19cd3f30fa0e976eeedcbf2558e9061e5fa65b4fe51ded1f4002e04d", - "sha256:4c7cae1f56056a4a2a2e3b00b26ab8550eae738bd9548f4ea0c2fcb88ed76ae5", - "sha256:519abfacbb421c3591d26e8daf7a4957763428db7267f7207e3693e29f6978db", - "sha256:60f32af25620abc4d7928d8197f9f25d49d558c5959aa1e08c686f974ac0b71a", - "sha256:613ac49f6db266fba243daf60fb32af107cfe3678e5c003bb40a381b6786389d", - "sha256:954bb14816edd24e746ba1a6b2d48c43576393bbde2fb8e1e3bd6d4504c7feac", - "sha256:9b1462c033a2cee7f4e8eb396905c69de2c532c3b835ff8f71f8e5fb77c38023", - "sha256:c0767f4d93ce4288475afe0571663c78870924f1f8881efd5406c10f070c75e4", - "sha256:c45f5980ce32879391144b5766120fd7b8803129f127ce36bd060dd38824801f", - "sha256:eeb7502f59e889a88bcb59f299493e215d1864f3d75335ea04a413004eb4fe24", - "sha256:fdb1742f883ee4662e39fcc5916f2725fec36a5191a52123fec60f8c53b70495", - "sha256:fe554066c4962c2db0a1d4752655223eb948d2bfa0fb1c4a7f2c00ec07324f1c" + "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab", + "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f", + "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a", + "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0", + "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4", + "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2", + "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee", + "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07", + "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151", + "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a", + "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f", + "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7", + "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956", + "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306", + "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961", + "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481", + "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a", + "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80" ], "index": "pypi", - "version": "==3.12.1" - }, - "py": { - "hashes": [ - "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", - "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" - ], - "version": "==1.8.1" - }, - "pyparsing": { - "hashes": [ - "sha256:67199f0c41a9c702154efb0e7a8cc08accf830eb003b4d9fa42c4059002e2492", - "sha256:700d17888d441604b0bd51535908dcb297561b040819cccde647a92439db5a2a" - ], - "version": "==3.0.0a1" - }, - "pytest": { - "hashes": [ - "sha256:95c710d0a72d91c13fae35dce195633c929c3792f54125919847fdcdf7caa0d3", - "sha256:eb2b5e935f6a019317e455b6da83dd8650ac9ffd2ee73a7b657a30873d67a698" - ], - "version": "==5.4.2" - }, - "pytest-asyncio": { - "hashes": [ - "sha256:475bd2f3dc0bc11d2463656b3cbaafdbec5a47b47508ea0b329ee693040eebd2" - ], - "index": "pypi", - "version": "==0.12.0" + "version": "==3.11.3" }, "regex": { "hashes": [ - "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927", - "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561", - "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3", - "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe", - "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c", - "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad", - "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1", - "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108", - "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929", - "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4", - "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994", - "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4", - "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd", - "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577", - "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7", - "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5", - "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f", - "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a", - "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd", - "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e", - "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01" + "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b", + "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8", + "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3", + "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e", + "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683", + "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1", + "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142", + "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3", + "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468", + "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e", + "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3", + "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a", + "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f", + "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6", + "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156", + "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b", + "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db", + "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd", + "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a", + "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948", + "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89" ], - "version": "==2020.5.14" + "version": "==2020.4.4" }, "six": { "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.15.0" + "version": "==1.14.0" }, "stringcase": { "hashes": [ @@ -277,10 +218,10 @@ }, "toml": { "hashes": [ - "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f", - "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88" + "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", + "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" ], - "version": "==0.10.1" + "version": "==0.10.0" }, "typed-ast": { "hashes": [ @@ -307,20 +248,6 @@ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" ], "version": "==1.4.1" - }, - "wcwidth": { - "hashes": [ - "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1", - "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" - ], - "version": "==0.1.9" - }, - "zipp": { - "hashes": [ - "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", - "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" - ], - "version": "==3.1.0" } }, "develop": { @@ -331,13 +258,20 @@ ], "version": "==19.3.0" }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" + }, "flake8": { "hashes": [ - "sha256:6c1193b0c3f853ef763969238f6c81e9e63ace9d024518edc020d5f1d6d93195", - "sha256:ea6623797bf9a52f4c9577d780da0bb17d65f870213f7b5bcc9fca82540c31d5" + "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", + "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" ], "index": "pypi", - "version": "==3.8.1" + "version": "==3.7.9" }, "importlib-metadata": { "hashes": [ @@ -364,10 +298,10 @@ }, "more-itertools": { "hashes": [ - "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be", - "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982" + "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", + "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" ], - "version": "==8.3.0" + "version": "==8.2.0" }, "mypy": { "hashes": [ @@ -398,10 +332,10 @@ }, "packaging": { "hashes": [ - "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", - "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3", + "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752" ], - "version": "==20.4" + "version": "==20.3" }, "pluggy": { "hashes": [ @@ -419,17 +353,17 @@ }, "pycodestyle": { "hashes": [ - "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", - "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" ], - "version": "==2.6.0" + "version": "==2.5.0" }, "pyflakes": { "hashes": [ - "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92", - "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8" + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" ], - "version": "==2.2.0" + "version": "==2.1.1" }, "pyparsing": { "hashes": [ @@ -440,31 +374,35 @@ }, "pytest": { "hashes": [ - "sha256:95c710d0a72d91c13fae35dce195633c929c3792f54125919847fdcdf7caa0d3", - "sha256:eb2b5e935f6a019317e455b6da83dd8650ac9ffd2ee73a7b657a30873d67a698" + "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172", + "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970" ], - "version": "==5.4.2" + "index": "pypi", + "version": "==5.4.1" }, "pytest-asyncio": { "hashes": [ - "sha256:475bd2f3dc0bc11d2463656b3cbaafdbec5a47b47508ea0b329ee693040eebd2" + "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", + "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b" ], "index": "pypi", - "version": "==0.12.0" + "version": "==0.10.0" }, "rope": { "hashes": [ - "sha256:658ad6705f43dcf3d6df379da9486529cf30e02d9ea14c5682aa80eb33b649e1" + "sha256:52423a7eebb5306a6d63bdc91a7c657db51ac9babfb8341c9a1440831ecf3203", + "sha256:ae1fa2fd56f64f4cc9be46493ce54bed0dd12dee03980c61a4393d89d84029ad", + "sha256:d2830142c2e046f5fc26a022fe680675b6f48f81c7fc1f03a950706e746e9dfe" ], "index": "pypi", - "version": "==0.17.0" + "version": "==0.16.0" }, "six": { "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.15.0" + "version": "==1.14.0" }, "typed-ast": { "hashes": [ From 13e08fdaa89d7444dffe8e375e290045d23fc9d7 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 15:05:52 +0200 Subject: [PATCH 05/16] Add missing file, ignore output files --- .gitignore | 2 ++ betterproto/tests/generate.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 betterproto/tests/generate.py diff --git a/.gitignore b/.gitignore index 249cc9b..a2d3d32 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ betterproto/tests/*.py dist **/*.egg-info output +betterproto/tests/output_* +.idea \ No newline at end of file diff --git a/betterproto/tests/generate.py b/betterproto/tests/generate.py new file mode 100644 index 0000000..03a5c2a --- /dev/null +++ b/betterproto/tests/generate.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +import os + +# Force pure-python implementation instead of C++, otherwise imports +# break things because we can't properly reset the symbol database. +os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python" + + +from betterproto.tests.util import get_directories, protoc_plugin, protoc_reference, root_path + +def main(): + os.chdir(root_path) + test_cases_directory = os.path.join(root_path, 'inputs') + test_case = get_directories(test_cases_directory) + + for test_case_name in test_case: + test_case_path = os.path.join(test_cases_directory, test_case_name) + + case_reference_output_dir = os.path.join(root_path, 'output_reference', test_case_name) + case_plugin_output_dir = os.path.join(root_path, 'output_betterproto', test_case_name) + + print(f'Generating output for {test_case_name}') + os.makedirs(case_reference_output_dir, exist_ok=True) + os.makedirs(case_plugin_output_dir, exist_ok=True) + + protoc_reference(test_case_path, case_reference_output_dir) + protoc_plugin(test_case_path, case_plugin_output_dir) + + +if __name__ == "__main__": + main() From 6969ff7ff6531b7cf5326596370c4acf29861939 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 15:34:25 +0200 Subject: [PATCH 06/16] Add another missing gitignored file, and remove gitignore filter for tests/ --- .gitignore | 7 +----- betterproto/tests/util.py | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 betterproto/tests/util.py diff --git a/.gitignore b/.gitignore index a2d3d32..dd22728 100644 --- a/.gitignore +++ b/.gitignore @@ -4,14 +4,9 @@ .pytest_cache .python-version build/ -betterproto/tests/*.bin -betterproto/tests/*_pb2.py -betterproto/tests/*.py -!betterproto/tests/generate.py -!betterproto/tests/test_*.py +betterproto/tests/output_* **/__pycache__ dist **/*.egg-info output -betterproto/tests/output_* .idea \ No newline at end of file diff --git a/betterproto/tests/util.py b/betterproto/tests/util.py new file mode 100644 index 0000000..c65e2a6 --- /dev/null +++ b/betterproto/tests/util.py @@ -0,0 +1,46 @@ +import os +import subprocess +from typing import Generator + +os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python" + +root_path = os.path.dirname(os.path.realpath(__file__)) +inputs_path = os.path.join(root_path, 'inputs') + +if os.name == 'nt': + plugin_path = os.path.join(root_path, '..', 'plugin.bat') +else: + plugin_path = os.path.join(root_path, '..', 'plugin.py') + + +def get_files(path, end: str) -> Generator[str, None, None]: + for r, dirs, files in os.walk(path): + for filename in [f for f in files if f.endswith(end)]: + yield os.path.join(r, filename) + + +def get_directories(path): + for root, directories, files in os.walk(path): + for directory in directories: + yield directory + + +def relative(file: str, path: str): + return os.path.join(os.path.dirname(file), path) + + +def read_relative(file: str, path: str): + with open(relative(file, path)) as fh: + return fh.read() + + +def protoc_plugin(path: str, output_dir: str): + subprocess.run( + f"protoc --plugin=protoc-gen-custom={plugin_path} --custom_out={output_dir} --proto_path={path} {path}/*.proto", + shell=True, + ) + + +def protoc_reference(path: str, output_dir: str): + subprocess.run(f"protoc --python_out={output_dir} --proto_path={path} {path}/*.proto", shell=True) + From 77c04414f5f4fc2acb254a3526c77b104af75df4 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 16:36:43 +0200 Subject: [PATCH 07/16] Update readme, add docs for standard tests --- README.md | 24 +++++-- betterproto/tests/inputs/bool/test.py | 8 --- betterproto/tests/inputs/bool/test_bool.py | 6 ++ betterproto/tests/standard-tests.md | 75 ++++++++++++++++++++++ pytest.ini | 2 +- 5 files changed, 102 insertions(+), 13 deletions(-) delete mode 100644 betterproto/tests/inputs/bool/test.py create mode 100644 betterproto/tests/inputs/bool/test_bool.py create mode 100644 betterproto/tests/standard-tests.md diff --git a/README.md b/README.md index e971ee2..315b0da 100644 --- a/README.md +++ b/README.md @@ -311,10 +311,26 @@ $ pip install -e . There are two types of tests: -1. Manually-written tests for some behavior of the library -2. Proto files and JSON inputs for automated tests +1. Standard tests +2. Custom tests -For #2, you can add a new `*.proto` file into the `betterproto/tests` directory along with a sample `*.json` input and it will get automatically picked up. +#### Standard tests + +Adding a standard test case is easy. + +- Create a new directory `betterproto/tests/inputs/` + - add `.proto` with a message called `Test` + - add `.json` with some test data + +It will be picked up automatically when you run `pipenv test` + +- See also: [Standard Tests Development Guide](betterproto\tests\standard-tests.md) + +#### Custom tests + +Custom tests are found in `tests/test_*.py` and are run with pytest. + +#### Running Here's how to run the tests. @@ -322,7 +338,7 @@ Here's how to run the tests. # Generate assets from sample .proto files $ pipenv run generate -# Run the tests +# Run all tests $ pipenv run test ``` diff --git a/betterproto/tests/inputs/bool/test.py b/betterproto/tests/inputs/bool/test.py deleted file mode 100644 index 846d522..0000000 --- a/betterproto/tests/inputs/bool/test.py +++ /dev/null @@ -1,8 +0,0 @@ -from betterproto.tests.output_betterproto.bool.bool import Test -from betterproto.tests.util import read_relative - - -def test_value(): - message = Test().from_json(read_relative(__file__, 'bool.json')) - assert message.value - diff --git a/betterproto/tests/inputs/bool/test_bool.py b/betterproto/tests/inputs/bool/test_bool.py new file mode 100644 index 0000000..0d4daa6 --- /dev/null +++ b/betterproto/tests/inputs/bool/test_bool.py @@ -0,0 +1,6 @@ +from betterproto.tests.output_betterproto.bool.bool import Test + + +def test_value(): + message = Test() + assert not message.value, "Boolean is False by default" diff --git a/betterproto/tests/standard-tests.md b/betterproto/tests/standard-tests.md new file mode 100644 index 0000000..ea15758 --- /dev/null +++ b/betterproto/tests/standard-tests.md @@ -0,0 +1,75 @@ +# Standard Tests Development Guide + +Standard test cases are found in [betterproto/tests/inputs](inputs), where each subdirectory represents a testcase, that is verified in isolation. + +``` +inputs/ + bool/ + double/ + int32/ + ... +``` + +## Test case directory structure + +Each testcase has a `.proto` file with a message called `Test`, a matching `.json` file and optionally a custom test file called `test_*.py`. + +```bash +bool/ + bool.proto + bool.json + test_bool.py # optional +``` + +### proto + +`.proto` — *The protobuf message to test* + +```protobuf +syntax = "proto3"; + +message Test { + bool value = 1; +} +``` + +You can add multiple `.proto` files to the test case, as long as one file matches the directory name. + +### json + +`.json` — *Test-data to validate the message with* + +```json +{ + "value": true +} +``` + +### pytest + +`test_.py` — *Custom test to validate specific aspects of the generated class* + +```python +from betterproto.tests.output_betterproto.bool.bool import Test + +def test_value(): + message = Test() + assert not message.value, "Boolean is False by default" +``` + +## Standard tests + +The following tests are automatically executed for all cases: + +- [x] Can the generated python code imported? +- [x] Can the generated message class be instantiated? +- [x] Is the generated code compatible with the Google's `grpc_tools.protoc` implementation? + +## Running the tests + +- `pipenv run generate` + This generates + - `betterproto/tests/output_betterproto` — *the plugin generated python classes* + - `betterproto/tests/output_reference` — *reference implementation classes* +- `pipenv run test` + diff --git a/pytest.ini b/pytest.ini index 5a120c0..bec2b96 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,5 +1,5 @@ [pytest] -python_files = test*.py +python_files = test_*.py python_classes = norecursedirs = **/output_* addopts = -p no:warnings \ No newline at end of file From dd4873dfba773a2c1584ed5aba9fba276f46fec4 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 20:51:22 +0200 Subject: [PATCH 08/16] Re-introducing whitelisting argument to generate.py --- betterproto/tests/generate.py | 58 +++++++++++++++++++++++++++-------- betterproto/tests/util.py | 2 ++ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/betterproto/tests/generate.py b/betterproto/tests/generate.py index 03a5c2a..c33f30b 100644 --- a/betterproto/tests/generate.py +++ b/betterproto/tests/generate.py @@ -1,30 +1,62 @@ #!/usr/bin/env python import os +import sys +from typing import Set + +from betterproto.tests.util import get_directories, inputs_path, output_path_betterproto, output_path_reference, \ + protoc_plugin, protoc_reference # Force pure-python implementation instead of C++, otherwise imports # break things because we can't properly reset the symbol database. os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python" -from betterproto.tests.util import get_directories, protoc_plugin, protoc_reference, root_path +def generate(whitelist: Set[str]): + path_whitelist = {os.path.realpath(e) for e in whitelist if os.path.exists(e)} + name_whitelist = {e for e in whitelist if not os.path.exists(e)} -def main(): - os.chdir(root_path) - test_cases_directory = os.path.join(root_path, 'inputs') - test_case = get_directories(test_cases_directory) + test_case_names = set(get_directories(inputs_path)) - for test_case_name in test_case: - test_case_path = os.path.join(test_cases_directory, test_case_name) + for test_case_name in test_case_names: + test_case_path = os.path.join(inputs_path, test_case_name) - case_reference_output_dir = os.path.join(root_path, 'output_reference', test_case_name) - case_plugin_output_dir = os.path.join(root_path, 'output_betterproto', test_case_name) + is_path_whitelisted = path_whitelist and os.path.realpath(test_case_path) in path_whitelist + is_name_whitelisted = name_whitelist and test_case_name in name_whitelist + + if whitelist and not is_path_whitelisted and not is_name_whitelisted: + continue + + case_output_dir_reference = os.path.join(output_path_reference, test_case_name) + case_output_dir_betterproto = os.path.join(output_path_betterproto, test_case_name) print(f'Generating output for {test_case_name}') - os.makedirs(case_reference_output_dir, exist_ok=True) - os.makedirs(case_plugin_output_dir, exist_ok=True) + os.makedirs(case_output_dir_reference, exist_ok=True) + os.makedirs(case_output_dir_betterproto, exist_ok=True) - protoc_reference(test_case_path, case_reference_output_dir) - protoc_plugin(test_case_path, case_plugin_output_dir) + protoc_reference(test_case_path, case_output_dir_reference) + protoc_plugin(test_case_path, case_output_dir_betterproto) + + +HELP = "\n".join([ + 'Usage: python generate.py', + ' python generate.py [DIRECTORIES or NAMES]', + 'Generate python classes for standard tests.', + '', + 'DIRECTORIES One or more relative or absolute directories of test-cases to generate classes for.', + ' python generate.py inputs/bool inputs/double inputs/enum', + '', + 'NAMES One or more test-case names to generate classes for.', + ' python generate.py bool double enums' +]) + + +def main(): + if sys.argv[1] in ('-h', '--help'): + print(HELP) + return + whitelist = set(sys.argv[1:]) + + generate(whitelist) if __name__ == "__main__": diff --git a/betterproto/tests/util.py b/betterproto/tests/util.py index c65e2a6..b627a23 100644 --- a/betterproto/tests/util.py +++ b/betterproto/tests/util.py @@ -6,6 +6,8 @@ os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python" root_path = os.path.dirname(os.path.realpath(__file__)) inputs_path = os.path.join(root_path, 'inputs') +output_path_reference = os.path.join(root_path, 'output_reference') +output_path_betterproto = os.path.join(root_path, 'output_betterproto') if os.name == 'nt': plugin_path = os.path.join(root_path, '..', 'plugin.bat') From dfa0a56b3906bb5066d0cfaddc477abc2b7d90e1 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 20:58:14 +0200 Subject: [PATCH 09/16] Simplify standard tests by using 1 json per case. --- betterproto/tests/inputs/int32/int32-negative.json | 3 --- betterproto/tests/inputs/int32/int32.json | 3 ++- betterproto/tests/inputs/int32/int32.proto | 3 ++- betterproto/tests/inputs/signed/signed-negative.json | 4 ---- betterproto/tests/inputs/signed/signed.json | 6 ++++-- betterproto/tests/inputs/signed/signed.proto | 7 +++++-- betterproto/tests/test_inputs.py | 7 ++++++- 7 files changed, 19 insertions(+), 14 deletions(-) delete mode 100644 betterproto/tests/inputs/int32/int32-negative.json delete mode 100644 betterproto/tests/inputs/signed/signed-negative.json diff --git a/betterproto/tests/inputs/int32/int32-negative.json b/betterproto/tests/inputs/int32/int32-negative.json deleted file mode 100644 index 0d2bb48..0000000 --- a/betterproto/tests/inputs/int32/int32-negative.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "count": -150 -} diff --git a/betterproto/tests/inputs/int32/int32.json b/betterproto/tests/inputs/int32/int32.json index 9514828..34d4111 100644 --- a/betterproto/tests/inputs/int32/int32.json +++ b/betterproto/tests/inputs/int32/int32.json @@ -1,3 +1,4 @@ { - "count": 150 + "positive": 150, + "negative": -150 } diff --git a/betterproto/tests/inputs/int32/int32.proto b/betterproto/tests/inputs/int32/int32.proto index 6b46857..cae0dc7 100644 --- a/betterproto/tests/inputs/int32/int32.proto +++ b/betterproto/tests/inputs/int32/int32.proto @@ -3,5 +3,6 @@ syntax = "proto3"; // Some documentation about the Test message. message Test { // Some documentation about the count. - int32 count = 1; + int32 positive = 1; + int32 negative = 2; } diff --git a/betterproto/tests/inputs/signed/signed-negative.json b/betterproto/tests/inputs/signed/signed-negative.json deleted file mode 100644 index 2f6525a..0000000 --- a/betterproto/tests/inputs/signed/signed-negative.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "signed_32": -150, - "signed_64": "-150" -} diff --git a/betterproto/tests/inputs/signed/signed.json b/betterproto/tests/inputs/signed/signed.json index 6049d88..b171e15 100644 --- a/betterproto/tests/inputs/signed/signed.json +++ b/betterproto/tests/inputs/signed/signed.json @@ -1,4 +1,6 @@ { - "signed_32": 150, - "signed_64": "150" + "signed32": 150, + "negative32": -150, + "string64": "150", + "negative64": "-150" } diff --git a/betterproto/tests/inputs/signed/signed.proto b/betterproto/tests/inputs/signed/signed.proto index 49b2bfd..23fc9ee 100644 --- a/betterproto/tests/inputs/signed/signed.proto +++ b/betterproto/tests/inputs/signed/signed.proto @@ -1,6 +1,9 @@ syntax = "proto3"; message Test { - sint32 signed_32 = 1; - sint64 signed_64 = 2; + // todo: rename fields after fixing bug where 'signed_32_positive' will map to 'signed_32Positive' as output json + sint32 signed32 = 1; // signed_32_positive + sint32 negative32 = 2; // signed_32_negative + sint64 string64 = 3; // signed_64_positive + sint64 negative64 = 4; // signed_64_negative } diff --git a/betterproto/tests/test_inputs.py b/betterproto/tests/test_inputs.py index 5088b41..cd86fff 100644 --- a/betterproto/tests/test_inputs.py +++ b/betterproto/tests/test_inputs.py @@ -50,7 +50,12 @@ def test_message_json(test_case_name: str) -> None: message.from_json(reference_json_data) message_json = message.to_json(0) - assert json.loads(message_json) == json.loads(reference_json_data) + print(reference_json_data) + print(message_json) + + assert json.loads(reference_json_data) == json.loads(message_json) + + # todo: handle -negative @pytest.mark.parametrize("test_case_name", test_case_names) From 4b4bdefb6fa4d1912d9e4e50ac2ac676293c030d Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 20:58:31 +0200 Subject: [PATCH 10/16] Add explicit test for casing rules --- betterproto/tests/inputs/casing/test_casing.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 betterproto/tests/inputs/casing/test_casing.py diff --git a/betterproto/tests/inputs/casing/test_casing.py b/betterproto/tests/inputs/casing/test_casing.py new file mode 100644 index 0000000..3d1ac3d --- /dev/null +++ b/betterproto/tests/inputs/casing/test_casing.py @@ -0,0 +1,16 @@ +import betterproto.tests.output_betterproto.casing.casing as casing +from betterproto.tests.output_betterproto.casing.casing import Test + + +def test_message_attributes(): + message = Test() + assert hasattr(message, 'snake_case_message'), 'snake_case field name is same in python' + assert hasattr(message, 'camel_case'), 'CamelCase field is snake_case in python' + + +def test_message_casing(): + assert hasattr(casing, 'SnakeCaseMessage'), 'snake_case Message name is converted to CamelCase in python' + + +def test_enum_casing(): + assert hasattr(casing, 'MyEnum'), 'snake_case Enum name is converted to CamelCase in python' From 960dba2ae8231c82c09bd1486d80b88f9006acb1 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 20:58:53 +0200 Subject: [PATCH 11/16] Renamed docs for standard tests --- README.md | 2 +- betterproto/tests/{standard-tests.md => README.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename betterproto/tests/{standard-tests.md => README.md} (100%) diff --git a/README.md b/README.md index 315b0da..28fd913 100644 --- a/README.md +++ b/README.md @@ -324,7 +324,7 @@ Adding a standard test case is easy. It will be picked up automatically when you run `pipenv test` -- See also: [Standard Tests Development Guide](betterproto\tests\standard-tests.md) +- See also: [Standard Tests Development Guide](betterproto/tests/README.md) #### Custom tests diff --git a/betterproto/tests/standard-tests.md b/betterproto/tests/README.md similarity index 100% rename from betterproto/tests/standard-tests.md rename to betterproto/tests/README.md From 6ec902c1b54b49635a73ab3388b7e691b3d2daaa Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 21:03:45 +0200 Subject: [PATCH 12/16] Fix generate noargs. Sorted iteration. --- betterproto/tests/generate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/betterproto/tests/generate.py b/betterproto/tests/generate.py index c33f30b..2c081b7 100644 --- a/betterproto/tests/generate.py +++ b/betterproto/tests/generate.py @@ -17,7 +17,7 @@ def generate(whitelist: Set[str]): test_case_names = set(get_directories(inputs_path)) - for test_case_name in test_case_names: + for test_case_name in sorted(test_case_names): test_case_path = os.path.join(inputs_path, test_case_name) is_path_whitelisted = path_whitelist and os.path.realpath(test_case_path) in path_whitelist @@ -51,7 +51,7 @@ HELP = "\n".join([ def main(): - if sys.argv[1] in ('-h', '--help'): + if set(sys.argv).intersection({'-h', '--help'}): print(HELP) return whitelist = set(sys.argv[1:]) From 6bd9c7835ce36368708a91e0624354808fd689b8 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 21:08:08 +0200 Subject: [PATCH 13/16] Fix docs --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 28fd913..53a7cdd 100644 --- a/README.md +++ b/README.md @@ -322,7 +322,7 @@ Adding a standard test case is easy. - add `.proto` with a message called `Test` - add `.json` with some test data -It will be picked up automatically when you run `pipenv test` +It will be picked up automatically when you run the tests. - See also: [Standard Tests Development Guide](betterproto/tests/README.md) @@ -356,6 +356,9 @@ $ pipenv run test - [x] Refs to nested types - [x] Imports in proto files - [x] Well-known Google types + - [ ] Support as request input + - [ ] Support as response output + - [ ] Automatically wrap/unwrap responses - [x] OneOf support - [x] Basic support on the wire - [x] Check which was set from the group From c3e3837f71f2030fe8b130eccc7844e8283b8dd1 Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 21:11:23 +0200 Subject: [PATCH 14/16] More concise whitelist logic --- betterproto/tests/generate.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/betterproto/tests/generate.py b/betterproto/tests/generate.py index 2c081b7..fdcb220 100644 --- a/betterproto/tests/generate.py +++ b/betterproto/tests/generate.py @@ -18,12 +18,9 @@ def generate(whitelist: Set[str]): test_case_names = set(get_directories(inputs_path)) for test_case_name in sorted(test_case_names): - test_case_path = os.path.join(inputs_path, test_case_name) + test_case_path = os.path.realpath(os.path.join(inputs_path, test_case_name)) - is_path_whitelisted = path_whitelist and os.path.realpath(test_case_path) in path_whitelist - is_name_whitelisted = name_whitelist and test_case_name in name_whitelist - - if whitelist and not is_path_whitelisted and not is_name_whitelisted: + if whitelist and test_case_path not in path_whitelist and test_case_name not in name_whitelist: continue case_output_dir_reference = os.path.join(output_path_reference, test_case_name) From 92088ebda88fe2e8e1217f1ac71ef384c7989baa Mon Sep 17 00:00:00 2001 From: boukeversteegh Date: Fri, 22 May 2020 21:16:27 +0200 Subject: [PATCH 15/16] Cleanup --- betterproto/tests/test_inputs.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/betterproto/tests/test_inputs.py b/betterproto/tests/test_inputs.py index cd86fff..d819b2e 100644 --- a/betterproto/tests/test_inputs.py +++ b/betterproto/tests/test_inputs.py @@ -3,6 +3,8 @@ import json import os import sys import pytest +import betterproto +from betterproto.tests.util import get_directories, inputs_path # Force pure-python implementation instead of C++, otherwise imports # break things because we can't properly reset the symbol database. @@ -12,8 +14,6 @@ from google.protobuf import symbol_database from google.protobuf.descriptor_pool import DescriptorPool from google.protobuf.json_format import Parse -import betterproto -from betterproto.tests.util import get_directories, inputs_path excluded_test_cases = {'googletypes_response', 'service'} test_case_names = {*get_directories(inputs_path)} - excluded_test_cases @@ -50,13 +50,8 @@ def test_message_json(test_case_name: str) -> None: message.from_json(reference_json_data) message_json = message.to_json(0) - print(reference_json_data) - print(message_json) - assert json.loads(reference_json_data) == json.loads(message_json) - # todo: handle -negative - @pytest.mark.parametrize("test_case_name", test_case_names) def test_binary_compatibility(test_case_name: str) -> None: @@ -67,7 +62,6 @@ def test_binary_compatibility(test_case_name: str) -> None: reference_module_root = os.path.join(*reference_output_package.split('.'), test_case_name) - print(f'Appending {reference_module_root}') sys.path.append(reference_module_root) # import reference message @@ -95,6 +89,7 @@ def test_binary_compatibility(test_case_name: str) -> None: helper methods ''' + def get_test_case_json_data(test_case_name): test_data_path = os.path.join(inputs_path, test_case_name, f'{test_case_name}.json') if not os.path.exists(test_data_path): From 5e2d9febea2a2982b7cc372ef5f4b1b7d2233e79 Mon Sep 17 00:00:00 2001 From: Nat Noordanus Date: Sat, 23 May 2020 23:37:22 +0200 Subject: [PATCH 16/16] Blacken --- betterproto/plugin.py | 2 +- betterproto/tests/generate.py | 48 ++++++++++++------- .../tests/inputs/casing/test_casing.py | 14 ++++-- .../test_googletypes_response.py | 6 ++- betterproto/tests/test_features.py | 2 +- betterproto/tests/test_inputs.py | 44 +++++++++++------ betterproto/tests/test_service_stub.py | 17 +++++-- betterproto/tests/util.py | 18 +++---- 8 files changed, 100 insertions(+), 51 deletions(-) diff --git a/betterproto/plugin.py b/betterproto/plugin.py index 597bf1a..5bce411 100755 --- a/betterproto/plugin.py +++ b/betterproto/plugin.py @@ -122,7 +122,7 @@ def get_py_zero(type_num: int) -> str: def traverse(proto_file): - def _traverse(path, items, prefix = ''): + def _traverse(path, items, prefix=""): for i, item in enumerate(items): # Adjust the name since we flatten the heirarchy. item.name = next_prefix = prefix + item.name diff --git a/betterproto/tests/generate.py b/betterproto/tests/generate.py index fdcb220..fc3c4cd 100644 --- a/betterproto/tests/generate.py +++ b/betterproto/tests/generate.py @@ -3,8 +3,14 @@ import os import sys from typing import Set -from betterproto.tests.util import get_directories, inputs_path, output_path_betterproto, output_path_reference, \ - protoc_plugin, protoc_reference +from betterproto.tests.util import ( + get_directories, + inputs_path, + output_path_betterproto, + output_path_reference, + protoc_plugin, + protoc_reference, +) # Force pure-python implementation instead of C++, otherwise imports # break things because we can't properly reset the symbol database. @@ -20,13 +26,19 @@ def generate(whitelist: Set[str]): for test_case_name in sorted(test_case_names): test_case_path = os.path.realpath(os.path.join(inputs_path, test_case_name)) - if whitelist and test_case_path not in path_whitelist and test_case_name not in name_whitelist: + if ( + whitelist + and test_case_path not in path_whitelist + and test_case_name not in name_whitelist + ): continue case_output_dir_reference = os.path.join(output_path_reference, test_case_name) - case_output_dir_betterproto = os.path.join(output_path_betterproto, test_case_name) + case_output_dir_betterproto = os.path.join( + output_path_betterproto, test_case_name + ) - print(f'Generating output for {test_case_name}') + print(f"Generating output for {test_case_name}") os.makedirs(case_output_dir_reference, exist_ok=True) os.makedirs(case_output_dir_betterproto, exist_ok=True) @@ -34,21 +46,23 @@ def generate(whitelist: Set[str]): protoc_plugin(test_case_path, case_output_dir_betterproto) -HELP = "\n".join([ - 'Usage: python generate.py', - ' python generate.py [DIRECTORIES or NAMES]', - 'Generate python classes for standard tests.', - '', - 'DIRECTORIES One or more relative or absolute directories of test-cases to generate classes for.', - ' python generate.py inputs/bool inputs/double inputs/enum', - '', - 'NAMES One or more test-case names to generate classes for.', - ' python generate.py bool double enums' -]) +HELP = "\n".join( + [ + "Usage: python generate.py", + " python generate.py [DIRECTORIES or NAMES]", + "Generate python classes for standard tests.", + "", + "DIRECTORIES One or more relative or absolute directories of test-cases to generate classes for.", + " python generate.py inputs/bool inputs/double inputs/enum", + "", + "NAMES One or more test-case names to generate classes for.", + " python generate.py bool double enums", + ] +) def main(): - if set(sys.argv).intersection({'-h', '--help'}): + if set(sys.argv).intersection({"-h", "--help"}): print(HELP) return whitelist = set(sys.argv[1:]) diff --git a/betterproto/tests/inputs/casing/test_casing.py b/betterproto/tests/inputs/casing/test_casing.py index 3d1ac3d..3255c4e 100644 --- a/betterproto/tests/inputs/casing/test_casing.py +++ b/betterproto/tests/inputs/casing/test_casing.py @@ -4,13 +4,19 @@ from betterproto.tests.output_betterproto.casing.casing import Test def test_message_attributes(): message = Test() - assert hasattr(message, 'snake_case_message'), 'snake_case field name is same in python' - assert hasattr(message, 'camel_case'), 'CamelCase field is snake_case in python' + assert hasattr( + message, "snake_case_message" + ), "snake_case field name is same in python" + assert hasattr(message, "camel_case"), "CamelCase field is snake_case in python" def test_message_casing(): - assert hasattr(casing, 'SnakeCaseMessage'), 'snake_case Message name is converted to CamelCase in python' + assert hasattr( + casing, "SnakeCaseMessage" + ), "snake_case Message name is converted to CamelCase in python" def test_enum_casing(): - assert hasattr(casing, 'MyEnum'), 'snake_case Enum name is converted to CamelCase in python' + assert hasattr( + casing, "MyEnum" + ), "snake_case Enum name is converted to CamelCase in python" diff --git a/betterproto/tests/inputs/googletypes_response/test_googletypes_response.py b/betterproto/tests/inputs/googletypes_response/test_googletypes_response.py index 9e8e454..fba2070 100644 --- a/betterproto/tests/inputs/googletypes_response/test_googletypes_response.py +++ b/betterproto/tests/inputs/googletypes_response/test_googletypes_response.py @@ -2,7 +2,9 @@ from typing import Optional import pytest -from betterproto.tests.output_betterproto.googletypes_response.googletypes_response import TestStub +from betterproto.tests.output_betterproto.googletypes_response.googletypes_response import ( + TestStub +) class TestStubChild(TestStub): @@ -12,7 +14,7 @@ class TestStubChild(TestStub): @pytest.mark.asyncio async def test(): - pytest.skip('todo') + pytest.skip("todo") stub = TestStubChild(None) await stub.get_int64() assert stub.response_type != Optional[int] diff --git a/betterproto/tests/test_features.py b/betterproto/tests/test_features.py index c0b40c1..47019e1 100644 --- a/betterproto/tests/test_features.py +++ b/betterproto/tests/test_features.py @@ -256,7 +256,7 @@ def test_to_dict_default_values(): some_double: float = betterproto.double_field(2) some_message: TestChildMessage = betterproto.message_field(3) - test = TestParentMessage().from_dict({"someInt": 0, "someDouble": 1.2,}) + test = TestParentMessage().from_dict({"someInt": 0, "someDouble": 1.2}) assert test.to_dict(include_default_values=True) == { "someInt": 0, diff --git a/betterproto/tests/test_inputs.py b/betterproto/tests/test_inputs.py index d819b2e..c8fb7d3 100644 --- a/betterproto/tests/test_inputs.py +++ b/betterproto/tests/test_inputs.py @@ -15,27 +15,33 @@ from google.protobuf.descriptor_pool import DescriptorPool from google.protobuf.json_format import Parse -excluded_test_cases = {'googletypes_response', 'service'} +excluded_test_cases = {"googletypes_response", "service"} test_case_names = {*get_directories(inputs_path)} - excluded_test_cases -plugin_output_package = 'betterproto.tests.output_betterproto' -reference_output_package = 'betterproto.tests.output_reference' +plugin_output_package = "betterproto.tests.output_betterproto" +reference_output_package = "betterproto.tests.output_reference" @pytest.mark.parametrize("test_case_name", test_case_names) def test_message_can_be_imported(test_case_name: str) -> None: - importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + importlib.import_module( + f"{plugin_output_package}.{test_case_name}.{test_case_name}" + ) @pytest.mark.parametrize("test_case_name", test_case_names) def test_message_can_instantiated(test_case_name: str) -> None: - plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + plugin_module = importlib.import_module( + f"{plugin_output_package}.{test_case_name}.{test_case_name}" + ) plugin_module.Test() @pytest.mark.parametrize("test_case_name", test_case_names) def test_message_equality(test_case_name: str) -> None: - plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + plugin_module = importlib.import_module( + f"{plugin_output_package}.{test_case_name}.{test_case_name}" + ) message1 = plugin_module.Test() message2 = plugin_module.Test() assert message1 == message2 @@ -43,7 +49,9 @@ def test_message_equality(test_case_name: str) -> None: @pytest.mark.parametrize("test_case_name", test_case_names) def test_message_json(test_case_name: str) -> None: - plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + plugin_module = importlib.import_module( + f"{plugin_output_package}.{test_case_name}.{test_case_name}" + ) message: betterproto.Message = plugin_module.Test() reference_json_data = get_test_case_json_data(test_case_name) @@ -60,20 +68,28 @@ def test_binary_compatibility(test_case_name: str) -> None: sym = symbol_database.Default() sym.pool = DescriptorPool() - reference_module_root = os.path.join(*reference_output_package.split('.'), test_case_name) + reference_module_root = os.path.join( + *reference_output_package.split("."), test_case_name + ) sys.path.append(reference_module_root) # import reference message - reference_module = importlib.import_module(f"{reference_output_package}.{test_case_name}.{test_case_name}_pb2") - plugin_module = importlib.import_module(f"{plugin_output_package}.{test_case_name}.{test_case_name}") + reference_module = importlib.import_module( + f"{reference_output_package}.{test_case_name}.{test_case_name}_pb2" + ) + plugin_module = importlib.import_module( + f"{plugin_output_package}.{test_case_name}.{test_case_name}" + ) test_data = get_test_case_json_data(test_case_name) reference_instance = Parse(test_data, reference_module.Test()) reference_binary_output = reference_instance.SerializeToString() - plugin_instance_from_json: betterproto.Message = plugin_module.Test().from_json(test_data) + plugin_instance_from_json: betterproto.Message = plugin_module.Test().from_json( + test_data + ) plugin_instance_from_binary = plugin_module.Test.FromString(reference_binary_output) # # Generally this can't be relied on, but here we are aiming to match the @@ -85,13 +101,13 @@ def test_binary_compatibility(test_case_name: str) -> None: sys.path.remove(reference_module_root) -''' +""" helper methods -''' +""" def get_test_case_json_data(test_case_name): - test_data_path = os.path.join(inputs_path, test_case_name, f'{test_case_name}.json') + test_data_path = os.path.join(inputs_path, test_case_name, f"{test_case_name}.json") if not os.path.exists(test_data_path): return None diff --git a/betterproto/tests/test_service_stub.py b/betterproto/tests/test_service_stub.py index 86377e2..b614e82 100644 --- a/betterproto/tests/test_service_stub.py +++ b/betterproto/tests/test_service_stub.py @@ -4,7 +4,12 @@ from grpclib.testing import ChannelFor import pytest from typing import Dict -from betterproto.tests.output_betterproto.service.service import DoThingResponse, DoThingRequest, ExampleServiceStub +from betterproto.tests.output_betterproto.service.service import ( + DoThingResponse, + DoThingRequest, + ExampleServiceStub, +) + class ExampleService: def __init__(self, test_hook=None): @@ -29,7 +34,7 @@ class ExampleService: grpclib.const.Cardinality.UNARY_UNARY, DoThingRequest, DoThingResponse, - ), + ) } @@ -94,7 +99,9 @@ async def test_service_call_lower_level_with_overrides(): ) as channel: stub = ExampleServiceStub(channel, deadline=deadline, metadata=metadata) response = await stub._unary_unary( - "/service.ExampleService/DoThing", DoThingRequest(ITERATIONS), DoThingResponse, + "/service.ExampleService/DoThing", + DoThingRequest(ITERATIONS), + DoThingResponse, deadline=kwarg_deadline, metadata=kwarg_metadata, ) @@ -116,7 +123,9 @@ async def test_service_call_lower_level_with_overrides(): ) as channel: stub = ExampleServiceStub(channel, deadline=deadline, metadata=metadata) response = await stub._unary_unary( - "/service.ExampleService/DoThing", DoThingRequest(ITERATIONS), DoThingResponse, + "/service.ExampleService/DoThing", + DoThingRequest(ITERATIONS), + DoThingResponse, timeout=kwarg_timeout, metadata=kwarg_metadata, ) diff --git a/betterproto/tests/util.py b/betterproto/tests/util.py index b627a23..83cfd98 100644 --- a/betterproto/tests/util.py +++ b/betterproto/tests/util.py @@ -5,14 +5,14 @@ from typing import Generator os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python" root_path = os.path.dirname(os.path.realpath(__file__)) -inputs_path = os.path.join(root_path, 'inputs') -output_path_reference = os.path.join(root_path, 'output_reference') -output_path_betterproto = os.path.join(root_path, 'output_betterproto') +inputs_path = os.path.join(root_path, "inputs") +output_path_reference = os.path.join(root_path, "output_reference") +output_path_betterproto = os.path.join(root_path, "output_betterproto") -if os.name == 'nt': - plugin_path = os.path.join(root_path, '..', 'plugin.bat') +if os.name == "nt": + plugin_path = os.path.join(root_path, "..", "plugin.bat") else: - plugin_path = os.path.join(root_path, '..', 'plugin.py') + plugin_path = os.path.join(root_path, "..", "plugin.py") def get_files(path, end: str) -> Generator[str, None, None]: @@ -44,5 +44,7 @@ def protoc_plugin(path: str, output_dir: str): def protoc_reference(path: str, output_dir: str): - subprocess.run(f"protoc --python_out={output_dir} --proto_path={path} {path}/*.proto", shell=True) - + subprocess.run( + f"protoc --python_out={output_dir} --proto_path={path} {path}/*.proto", + shell=True, + )