From e2f791840d494d2ecb37e9e63b12b6406548a98d Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Thu, 20 Feb 2020 19:14:09 -0500 Subject: [PATCH 1/9] Drop `first` as a dependency - Assorted additional optimizations around `pip_shims` invocations for tests to pass Signed-off-by: Dan Ryan --- Pipfile.lock | 348 +++++++++------------ setup.cfg | 6 +- src/requirementslib/models/dependencies.py | 15 +- src/requirementslib/models/markers.py | 79 +++-- src/requirementslib/models/requirements.py | 68 ++-- src/requirementslib/models/setup_info.py | 4 + src/requirementslib/models/utils.py | 15 +- tests/unit/test_requirements.py | 12 +- 8 files changed, 274 insertions(+), 273 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 6f07b19c..56ba0858 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -78,11 +78,11 @@ }, "babel": { "hashes": [ - "sha256:af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", - "sha256:e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28" + "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", + "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.7.0" + "version": "==2.8.0" }, "backports.functools-lru-cache": { "hashes": [ @@ -235,10 +235,11 @@ }, "colorama": { "hashes": [ - "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", - "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48" + "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", + "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" ], - "version": "==0.4.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.4.3" }, "configparser": { "hashes": [ @@ -258,38 +259,40 @@ }, "coverage": { "hashes": [ - "sha256:2358e685d0253125da42a48396038d4c7b4cd1448c00bbc4bda0cb8c43c2a870", - "sha256:25017cf384eeed2e6caf72efd3ec4124e32a8b7a4387600499104387975400c7", - "sha256:2e2de9423ff8b14303a97eafddd16c479fbcc9a0b8b0be3b7c3843a3e0cf6d69", - "sha256:324ed908e4e40a6e2451056fe502470ad4e79495cb7a03ecab94e6309c3e117e", - "sha256:34f865a0cf6255b694a46e4383a7131c61ea72c5b4c4f81d20e522fb1e440b4b", - "sha256:3a2bcc464b60a18f1f7167b95b2773ede93bf3722bfa59e0802717f652b6cc25", - "sha256:48d70865266d649b6602e2ba94820d7972ef470d3b72a8fd41a3d17321feed3a", - "sha256:50cf23523ab3a724c6905d3b60f87fa8250d9bae3995e09f49f63effa2b54f15", - "sha256:54c84a68abd8c4c5b71878b35eb85321df41f3d144c78181867d5b026ec74994", - "sha256:5b59d661ee7f3200aedd7b71882b7927ea7ed522df75e3853f316a79ad872a2e", - "sha256:5ffb39624bc573177888a21fb301ccee46838c600b27d58c3e9dae495f44d34a", - "sha256:699b3072b7f0e69ed175a88fa8b2ec7eefc4f34d490c54ed9a52feff21a15fdc", - "sha256:79ef4a2bb862110bd585174e551a783bee5c3aa461734a2ac7429193be357589", - "sha256:8210a6f93c4a8c6d460b402e20e38399529b99200c3318542faf6a520c9b6a5c", - "sha256:8d30c10cfd0a6fdf0a2d5023de00ef7b329cd6ead2310c9e53eab79c209acb70", - "sha256:97ac79ff28f2cda6ac00a803ee582b965951755f61ab43377482bfba450b619a", - "sha256:9fe4aacacff9028ed167db108bf013510654f148d83c4857fed61d2ce0588bf2", - "sha256:a5b6395d5957d638f8b1870561607e3c39b1a236ea6cff9eafe5b9bb1db913f2", - "sha256:ab32c5fad6905986a7e34e3acf01180a69bb60c2aa7331815b46e51c776a1943", - "sha256:ad67f0cfdfecbd49b9da46a7e488e6dc32a69388740b85c36a4ef4b33082cbad", - "sha256:aedad67c30326a1af324f45833a40b97180664912deb29942459ddbe9fa0ce19", - "sha256:b077cd0e70f41366ac1f9d09275258fa1906758a5d4f31cacc18b10dfcf90784", - "sha256:b8ea210810d3c14aec7561f8fe0d3eec582d1088100aaa0bb8153d53d867d20f", - "sha256:bf572722326ce6704e863447a070039a827072b7179352570859be899b9e6551", - "sha256:c0df57e189dacd2606cae6386acf127d01d85b2bf49acd9a65543b5d6c359ddc", - "sha256:d523e75f2a8a0b4a6a8be1287c0e0e3a561b8832b05ddd987d4cd7c62f3ad3bc", - "sha256:e10593c60c5f0bfd8b241bf9f27ef2191a3005b73dde8ada0424f642543a1e59", - "sha256:e9128444c83bc260aea988bf1ca6278a33ba730955bf94720468c656b61353eb", - "sha256:f7162f2e3711f3a08a8a741f92e1f63afd58d0713177979f2cf9723dd50161cf" + "sha256:15cf13a6896048d6d947bf7d222f36e4809ab926894beb748fc9caa14605d9c3", + "sha256:1daa3eceed220f9fdb80d5ff950dd95112cd27f70d004c7918ca6dfc6c47054c", + "sha256:1e44a022500d944d42f94df76727ba3fc0a5c0b672c358b61067abb88caee7a0", + "sha256:25dbf1110d70bab68a74b4b9d74f30e99b177cde3388e07cc7272f2168bd1477", + "sha256:3230d1003eec018ad4a472d254991e34241e0bbd513e97a29727c7c2f637bd2a", + "sha256:3dbb72eaeea5763676a1a1efd9b427a048c97c39ed92e13336e726117d0b72bf", + "sha256:5012d3b8d5a500834783689a5d2292fe06ec75dc86ee1ccdad04b6f5bf231691", + "sha256:51bc7710b13a2ae0c726f69756cf7ffd4362f4ac36546e243136187cfcc8aa73", + "sha256:527b4f316e6bf7755082a783726da20671a0cc388b786a64417780b90565b987", + "sha256:722e4557c8039aad9592c6a4213db75da08c2cd9945320220634f637251c3894", + "sha256:76e2057e8ffba5472fd28a3a010431fd9e928885ff480cb278877c6e9943cc2e", + "sha256:77afca04240c40450c331fa796b3eab6f1e15c5ecf8bf2b8bee9706cd5452fef", + "sha256:7afad9835e7a651d3551eab18cbc0fdb888f0a6136169fbef0662d9cdc9987cf", + "sha256:9bea19ac2f08672636350f203db89382121c9c2ade85d945953ef3c8cf9d2a68", + "sha256:a8b8ac7876bc3598e43e2603f772d2353d9931709345ad6c1149009fd1bc81b8", + "sha256:b0840b45187699affd4c6588286d429cd79a99d509fe3de0f209594669bb0954", + "sha256:b26aaf69713e5674efbde4d728fb7124e429c9466aeaf5f4a7e9e699b12c9fe2", + "sha256:b63dd43f455ba878e5e9f80ba4f748c0a2156dde6e0e6e690310e24d6e8caf40", + "sha256:be18f4ae5a9e46edae3f329de2191747966a34a3d93046dbdf897319923923bc", + "sha256:c312e57847db2526bc92b9bfa78266bfbaabac3fdcd751df4d062cd4c23e46dc", + "sha256:c60097190fe9dc2b329a0eb03393e2e0829156a589bd732e70794c0dd804258e", + "sha256:c62a2143e1313944bf4a5ab34fd3b4be15367a02e9478b0ce800cb510e3bbb9d", + "sha256:cc1109f54a14d940b8512ee9f1c3975c181bbb200306c6d8b87d93376538782f", + "sha256:cd60f507c125ac0ad83f05803063bed27e50fa903b9c2cfee3f8a6867ca600fc", + "sha256:d513cc3db248e566e07a0da99c230aca3556d9b09ed02f420664e2da97eac301", + "sha256:d649dc0bcace6fcdb446ae02b98798a856593b19b637c1b9af8edadf2b150bea", + "sha256:d7008a6796095a79544f4da1ee49418901961c97ca9e9d44904205ff7d6aa8cb", + "sha256:da93027835164b8223e8e5af2cf902a4c80ed93cb0909417234f4a9df3bcd9af", + "sha256:e69215621707119c6baf99bda014a45b999d37602cb7043d943c76a59b05bf52", + "sha256:ea9525e0fef2de9208250d6c5aeeee0138921057cd67fcef90fbed49c4d62d37", + "sha256:fca1669d464f0c9831fd10be2eef6b86f5ebd76c724d1e0706ebdff86bb4adf0" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", - "version": "==5.0b1" + "version": "==5.0.3" }, "cryptography": { "hashes": [ @@ -333,11 +336,11 @@ }, "docutils": { "hashes": [ - "sha256:7a6228589435302e421f5c473ce0180878b90f70227f7174cacde5efbd34275f", - "sha256:f1bad547016f945f7b35b28d8bead307821822ca3f8d4f87a1bd2ad1a8faab51" + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.16b0.dev0" + "version": "==0.16" }, "entrypoints": { "hashes": [ @@ -379,13 +382,6 @@ ], "version": "==1.5.2" }, - "first": { - "hashes": [ - "sha256:8d8e46e115ea8ac652c76123c0865e3ff18372aef6f03c22809ceefcea9dec86", - "sha256:ff285b08c55f8c97ce4ea7012743af2495c9f1291785f163722bd36f6af6d3bf" - ], - "version": "==2.0.2" - }, "flake8": { "hashes": [ "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", @@ -436,11 +432,11 @@ }, "identify": { "hashes": [ - "sha256:7782115794ec28b011702815d9f5e532244560cd2bf0789c4f09381d43befd90", - "sha256:9e7521e9abeaede4d2d1092a106e418c65ddf6b3182b43930bcb3c8cfb974488" + "sha256:1222b648251bdcb8deb240b294f450fbf704c7984e08baa92507e4ea10b436d5", + "sha256:d824ebe21f38325c771c41b08a95a761db1982f1fc0eee37c6c97df3f1636b96" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.4.8" + "version": "==1.4.11" }, "idna": { "hashes": [ @@ -452,11 +448,11 @@ }, "imagesize": { "hashes": [ - "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", - "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5" + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.1.0" + "version": "==1.2.0" }, "importlab": { "hashes": [ @@ -506,11 +502,11 @@ }, "jedi": { "hashes": [ - "sha256:786b6c3d80e2f06fd77162a07fed81b8baa22dde5d62896a790a331d6ac21a27", - "sha256:ba859c74fa3c966a22f2aeebe1b74ee27e2a462f56d3f5f7ca4a59af61bfe42e" + "sha256:b4f4052551025c6b0b0b193b29a6ff7bdb74c52450631206c262aef9f7159ad2", + "sha256:d5c871cb9360b414f981e7072c52c33258d598305280fef91c6cae34739d65d5" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.15.1" + "version": "==0.16.0" }, "jeepney": { "hashes": [ @@ -575,13 +571,16 @@ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", @@ -598,7 +597,9 @@ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.1" @@ -636,23 +637,23 @@ }, "mypy": { "hashes": [ - "sha256:02d9bdd3398b636723ecb6c5cfe9773025a9ab7f34612c1cde5c7f2292e2d768", - "sha256:088f758a50af31cf8b42688118077292370c90c89232c783ba7979f39ea16646", - "sha256:28e9fbc96d13397a7ddb7fad7b14f373f91b5cff538e0772e77c270468df083c", - "sha256:30e123b24931f02c5d99307406658ac8f9cd6746f0d45a3dcac2fe5fbdd60939", - "sha256:3294821b5840d51a3cd7a2bb63b40fc3f901f6a3cfb3c6046570749c4c7ef279", - "sha256:41696a7d912ce16fdc7c141d87e8db5144d4be664a0c699a2b417d393994b0c2", - "sha256:4f42675fa278f3913340bb8c3371d191319704437758d7c4a8440346c293ecb2", - "sha256:54d205ccce6ed930a8a2ccf48404896d456e8b87812e491cb907a355b1a9c640", - "sha256:6992133c95a2847d309b4b0c899d7054adc60481df6f6b52bb7dee3d5fd157f7", - "sha256:6ecbd0e8e371333027abca0922b0c2c632a5b4739a0c61ffbd0733391e39144c", - "sha256:83fa87f556e60782c0fc3df1b37b7b4a840314ba1ac27f3e1a1e10cb37c89c17", - "sha256:c87ac7233c629f305602f563db07f5221950fe34fe30af072ac838fa85395f78", - "sha256:de9ec8dba773b78c49e7bec9a35c9b6fc5235682ad1fc2105752ae7c22f4b931", - "sha256:f385a0accf353ca1bca4bbf473b9d83ed18d923fdb809d3a70a385da23e25b6a" + "sha256:0a9a45157e532da06fe56adcfef8a74629566b607fa2c1ac0122d1ff995c748a", + "sha256:2c35cae79ceb20d47facfad51f952df16c2ae9f45db6cb38405a3da1cf8fc0a7", + "sha256:4b9365ade157794cef9685791032521233729cb00ce76b0ddc78749abea463d2", + "sha256:53ea810ae3f83f9c9b452582261ea859828a9ed666f2e1ca840300b69322c474", + "sha256:634aef60b4ff0f650d3e59d4374626ca6153fcaff96ec075b215b568e6ee3cb0", + "sha256:7e396ce53cacd5596ff6d191b47ab0ea18f8e0ec04e15d69728d530e86d4c217", + "sha256:7eadc91af8270455e0d73565b8964da1642fe226665dd5c9560067cd64d56749", + "sha256:7f672d02fffcbace4db2b05369142e0506cdcde20cea0e07c7c2171c4fd11dd6", + "sha256:85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf", + "sha256:87c556fb85d709dacd4b4cb6167eecc5bbb4f0a9864b69136a0d4640fdc76a36", + "sha256:a6bd44efee4dc8c3324c13785a9dc3519b3ee3a92cada42d2b57762b7053b49b", + "sha256:c6d27bd20c3ba60d5b02f20bd28e20091d6286a699174dfad515636cb09b5a72", + "sha256:e2bb577d10d09a2d8822a042a23b8d62bc3b269667c9eb8e60a6edfa000211b1", + "sha256:f97a605d7c8bc2c6d1172c2f0d5a65b24142e11a58de689046e62c2d632ca8c1" ], "markers": "python_version >= '3.4'", - "version": "==0.750" + "version": "==0.761" }, "mypy-extensions": { "hashes": [ @@ -740,9 +741,10 @@ }, "pathspec": { "hashes": [ - "sha256:e285ccc8b0785beadd4c18e5708b12bb8fcf529a1e61215b3feff1d1e559ea5c" + "sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424", + "sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96" ], - "version": "==0.6.0" + "version": "==0.7.0" }, "pathtools": { "hashes": [ @@ -817,11 +819,11 @@ }, "py": { "hashes": [ - "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", - "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" + "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", + "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.8.0" + "version": "==1.8.1" }, "pycodestyle": { "hashes": [ @@ -857,11 +859,11 @@ }, "pyparsing": { "hashes": [ - "sha256:20f995ecd72f2a1f4bf6b072b63b22e2eb457836601e76d6e5dfcd75436acc1f", - "sha256:4ca62001be367f01bd3e92ecbb79070272a9d4964dce6a48a82ff0b8bc7e683a" + "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", + "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" ], "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.4.5" + "version": "==2.4.6" }, "pytest": { "hashes": [ @@ -889,24 +891,26 @@ }, "pytest-timeout": { "hashes": [ - "sha256:4a30ba76837a32c7b7cd5c84ee9933fde4b9022b0cd20ea7d4a577c2a1649fb1", - "sha256:d49f618c6448c14168773b6cdda022764c63ea80d42274e3156787e8088d04c6" + "sha256:80faa19cd245a42b87a51699d640c00d937c02b749052bfca6bae8bdbe12c48e", + "sha256:95ca727d4a1dace6ec5f0534d2940b8417ff8b782f7eef0ea09240bdd94d95c2" ], - "version": "==1.3.3" + "version": "==1.3.4" }, "pytest-xdist": { "hashes": [ - "sha256:5d1b1d4461518a6023d56dab62fb63670d6f7537f23e2708459a557329accf48", - "sha256:a8569b027db70112b290911ce2ed732121876632fb3f40b1d39cd2f72f58b147" + "sha256:0f46020d3d9619e6d17a65b5b989c1ebbb58fc7b1da8fb126d70f4bac4dfeed1", + "sha256:7dc0d027d258cd0defc618fb97055fbd1002735ca7a6d17037018cf870e24011" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.30.0" + "version": "==1.31.0" }, - "pytoml": { + "python-dateutil": { "hashes": [ - "sha256:ca2d0cb127c938b8b76a9a0d0f855cf930c1d50cc3a0af6d3595b566519a1013" + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], - "version": "==0.1.20" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.1" }, "pytype": { "hashes": [ @@ -924,19 +928,19 @@ }, "pyyaml": { "hashes": [ - "sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc", - "sha256:2e9f0b7c5914367b0916c3c104a024bb68f269a486b9d04a2e8ac6f6597b7803", - "sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc", - "sha256:38a4f0d114101c58c0f3a88aeaa44d63efd588845c5a2df5290b73db8f246d15", - "sha256:483eb6a33b671408c8529106df3707270bfacb2447bf8ad856a4b4f57f6e3075", - "sha256:4b6be5edb9f6bb73680f5bf4ee08ff25416d1400fbd4535fe0069b2994da07cd", - "sha256:7f38e35c00e160db592091751d385cd7b3046d6d51f578b29943225178257b31", - "sha256:8100c896ecb361794d8bfdb9c11fce618c7cf83d624d73d5ab38aef3bc82d43f", - "sha256:c0ee8eca2c582d29c3c2ec6e2c4f703d1b7f1fb10bc72317355a746057e7346c", - "sha256:e4c015484ff0ff197564917b4b4246ca03f411b9bd7f16e02a2f586eb48b6d04", - "sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4" + "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6", + "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf", + "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5", + "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e", + "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811", + "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e", + "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d", + "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20", + "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689", + "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994", + "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615" ], - "version": "==5.2" + "version": "==5.3" }, "readme-renderer": { "extras": [ @@ -1008,11 +1012,11 @@ }, "rope": { "hashes": [ - "sha256:6b728fdc3e98a83446c27a91fc5d56808a004f8beab7a31ab1d7224cecc7d969", - "sha256:c5c5a6a87f7b1a2095fb311135e2a3d1f194f5ecb96900fdd0a9100881f48aaf", - "sha256:f0dcf719b63200d492b85535ebe5ea9b29e0d0b8aebeb87fe03fc1a65924fdaf" + "sha256:52423a7eebb5306a6d63bdc91a7c657db51ac9babfb8341c9a1440831ecf3203", + "sha256:ae1fa2fd56f64f4cc9be46493ce54bed0dd12dee03980c61a4393d89d84029ad", + "sha256:d2830142c2e046f5fc26a022fe680675b6f48f81c7fc1f03a950706e746e9dfe" ], - "version": "==0.14.0" + "version": "==0.16.0" }, "scandir": { "hashes": [ @@ -1033,19 +1037,19 @@ }, "secretstorage": { "hashes": [ - "sha256:20c797ae48a4419f66f8d28fc221623f11fc45b6828f96bdb1ad9990acb59f92", - "sha256:7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a" + "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6", + "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b" ], "markers": "sys_platform == 'linux'", - "version": "==3.1.1" + "version": "==3.1.2" }, "six": { "hashes": [ - "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", - "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.13.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.14.0" }, "snowballstemmer": { "hashes": [ @@ -1054,6 +1058,13 @@ ], "version": "==2.0.0" }, + "sortedcontainers": { + "hashes": [ + "sha256:974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a", + "sha256:d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60" + ], + "version": "==2.1.0" + }, "sphinx": { "hashes": [ "sha256:9f3e17c64b34afc653d7c5ec95766e03043cc6d80b0de224f59b6b6e19d37c3c", @@ -1070,54 +1081,6 @@ "index": "pypi", "version": "==0.4.3" }, - "sphinxcontrib-applehelp": { - "hashes": [ - "sha256:edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897", - "sha256:fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.1" - }, - "sphinxcontrib-devhelp": { - "hashes": [ - "sha256:6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34", - "sha256:9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.1" - }, - "sphinxcontrib-htmlhelp": { - "hashes": [ - "sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422", - "sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.2" - }, - "sphinxcontrib-jsmath": { - "hashes": [ - "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", - "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.1" - }, - "sphinxcontrib-qthelp": { - "hashes": [ - "sha256:513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20", - "sha256:79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.2" - }, - "sphinxcontrib-serializinghtml": { - "hashes": [ - "sha256:c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227", - "sha256:db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768" - ], - "markers": "python_version >= '3.5'", - "version": "==1.1.3" - }, "sphinxcontrib-websupport": { "hashes": [ "sha256:1501befb0fdf1d1c29a800fdbf4ef5dc5369377300ddbdd16d2cd40e54c6eefc", @@ -1150,10 +1113,10 @@ }, "towncrier": { "hashes": [ - "sha256:d0c49060522e4b45d02c8ffe0b63e5ffa660830f681446945212e5c66314228b", - "sha256:f0375efce604977b4098c18dc805d5ce0de59b232db8374cb3ca98b078b5afae" + "sha256:48251a1ae66d2cf7e6fa5552016386831b3e12bb3b2d08eb70374508c17a8196", + "sha256:de19da8b8cb44f18ea7ed3a3823087d2af8fcf497151bb9fd1e1b092ff56ed8d" ], - "version": "==19.9.0rc1" + "version": "==19.2.0" }, "tqdm": { "hashes": [ @@ -1173,29 +1136,30 @@ }, "typed-ast": { "hashes": [ - "sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161", - "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", - "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", - "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", - "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", - "sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47", - "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", - "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", - "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", - "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", - "sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2", - "sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e", - "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", - "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", - "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", - "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", - "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", - "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", - "sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66", - "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" + "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" ], "markers": "python_version >= '3.4'", - "version": "==1.4.0" + "version": "==1.4.1" }, "typing": { "hashes": [ @@ -1217,11 +1181,11 @@ }, "urllib3": { "hashes": [ - "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", - "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", - "version": "==1.25.7" + "version": "==1.25.8" }, "virtualenv": { "hashes": [ @@ -1233,11 +1197,11 @@ }, "vistir": { "hashes": [ - "sha256:2166e3148a67c438c9e3edbba0cde153d42dec6e3bf5d8f4624feb27686c0990", - "sha256:3a0529b4b6c2e842fd19b5ceaa95b6c9201321314825c110406d4af3331a0709" + "sha256:33f8e905d40a77276b3d5310c8b57c1479a4e46930042b4894fcf7ed60ad76c4", + "sha256:e47afdec8baf35032a8d17116765f751ecd2f2146d47e5af457c5de1fe5a334e" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.4.3" + "version": "==0.5.0" }, "vulture": { "hashes": [ @@ -1255,10 +1219,10 @@ }, "wcwidth": { "hashes": [ - "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", - "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603", + "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8" ], - "version": "==0.1.7" + "version": "==0.1.8" }, "webencodings": { "hashes": [ diff --git a/setup.cfg b/setup.cfg index 2b229dea..aed17f8e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -50,18 +50,17 @@ install_requires = attrs>=18.2 cached_property distlib>=0.2.8 - first orderedmultidict packaging>=19.0 pep517>=0.5.0 pip-shims>=0.3.2 plette[validation] + python-dateutil requests scandir;python_version<"3.5" setuptools>=40.8 six>=1.11.0 tomlkit>=0.5.3 - typing;python_version<"3.5" vistir>=0.3.1 [options.extras_require] @@ -89,6 +88,7 @@ tests = coverage hypothesis typing = + typing;python_version<"3.5" mypy;python_version>="3.4" mypy-extensions;python_version>="3.4" mypytools;python_version>="3.4" @@ -127,7 +127,7 @@ not_skip = __init__.py line_length = 90 indent = ' ' multi_line_output = 3 -known_third_party = appdirs,attr,cached_property,distlib,environ,first,hypothesis,invoke,orderedmultidict,packaging,parver,pep517,pip_shims,pkg_resources,plette,pyparsing,pytest,requests,setuptools,six,tomlkit,towncrier,urllib3,vistir +known_third_party = appdirs,attr,cached_property,distlib,environ,hypothesis,invoke,orderedmultidict,packaging,parver,pep517,pip_shims,pkg_resources,plette,pyparsing,pytest,requests,setuptools,six,tomlkit,towncrier,urllib3,vistir known_first_party = requirementslib,tests combine_as_imports=True include_trailing_comma = True diff --git a/src/requirementslib/models/dependencies.py b/src/requirementslib/models/dependencies.py index 5e69b137..7a0a6d9f 100644 --- a/src/requirementslib/models/dependencies.py +++ b/src/requirementslib/models/dependencies.py @@ -11,7 +11,6 @@ import packaging.version import pip_shims.shims import requests -from first import first from packaging.utils import canonicalize_name from vistir.compat import JSONDecodeError, fs_str from vistir.contextmanagers import cd, temp_environ @@ -144,9 +143,9 @@ def compatible_versions(self, other): :rtype: set(str) """ - if len(self.candidates) == 1 and first(self.candidates).editable: + if len(self.candidates) == 1 and next(iter(self.candidates)).editable: return self - elif len(other.candidates) == 1 and first(other.candidates).editable: + elif len(other.candidates) == 1 and next(iter(other.candidates)).editable: return other return self.version_set & other.version_set @@ -163,9 +162,9 @@ def compatible_abstract_dep(self, other): from .requirements import Requirement - if len(self.candidates) == 1 and first(self.candidates).editable: + if len(self.candidates) == 1 and next(iter(self.candidates)).editable: return self - elif len(other.candidates) == 1 and first(other.candidates).editable: + elif len(other.candidates) == 1 and next(iter(other.candidates)).editable: return other new_specifiers = self.specifiers & other.specifiers markers = set(self.markers) if self.markers else set() @@ -694,10 +693,10 @@ def get_grouped_dependencies(constraints): # then we take the loose match (which _is_ flexible) and start moving backwards in # versions by popping them off of a stack and checking for the conflicting package for _, ireqs in full_groupby(constraints, key=key_from_ireq): - ireqs = list(ireqs) - editable_ireq = first(ireqs, key=lambda ireq: ireq.editable) + ireqs = sorted(ireqs, key=lambda ireq: ireq.editable) + editable_ireq = next(iter(ireq for ireq in ireqs if ireq.editable), None) if editable_ireq: - yield editable_ireq # ignore all the other specs: the editable one is the one that counts + yield editable_ireq # only the editable match mattters, ignore all others continue ireqs = iter(ireqs) # deepcopy the accumulator so as to not modify the self.our_constraints invariant diff --git a/src/requirementslib/models/markers.py b/src/requirementslib/models/markers.py index c7649b77..e22ab976 100644 --- a/src/requirementslib/models/markers.py +++ b/src/requirementslib/models/markers.py @@ -11,9 +11,9 @@ from vistir.compat import Mapping, Set, lru_cache from vistir.misc import dedup -from .utils import filter_none, validate_markers from ..environment import MYPY_RUNNING from ..exceptions import RequirementError +from .utils import filter_none, validate_markers from six.moves import reduce # isort:skip @@ -24,7 +24,8 @@ STRING_TYPE = Union[str, bytes, Text] -MAX_VERSIONS = {2: 7, 3: 10} +MAX_VERSIONS = {2: 7, 3: 11, 4: 0} +DEPRECATED_VERSIONS = ["3.0", "3.1", "3.2", "3.3"] def is_instance(item, cls): @@ -528,34 +529,62 @@ def contains_pyversion(marker): return _markers_contains_pyversion(marker._markers) +def _split_specifierset_str(specset_str, prefix="=="): + # type: (str, str) -> Set[Specifier] + """ + Take a specifierset string and split it into a list to join for specifier sets + + :param str specset_str: A string containing python versions, often comma separated + :param str prefix: A prefix to use when generating the specifier set + :return: A list of :class:`Specifier` instances generated with the provided prefix + :rtype: Set[Specifier] + """ + specifiers = set() + if "," not in specset_str and " " in specset_str: + values = [v.strip() for v in specset_str.split()] + else: + values = [v.strip() for v in specset_str.split(",")] + if prefix == "!=" and any(v in values for v in DEPRECATED_VERSIONS): + values = DEPRECATED_VERSIONS[:] + for value in sorted(values): + specifiers.add(Specifier("{0}{1}".format(prefix, value))) + return specifiers + + +def _get_specifiers_from_markers(marker_item): + """ + Given a marker item, get specifiers from the version marker + + :param :class:`~packaging.markers.Marker` marker_sequence: A marker describing a version constraint + :return: A set of specifiers corresponding to the marker constraint + :rtype: Set[Specifier] + """ + specifiers = set() + if isinstance(marker_item, tuple): + variable, op, value = marker_item + if variable.value != "python_version": + return specifiers + if op.value == "in": + specifiers.update(_split_specifierset_str(value.value, prefix="==")) + elif op.value == "not in": + specifiers.update(_split_specifierset_str(value.value, prefix="!=")) + else: + specifiers.add(Specifier("{0}{1}".format(op.value, value.value))) + elif isinstance(marker_item, list): + parts = get_specset(marker_item) + if parts: + specifiers.update(parts) + return specifiers + + def get_specset(marker_list): # type: (List) -> Optional[SpecifierSet] specset = set() _last_str = "and" for marker_parts in marker_list: - if isinstance(marker_parts, tuple): - variable, op, value = marker_parts - if variable.value != "python_version": - continue - if op.value == "in": - values = [v.strip() for v in value.value.split(",")] - specset.update(Specifier("=={0}".format(v)) for v in values) - elif op.value == "not in": - values = [v.strip() for v in value.value.split(",")] - bad_versions = ["3.0", "3.1", "3.2", "3.3"] - if len(values) >= 2 and any(v in values for v in bad_versions): - values = bad_versions - specset.update( - Specifier("!={0}".format(v.strip())) for v in sorted(bad_versions) - ) - else: - specset.add(Specifier("{0}{1}".format(op.value, value.value))) - elif isinstance(marker_parts, list): - parts = get_specset(marker_parts) - if parts: - specset.update(parts) - elif isinstance(marker_parts, str): - _last_str = marker_parts + specset.update(marker_parts) + if isinstance(marker_parts, str): + _last_str = marker_parts # noqa specifiers = SpecifierSet() specifiers._specs = frozenset(specset) return specifiers diff --git a/src/requirementslib/models/requirements.py b/src/requirementslib/models/requirements.py index 1ec47f7c..0537ca08 100644 --- a/src/requirementslib/models/requirements.py +++ b/src/requirementslib/models/requirements.py @@ -15,7 +15,6 @@ import six import vistir from cached_property import cached_property -from first import first from packaging.markers import Marker from packaging.requirements import Requirement as PackagingRequirement from packaging.specifiers import ( @@ -793,27 +792,25 @@ def wheel_kwargs(self): def get_setup_info(self): # type: () -> SetupInfo - setup_info = SetupInfo.from_ireq(self.ireq) - if not setup_info.name: - setup_info.get_info() + setup_info = None + with pip_shims.shims.global_tempdir_manager(): + setup_info = SetupInfo.from_ireq(self.ireq) + if not setup_info.name: + setup_info.get_info() return setup_info @property def setup_info(self): # type: () -> Optional[SetupInfo] - if self._setup_info is None and not self.is_named and not self.is_wheel: - if self._setup_info: - if not self._setup_info.name: - self._setup_info.get_info() - else: - # make two attempts at this before failing to allow for stale data + if not self._setup_info and not self.is_named and not self.is_wheel: + # make two attempts at this before failing to allow for stale data + try: + self.setup_info = self.get_setup_info() + except FileNotFoundError: try: self.setup_info = self.get_setup_info() except FileNotFoundError: - try: - self.setup_info = self.get_setup_info() - except FileNotFoundError: - raise + raise return self._setup_info @setup_info.setter @@ -890,7 +887,7 @@ def vcsrepo(self, repo): wheel_kwargs = self.wheel_kwargs.copy() wheel_kwargs["src_dir"] = repo.checkout_directory ireq.ensure_has_source_dir(wheel_kwargs["src_dir"]) - with temp_path(): + with pip_shims.shims.global_tempdir_manager(), temp_path(): sys.path = [repo.checkout_directory, "", ".", get_python_lib(plat_specific=0)] setupinfo = SetupInfo.create( repo.checkout_directory, @@ -1065,7 +1062,7 @@ def parse_requirement(self): # type: () -> "Line" if self._name is None: self.parse_name() - if not self._name and not self.is_vcs and not self.is_named: + if not any([self._name, self.is_vcs, self.is_named]): if self.setup_info and self.setup_info.name: self._name = self.setup_info.name name, extras, url = self.requirement_info @@ -1562,16 +1559,18 @@ def setup_info(self): self._parsed_line._setup_info and not self._parsed_line._setup_info.name ): - self._parsed_line._setup_info.get_info() + with pip_shims.shims.global_tempdir_manager(): + self._parsed_line._setup_info.get_info() self._setup_info = self.parsed_line._setup_info elif self.parsed_line and ( self.parsed_line.ireq and not self.parsed_line.is_wheel ): - self._setup_info = SetupInfo.from_ireq(self.parsed_line.ireq) + with pip_shims.shims.global_tempdir_manager(): + self._setup_info = SetupInfo.from_ireq(self.parsed_line.ireq) else: if self.link and not self.link.is_wheel: self._setup_info = Line(self.line_part).setup_info - if self._setup_info: + with pip_shims.shims.global_tempdir_manager(): self._setup_info.get_info() return self._setup_info @@ -1958,20 +1957,23 @@ def vcs_uri(self): def setup_info(self): if self._parsed_line and self._parsed_line.setup_info: if not self._parsed_line.setup_info.name: - self._parsed_line._setup_info.get_info() + with pip_shims.shims.global_tempdir_manager(): + self._parsed_line._setup_info.get_info() return self._parsed_line.setup_info if self._repo: from .setup_info import SetupInfo - self._setup_info = SetupInfo.from_ireq( - Line(self._repo.checkout_directory).ireq - ) - self._setup_info.get_info() + with pip_shims.shims.global_tempdir_manager(): + self._setup_info = SetupInfo.from_ireq( + Line(self._repo.checkout_directory).ireq + ) + self._setup_info.get_info() return self._setup_info ireq = self.parsed_line.ireq from .setup_info import SetupInfo - self._setup_info = SetupInfo.from_ireq(ireq) + with pip_shims.shims.global_tempdir_manager(): + self._setup_info = SetupInfo.from_ireq(ireq) return self._setup_info @setup_info.setter @@ -2275,7 +2277,7 @@ def _choose_vcs_source(pipfile): alt_type = "" # type: Optional[STRING_TYPE] vcs_value = "" # type: STRING_TYPE if src_keys: - chosen_key = first(src_keys) + chosen_key = next(iter(src_keys)) vcs_type = pipfile.pop("vcs") if chosen_key in pipfile: vcs_value = pipfile[chosen_key] @@ -2565,7 +2567,8 @@ def build_backend(self): if self.req is not None and ( not isinstance(self.req, NamedRequirement) and self.req.is_local ): - setup_info = self.run_requires() + with pip_shims.shims.global_tempdir_manager(): + setup_info = self.run_requires() build_backend = setup_info.get("build_backend") return build_backend return "setuptools.build_meta" @@ -2677,7 +2680,7 @@ def from_pipfile(cls, name, pipfile): if hasattr(pipfile, "keys"): _pipfile = dict(pipfile).copy() _pipfile["version"] = get_version(pipfile) - vcs = first([vcs for vcs in VCS_LIST if vcs in _pipfile]) + vcs = next(iter([vcs for vcs in VCS_LIST if vcs in _pipfile]), None) if vcs: _pipfile["vcs"] = vcs r = VCSRequirement.from_pipfile(name, pipfile) @@ -2959,10 +2962,11 @@ def run_requires(self, sources=None, finder=None): from .dependencies import get_finder finder = get_finder(sources=sources) - info = SetupInfo.from_requirement(self, finder=finder) - if info is None: - return {} - info_dict = info.get_info() + with pip_shims.shims.global_tempdir_manager(): + info = SetupInfo.from_requirement(self, finder=finder) + if info is None: + return {} + info_dict = info.get_info() if self.req and not self.req.setup_info: self.req._setup_info = info if self.req._has_hashed_name and info_dict.get("name"): diff --git a/src/requirementslib/models/setup_info.py b/src/requirementslib/models/setup_info.py index 47846e5b..da7078c6 100644 --- a/src/requirementslib/models/setup_info.py +++ b/src/requirementslib/models/setup_info.py @@ -47,6 +47,10 @@ import distutils from distutils.core import Distribution +try: + from contextlib import ExitStack +except ImportError: + from contextlib2 import ExitStack try: from os import scandir diff --git a/src/requirementslib/models/utils.py b/src/requirementslib/models/utils.py index 5d470864..9b6beb64 100644 --- a/src/requirementslib/models/utils.py +++ b/src/requirementslib/models/utils.py @@ -12,7 +12,6 @@ import six import tomlkit from attr import validators -from first import first from packaging.markers import InvalidMarker, Marker, Op, Value, Variable from packaging.specifiers import InvalidSpecifier, Specifier, SpecifierSet from packaging.version import parse as parse_version @@ -103,6 +102,11 @@ def filter_none(k, v): return False +def filter_dict(dict_): + # type: (Dict[AnyStr, Any]) -> Dict[AnyStr, Any] + return {k: v for k, v in dict_.items() if filter_none(k, v)} + + def optional_instance_of(cls): # type: (Any) -> _ValidatorType[Optional[_T]] return validators.optional(validators.instance_of(cls)) @@ -548,8 +552,9 @@ def split_vcs_method_from_uri(uri): # type: (AnyStr) -> Tuple[Optional[STRING_TYPE], STRING_TYPE] """Split a vcs+uri formatted uri into (vcs, uri)""" vcs_start = "{0}+" - vcs = None # type: Optional[STRING_TYPE] - vcs = first([vcs for vcs in VCS_LIST if uri.startswith(vcs_start.format(vcs))]) + vcs = next( + iter([vcs for vcs in VCS_LIST if uri.startswith(vcs_start.format(vcs))]), None + ) if vcs: vcs, uri = uri.split("+", 1) return vcs, uri @@ -766,7 +771,7 @@ def as_tuple(ireq): raise TypeError("Expected a pinned InstallRequirement, got {}".format(ireq)) name = key_from_req(ireq.req) - version = first(ireq.specifier._specs)._spec[1] + version = next(iter(ireq.specifier._specs))._spec[1] extras = tuple(sorted(ireq.extras)) return name, version, extras @@ -906,7 +911,7 @@ def version_from_ireq(ireq): :rtype: str """ - return first(ireq.specifier._specs).version + return next(iter(ireq.specifier._specs)).version def _get_requires_python(candidate): diff --git a/tests/unit/test_requirements.py b/tests/unit/test_requirements.py index ec178d78..04338f9d 100644 --- a/tests/unit/test_requirements.py +++ b/tests/unit/test_requirements.py @@ -3,7 +3,6 @@ import pip_shims.shims import pytest -from first import first from hypothesis import given, settings, strategies as st from vistir.compat import Path @@ -212,7 +211,7 @@ def test_convert_from_pip(monkeypatch, expected, requirement): m.setattr(SetupInfo, "get_info", mock_run_requires) m.setattr(Line, "get_setup_info", mock_run_requires) m.setattr(pip_shims.shims, "unpack_url", mock_unpack) - pkg_name = first(expected.keys()) + pkg_name = next(iter(expected.keys())) pkg_pipfile = expected[pkg_name] line = Line(requirement) if ( @@ -236,7 +235,7 @@ def test_convert_from_pipfile(monkeypatch, requirement, expected): m.setattr(pip_shims.shims, "unpack_url", mock_unpack) m.setattr(SetupInfo, "get_info", mock_run_requires) m.setattr(Requirement, "run_requires", mock_run_requires) - pkg_name = first(requirement.keys()) + pkg_name = next(iter(requirement.keys())) pkg_pipfile = requirement[pkg_name] req = Requirement.from_pipfile(pkg_name, pkg_pipfile) if " (" in expected and expected.endswith(")"): @@ -283,7 +282,7 @@ def test_convert_non_installable_dir_fail(pathlib_tmpdir): def test_one_way_editable_extras(): dep = "-e .[socks]" dep = Requirement.from_line(dep).as_pipfile() - k = first(dep.keys()) + k = next(iter(dep.keys())) assert dep[k]["extras"] == ["socks"] @@ -438,10 +437,7 @@ def test_pep_508(): "tablib@ https://codeload.github.com/kennethreitz/tablib/zip/v0.12.1" ) assert r.specifiers == "==0.12.1" - assert ( - r.req.link.url - == "https://codeload.github.com/kennethreitz/tablib/zip/v0.12.1" - ) + assert r.req.link.url == "https://codeload.github.com/kennethreitz/tablib/zip/v0.12.1" assert r.req.req.name == "tablib" assert r.req.req.url == "https://codeload.github.com/kennethreitz/tablib/zip/v0.12.1" requires, setup_requires, build_requires = r.req.dependencies From 4e89dd1905cfd975f4e8e2a3be0f01428fb33aff Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Fri, 21 Feb 2020 19:09:34 -0500 Subject: [PATCH 2/9] Limit marker complexity a bit - Fix bugs related to previous marker complexity reduction Signed-off-by: Dan Ryan --- src/requirementslib/models/dependencies.py | 90 +++------------------- src/requirementslib/models/markers.py | 14 ++-- tests/unit/test_markers.py | 2 +- 3 files changed, 18 insertions(+), 88 deletions(-) diff --git a/src/requirementslib/models/dependencies.py b/src/requirementslib/models/dependencies.py index 7a0a6d9f..78c78ace 100644 --- a/src/requirementslib/models/dependencies.py +++ b/src/requirementslib/models/dependencies.py @@ -19,6 +19,7 @@ from ..environment import MYPY_RUNNING from ..utils import _ensure_dir, prepare_pip_source_args from .cache import CACHE_DIR, DependencyCache +from .setup_info import SetupInfo from .utils import ( clean_requires_python, fix_requires_python_marker, @@ -479,90 +480,19 @@ def get_dependencies_from_index(dep, sources=None, pip_options=None, wheel_cache if not wheel_cache: wheel_cache = WHEEL_CACHE dep.is_direct = True - reqset = pip_shims.shims.RequirementSet() - reqset.add_requirement(dep) requirements = None setup_requires = {} - with temp_environ(), start_resolver( - finder=finder, session=session, wheel_cache=wheel_cache - ) as resolver: + with temp_environ(): os.environ["PIP_EXISTS_ACTION"] = "i" - dist = None if dep.editable and not dep.prepared and not dep.req: - with cd(dep.setup_py_dir): - from setuptools.dist import distutils - - try: - dist = distutils.core.run_setup(dep.setup_py) - except (ImportError, TypeError, AttributeError): - dist = None - else: - setup_requires[dist.get_name()] = dist.setup_requires - if not dist: - try: - dist = dep.get_dist() - except (TypeError, ValueError, AttributeError): - pass - else: - setup_requires[dist.get_name()] = dist.setup_requires - resolver.require_hashes = False - try: - results = resolver._resolve_one(reqset, dep) - except Exception: - # FIXME: Needs to bubble the exception somehow to the user. - results = [] - finally: - try: - wheel_cache.cleanup() - except AttributeError: - pass - resolver_requires_python = getattr(resolver, "requires_python", None) - requires_python = getattr(reqset, "requires_python", resolver_requires_python) - if requires_python: - add_marker = fix_requires_python_marker(requires_python) - reqset.remove(dep) - if dep.req.marker: - dep.req.marker._markers.extend(["and"].extend(add_marker._markers)) - else: - dep.req.marker = add_marker - reqset.add(dep) - requirements = set() - for r in results: - if requires_python: - if r.req.marker: - r.req.marker._markers.extend(["and"].extend(add_marker._markers)) - else: - r.req.marker = add_marker - requirements.add(format_requirement(r)) - for section in setup_requires: - python_version = section - not_python = not is_python(section) - - # This is for cleaning up :extras: formatted markers - # by adding them to the results of the resolver - # since any such extra would have been returned as a result anyway - for value in setup_requires[section]: - - # This is a marker. - if is_python(section): - python_version = value[1:-1] - else: - not_python = True - - if ":" not in value and not_python: - try: - requirement_str = "{0}{1}".format(value, python_version).replace( - ":", ";" - ) - requirements.add( - format_requirement( - make_install_requirement(requirement_str).ireq - ) - ) - # Anything could go wrong here -- can't be too careful. - except Exception: - pass - + setup_info = SetupInfo.from_ireq(dep) + results = setup_info.get_info() + setup_requires.update(results["setup_requires"]) + requirements = set(results["requires"].values()) + else: + results = pip_shims.shims.resolve(dep) + requirements = [v for v in results.values() if v.name != dep.name] + requirements = set([format_requirement(r) for r in requirements]) if not dep.editable and is_pinned_requirement(dep) and requirements is not None: DEPENDENCY_CACHE[dep] = list(requirements) return requirements diff --git a/src/requirementslib/models/markers.py b/src/requirementslib/models/markers.py index e22ab976..8dda0495 100644 --- a/src/requirementslib/models/markers.py +++ b/src/requirementslib/models/markers.py @@ -148,9 +148,8 @@ def _format_pyspec(specifier): version = getattr(specifier, "version", specifier).rstrip() if version and version.endswith("*"): if version.endswith(".*"): - version = version.rstrip(".*") - else: - version = version.rstrip("*") + version = version[:-2] + version = version.rstrip("*") specifier = Specifier("{0}{1}".format(specifier.operator, version)) try: op = REPLACE_RANGES[specifier.operator] @@ -228,10 +227,10 @@ def normalize_specifier_set(specs): return {_format_pyspec(spec) for spec in specs} spec_list = [] for spec in specs.split(","): + spec = spec.strip() if spec.endswith(".*"): - spec = spec.rstrip(".*") - elif spec.endswith("*"): - spec = spec.rstrip("*") + spec = spec[:-2] + spec = spec.rstrip("*") spec_list.append(spec) return normalize_specifier_set(SpecifierSet(",".join(spec_list))) @@ -582,9 +581,10 @@ def get_specset(marker_list): specset = set() _last_str = "and" for marker_parts in marker_list: - specset.update(marker_parts) if isinstance(marker_parts, str): _last_str = marker_parts # noqa + else: + specset.update(_get_specifiers_from_markers(marker_parts)) specifiers = SpecifierSet() specifiers._specs = frozenset(specset) return specifiers diff --git a/tests/unit/test_markers.py b/tests/unit/test_markers.py index 701eabf8..5121ab62 100644 --- a/tests/unit/test_markers.py +++ b/tests/unit/test_markers.py @@ -136,7 +136,7 @@ def test_get_extras(marker, extras): Marker( "os_name == 'posix' and python_version >= '2.7' and python_version not in '3.0.*,3.1.*,3.2.*,3.3.*'" ), - SpecifierSet("!=3.0,!=3.1,!=3.2,!=3.3,>=2.7"), + SpecifierSet("!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"), ), ], ) From d262489eedceab1ca9400ae0a6e8d3aef928f661 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Sat, 7 Mar 2020 22:35:37 -0500 Subject: [PATCH 3/9] Fix binary operator mapping in setup.py ast parser - Fix handling of `ast.binOp` nodes during unmapping of `setup.py` files when parsing -- add mapping for all binary operators and execute translated functions using the unparsed left and right hand sides of the binary operator - Add equivalent handling for `ast.Compare` types - Add `importlib.import_module` attempts to `ast.Compare` evaluations when encountering `ast.Attribute` types on either side of the comparison - Add handling for `ast.IfExp` type to evaluate truth values of the expression and return `node.body` if the expression is `True`, otherwise `node.orelse` - Add equivalence mapping for `ast.Ellipsis` type which becomes `ast.Constant` in python `>= 3.8` - Fixes #204 - Fixes #206 - Fixes #207 Signed-off-by: Dan Ryan --- .pre-commit-config.yaml | 15 ++- news/204.bugfix.rst | 1 + news/206.bugfix.rst | 1 + news/207.bugfix.rst | 1 + src/requirementslib/models/setup_info.py | 132 ++++++++++++++++++----- 5 files changed, 119 insertions(+), 31 deletions(-) create mode 100644 news/204.bugfix.rst create mode 100644 news/206.bugfix.rst create mode 100644 news/207.bugfix.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f579267f..dde3109c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/ambv/black - rev: 19.10b0 + rev: stable hooks: - id: black args: ["--target-version=py27", "--target-version=py37"] @@ -11,11 +11,18 @@ repos: #- id: flake8 - repo: https://github.com/asottile/seed-isort-config - rev: v1.9.3 + rev: v2.1.0 hooks: - id: seed-isort-config + args: [ + --application-directories=src/requirementslib, + --settings-path=./, + # --exclude=tests/.*\.py, + # --exclude=src/requirementslib/models/setup_info.py + ] - - repo: https://github.com/pre-commit/mirrors-isort - rev: v4.3.21 + - repo: https://github.com/timothycrosley/isort + rev: 4.3.21 hooks: - id: isort + diff --git a/news/204.bugfix.rst b/news/204.bugfix.rst new file mode 100644 index 00000000..f20d30bf --- /dev/null +++ b/news/204.bugfix.rst @@ -0,0 +1 @@ +Fixed an issue in binary operator mapping in the ``ast_parse_setup_py`` functionality of the dependency parser which could cause dependency resolution to fail. diff --git a/news/206.bugfix.rst b/news/206.bugfix.rst new file mode 100644 index 00000000..9795814d --- /dev/null +++ b/news/206.bugfix.rst @@ -0,0 +1 @@ +Fixed an issue which caused mappings of binary operators to fail to evaluate when parsing ``setup.py`` files. diff --git a/news/207.bugfix.rst b/news/207.bugfix.rst new file mode 100644 index 00000000..8f2ca993 --- /dev/null +++ b/news/207.bugfix.rst @@ -0,0 +1 @@ +Fixed mapping and evaluation of boolean operators and comparisons when evaluating ``setup.py`` files with AST parser to discover dependencies. diff --git a/src/requirementslib/models/setup_info.py b/src/requirementslib/models/setup_info.py index da7078c6..8bf3496a 100644 --- a/src/requirementslib/models/setup_info.py +++ b/src/requirementslib/models/setup_info.py @@ -6,6 +6,7 @@ import contextlib import importlib import io +import operator import os import shutil import sys @@ -74,6 +75,7 @@ AnyStr, Sequence, ) + import requests from pip_shims.shims import InstallRequirement, PackageFinder from pkg_resources import ( PathMetadata, @@ -285,8 +287,11 @@ def get_extras_from_setupcfg(parser): return extras -def parse_setup_cfg(setup_cfg_contents, base_dir): - # type: (S, S) -> Dict[S, Union[S, None, Set[BaseRequirement], List[S], Dict[STRING_TYPE, Tuple[BaseRequirement]]]] +def parse_setup_cfg( + setup_cfg_contents, # type: S + base_dir, # type: S +): + # type: (...) -> Dict[S, Union[S, None, Set[BaseRequirement], List[S], Dict[STRING_TYPE, Tuple[BaseRequirement]]]] default_opts = { "metadata": {"name": "", "version": ""}, "options": { @@ -637,6 +642,37 @@ def get_metadata_from_dist(dist): } +AST_BINOP_MAP = dict(( + (ast.Add, operator.add), + (ast.Sub, operator.sub), + (ast.Mult, operator.mul), + (ast.Div, operator.floordiv), + (ast.Mod, operator.mod), + (ast.Pow, operator.pow), + (ast.LShift, operator.lshift), + (ast.RShift, operator.rshift), + (ast.BitAnd, operator.and_), + (ast.BitOr, operator.or_), + (ast.BitXor, operator.xor), +)) + + +AST_COMPARATORS = dict(( + (ast.Lt, operator.lt), + (ast.LtE, operator.le), + (ast.Eq, operator.eq), + (ast.Gt, operator.gt), + (ast.GtE, operator.ge), + (ast.NotEq, operator.ne), + (ast.Is, operator.is_), + (ast.IsNot, operator.is_not), + (ast.And, operator.and_), + (ast.Or, operator.or_), + (ast.Not, operator.not_), + (ast.In, operator.contains), +)) + + class Analyzer(ast.NodeVisitor): def __init__(self): self.name_types = [] @@ -661,10 +697,7 @@ def generic_visit(self, node): super(Analyzer, self).generic_visit(node) def visit_BinOp(self, node): - left = ast_unparse(node.left, initial_mapping=True) - right = ast_unparse(node.right, initial_mapping=True) - node.left = left - node.right = right + node = ast_unparse(node, initial_mapping=True) self.binOps.append(node) def unmap_binops(self): @@ -687,6 +720,10 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no unparse = partial( ast_unparse, initial_mapping=initial_mapping, analyzer=analyzer, recurse=recurse ) + if getattr(ast, "Constant", None): + constant = (ast.Constant, ast.Ellipsis) + else: + constant = ast.Ellipsis if isinstance(item, ast.Dict): unparsed = dict(zip(unparse(item.keys), unparse(item.values))) elif isinstance(item, ast.List): @@ -697,28 +734,26 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no unparsed = item.s elif isinstance(item, ast.Subscript): unparsed = unparse(item.value) + elif any(isinstance(item, k) for k in AST_BINOP_MAP.keys()): + unparsed = AST_BINOP_MAP[type(item)] elif isinstance(item, ast.BinOp): if analyzer and item in analyzer.binOps_map: unparsed = analyzer.binOps_map[item] - elif isinstance(item.op, ast.Add): + else: + right_item = unparse(item.right) + left_item = unparse(item.left) + op = getattr(item, "op", None) + op_func = unparse(op) if op is not None else op if not initial_mapping: - right_item = unparse(item.right) - left_item = unparse(item.left) - if not all( - isinstance(side, (six.string_types, int, float, list, tuple)) - for side in (left_item, right_item) - ): - item.left = left_item - item.right = right_item - unparsed = item - else: - unparsed = left_item + right_item + try: + unparsed = op_func(left_item, right_item) + except Exception: + unparsed = (left_item, op_func, right_item) else: + item.left = left_item + item.right = right_item + item.op = op_func unparsed = item - elif isinstance(item.op, ast.Sub): - unparsed = unparse(item.left) - unparse(item.right) - else: - unparsed = item elif isinstance(item, ast.Name): if not initial_mapping: unparsed = item.id @@ -735,6 +770,41 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no unparsed = item elif six.PY3 and isinstance(item, ast.NameConstant): unparsed = item.value + elif any(isinstance(item, k) for k in AST_COMPARATORS.keys()): + unparsed = AST_COMPARATORS[type(item)] + elif isinstance(item, constant): + unparsed = item.value + elif isinstance(item, ast.Compare): + if isinstance(item.left, ast.Attribute): + import importlib + + left = unparse(item.left) + if "." in left: + name, _, val = left.rpartition(".") + left = getattr(importlib.import_module(name), val, left) + comparators = [] + for comparator in item.comparators: + right = unparse(comparator) + if isinstance(comparator, ast.Attribute) and "." in right: + name, _, val = right.rpartition(".") + right = getattr(importlib.import_module(name), val, right) + comparators.append(right) + unparsed = (left, unparse(item.ops), comparators) + elif isinstance(item, ast.IfExp): + if initial_mapping: + unparsed = item + else: + left, ops, right = unparse(item.test) + truth_vals = [] + for i, op in enumerate(ops): + if i == 0: + truth_vals.append(op(left, right[i])) + else: + truth_vals.append(op(right[i - 1], right[i])) + if all(truth_vals): + unparsed = unparse(item.body) + else: + unparsed = unparse(item.orelse) elif isinstance(item, ast.Attribute): attr_name = getattr(item, "value", None) attr_attr = getattr(item, "attr", None) @@ -756,13 +826,21 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no unparsed = name if not unparsed else unparsed elif isinstance(item, ast.Call): unparsed = {} - if isinstance(item.func, ast.Name): + if isinstance(item.func, (ast.Name, ast.Attribute)): func_name = unparse(item.func) - elif isinstance(item.func, ast.Attribute): - func_name = unparse(item.func) - if func_name: + else: + try: + func_name = unparse(item.func) + except Exception: + func_name = None + if isinstance(func_name, dict): + unparsed.update(func_name) + func_name = next(iter(func_name.keys())) + for keyword in getattr(item, "keywords", []): + unparsed[func_name].update(unparse(keyword)) + elif func_name: unparsed[func_name] = {} - for keyword in item.keywords: + for keyword in getattr(item, "keywords", []): unparsed[func_name].update(unparse(keyword)) elif isinstance(item, ast.keyword): unparsed = {unparse(item.arg): unparse(item.value)} From cc9fdfcfd7ba23e41c88d5d0fc1e79f22a06c0e5 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Tue, 10 Mar 2020 17:15:35 -0400 Subject: [PATCH 4/9] Handle AST comparisons which reference functions - Add AST tests Signed-off-by: Dan Ryan --- src/requirementslib/models/setup_info.py | 78 +++++++++++++----------- tests/unit/test_setup_info.py | 17 ++++++ 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/requirementslib/models/setup_info.py b/src/requirementslib/models/setup_info.py index 8bf3496a..96d07fb0 100644 --- a/src/requirementslib/models/setup_info.py +++ b/src/requirementslib/models/setup_info.py @@ -642,35 +642,39 @@ def get_metadata_from_dist(dist): } -AST_BINOP_MAP = dict(( - (ast.Add, operator.add), - (ast.Sub, operator.sub), - (ast.Mult, operator.mul), - (ast.Div, operator.floordiv), - (ast.Mod, operator.mod), - (ast.Pow, operator.pow), - (ast.LShift, operator.lshift), - (ast.RShift, operator.rshift), - (ast.BitAnd, operator.and_), - (ast.BitOr, operator.or_), - (ast.BitXor, operator.xor), -)) - - -AST_COMPARATORS = dict(( - (ast.Lt, operator.lt), - (ast.LtE, operator.le), - (ast.Eq, operator.eq), - (ast.Gt, operator.gt), - (ast.GtE, operator.ge), - (ast.NotEq, operator.ne), - (ast.Is, operator.is_), - (ast.IsNot, operator.is_not), - (ast.And, operator.and_), - (ast.Or, operator.or_), - (ast.Not, operator.not_), - (ast.In, operator.contains), -)) +AST_BINOP_MAP = dict( + ( + (ast.Add, operator.add), + (ast.Sub, operator.sub), + (ast.Mult, operator.mul), + (ast.Div, operator.floordiv), + (ast.Mod, operator.mod), + (ast.Pow, operator.pow), + (ast.LShift, operator.lshift), + (ast.RShift, operator.rshift), + (ast.BitAnd, operator.and_), + (ast.BitOr, operator.or_), + (ast.BitXor, operator.xor), + ) +) + + +AST_COMPARATORS = dict( + ( + (ast.Lt, operator.lt), + (ast.LtE, operator.le), + (ast.Eq, operator.eq), + (ast.Gt, operator.gt), + (ast.GtE, operator.ge), + (ast.NotEq, operator.ne), + (ast.Is, operator.is_), + (ast.IsNot, operator.is_not), + (ast.And, operator.and_), + (ast.Or, operator.or_), + (ast.Not, operator.not_), + (ast.In, operator.contains), + ) +) class Analyzer(ast.NodeVisitor): @@ -724,6 +728,7 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no constant = (ast.Constant, ast.Ellipsis) else: constant = ast.Ellipsis + unparsed = item if isinstance(item, ast.Dict): unparsed = dict(zip(unparse(item.keys), unparse(item.values))) elif isinstance(item, ast.List): @@ -789,13 +794,20 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no name, _, val = right.rpartition(".") right = getattr(importlib.import_module(name), val, right) comparators.append(right) - unparsed = (left, unparse(item.ops), comparators) + unparsed = (left, unparse(item.ops), comparators) elif isinstance(item, ast.IfExp): if initial_mapping: unparsed = item else: - left, ops, right = unparse(item.test) - truth_vals = [] + ops, truth_vals = [], [] + if isinstance(item.test, ast.Compare): + left, ops, right = unparse(item.test) + else: + result = ast_unparse(item.test) + if isinstance(result, dict): + k, v = result.popitem() + if not v: + truth_vals = [False] for i, op in enumerate(ops): if i == 0: truth_vals.append(op(left, right[i])) @@ -869,8 +881,6 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no unparsed = type(item)([unparse(el) for el in item]) elif isinstance(item, six.string_types): unparsed = item - else: - return item return unparsed diff --git a/tests/unit/test_setup_info.py b/tests/unit/test_setup_info.py index 1878d779..565cb2a4 100644 --- a/tests/unit/test_setup_info.py +++ b/tests/unit/test_setup_info.py @@ -211,6 +211,23 @@ def test_ast_parser_finds_fully_qualified_setup(setup_py_dir): assert parsed[k] == v, parsed[k] +def test_ast_parser_handles_binops(setup_py_dir): + parsed = ast_parse_setup_py( + setup_py_dir.joinpath( + "package_with_conditional_install_requires/setup.py" + ).as_posix() + ) + expected = [ + "azure-common>=1.1.5", + "cryptography", + "python-dateutil", + "requests", + ] + if six.PY2: + expected.append("futures") + assert list(sorted(parsed["install_requires"])) == list(sorted(expected)) + + def test_setup_cfg_parser(setup_cfg_dir): setup_path = setup_cfg_dir / "package_with_multiple_extras/setup.cfg" if six.PY2: From 7d401d2d82b59cc2098701fc338d136285662808 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 11 Mar 2020 11:31:08 -0400 Subject: [PATCH 5/9] Add missing conditional install requires test Signed-off-by: Dan Ryan --- .../README.rst | 1 + .../setup.py | 61 +++++++++++++++++++ .../src/fakepkg/__init__.py | 0 3 files changed, 62 insertions(+) create mode 100644 tests/fixtures/setup_py/package_with_conditional_install_requires/README.rst create mode 100644 tests/fixtures/setup_py/package_with_conditional_install_requires/setup.py create mode 100644 tests/fixtures/setup_py/package_with_conditional_install_requires/src/fakepkg/__init__.py diff --git a/tests/fixtures/setup_py/package_with_conditional_install_requires/README.rst b/tests/fixtures/setup_py/package_with_conditional_install_requires/README.rst new file mode 100644 index 00000000..e652f900 --- /dev/null +++ b/tests/fixtures/setup_py/package_with_conditional_install_requires/README.rst @@ -0,0 +1 @@ +This file is fake diff --git a/tests/fixtures/setup_py/package_with_conditional_install_requires/setup.py b/tests/fixtures/setup_py/package_with_conditional_install_requires/setup.py new file mode 100644 index 00000000..77a26da6 --- /dev/null +++ b/tests/fixtures/setup_py/package_with_conditional_install_requires/setup.py @@ -0,0 +1,61 @@ +import sys + +from setuptools import setup + +try: + from non_existant_pkg import cmdclass +except ImportError: + from distutils import log as logger + + logger.warn("Wheel is not available, disabling bdist_wheel hook") + cmdclass = {} + +try: + import incompatible_pkg + + try: + ver = incompatible_pkg.__version__ + raise Exception( + "This package is incompatible with incompatible_pkg=={}. ".format(ver) + + 'Uninstall it with "pip uninstall azure".' + ) + except AttributeError: + pass +except ImportError: + pass + +setup( + name="fakepkg", + version="0.1.0", + description="Fake package", + long_description=open("README.rst", "r").read(), + license="MIT", + author="Fake Author", + author_email="Fake@fake.com", + url="https://github.com/fake/fakepackage", + classifiers=[ + "Development Status :: 4 - Beta", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "License :: OSI Approved :: MIT License", + ], + zip_safe=True, + package_dir={"": "src"}, + packages=["fakepkg"], + install_requires=[ + "azure-common>=1.1.5", + "cryptography", + "python-dateutil", + "requests", + ] + + (["futures"] if sys.version_info < (3, 0) else []), + cmdclass=cmdclass, +) diff --git a/tests/fixtures/setup_py/package_with_conditional_install_requires/src/fakepkg/__init__.py b/tests/fixtures/setup_py/package_with_conditional_install_requires/src/fakepkg/__init__.py new file mode 100644 index 00000000..e69de29b From 6834dbae9e1364c8915fa2a02c957eb18774d640 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 11 Mar 2020 12:01:17 -0400 Subject: [PATCH 6/9] Re-lock with correct dependencies Signed-off-by: Dan Ryan --- Pipfile.lock | 155 ++++++++++++++++++++++----------------------------- 1 file changed, 68 insertions(+), 87 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 56ba0858..69e30bb1 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -97,15 +97,23 @@ "sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", "sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80" ], - "markers": "python_version < '3.3'", + "markers": "python_version == '2.7'", "version": "==1.0.0" }, + "backports.tempfile": { + "hashes": [ + "sha256:05aa50940946f05759696156a8c39be118169a0e0f94a49d0bb106503891ff54", + "sha256:1c648c452e8770d759bdc5a5e2431209be70d25484e1be24876cf2168722c762" + ], + "markers": "python_version < '3.5'", + "version": "==1.0" + }, "backports.weakref": { "hashes": [ "sha256:81bc9b51c0abc58edc76aefbbc68c62a787918ffe943a37947e162c3f8e19e82", "sha256:bc4170a29915f8b22c9e7c4939701859650f2eb84184aee80da329ac0b9825c2" ], - "markers": "python_version < '3.3'", + "markers": "python_version == '2.7'", "version": "==1.0.post1" }, "black": { @@ -334,6 +342,12 @@ ], "version": "==0.3.0" }, + "docopt": { + "hashes": [ + "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" + ], + "version": "==0.6.2" + }, "docutils": { "hashes": [ "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", @@ -352,13 +366,12 @@ }, "enum34": { "hashes": [ - "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", - "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", - "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", - "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1" + "sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53", + "sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328", + "sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248" ], "markers": "python_version < '3.4'", - "version": "==1.1.6" + "version": "==1.1.10" }, "execnet": { "hashes": [ @@ -392,11 +405,11 @@ }, "flake8-bugbear": { "hashes": [ - "sha256:a3ddc03ec28ba2296fc6f89444d1c946a6b76460f859795b35b77d4920a51b63", - "sha256:bd02e4b009fb153fe6072c31c52aeab5b133d508095befb2ffcf3b41c4823162" + "sha256:d8c466ea79d5020cb20bf9f11cf349026e09517a42264f313d3f6fddb83e0571", + "sha256:ded4d282778969b5ab5530ceba7aa1a9f1b86fa7618fc96a19a1d512331640f8" ], - "markers": "python_version > '3.5'", - "version": "==20.1.4" + "markers": "python_version >= '3.5'", + "version": "==19.8.0" }, "funcsigs": { "hashes": [ @@ -424,11 +437,11 @@ }, "hypothesis": { "hashes": [ - "sha256:3870b151a25a36d94d1c9174404b506b1165e507904ec8a9ec049cca51329008", - "sha256:693fe3f72a4bbb67529c1873c1350c3eb0c028c323611dce9e7f3c341ddafbb1" + "sha256:3c4369a4b0a1348561048bcda5f1db951a1b8e2a514ea8e8c70d36e656bf6fa0", + "sha256:94f0910bc87e0ae8c098f4ada28dfdc381245e0c8079c674292b417dbde144b5" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==4.50.7" + "version": "==4.57.1" }, "identify": { "hashes": [ @@ -454,28 +467,21 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.2.0" }, - "importlab": { - "hashes": [ - "sha256:d855350d19dc10a17aabd2fe6f4b428ff1a936071f692fbf686a73694d26a51c" - ], - "markers": "python_version >= '2.7.0'", - "version": "==0.5.1" - }, "importlib-metadata": { "hashes": [ - "sha256:3a8b2dfd0a2c6a3636e7c016a7e54ae04b997d30e69d5eacdca7a6c2221a1402", - "sha256:41e688146d000891f32b1669e8573c57e39e5060e7f5f647aa617cd9a9568278" + "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302", + "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b" ], "markers": "python_version < '3.8'", - "version": "==1.2.0" + "version": "==1.5.0" }, "importlib-resources": { "hashes": [ - "sha256:6e2783b2538bd5a14678284a3962b0660c715e5a0f10243fd5e00a4b5974f50b", - "sha256:d3279fd0f6f847cced9f7acc19bd3e5df54d34f93a2e7bb5f238f81545787078" + "sha256:1dff36d42d94bd523eeb847c25c7dd327cb56686d74a26dfcc8d67c504922d59", + "sha256:7f0e1b2b5f3981e39c52da0f99b2955353c5a139c314994d1126c2551ace9bdf" ], "markers": "python_version < '3.7'", - "version": "==1.0.2" + "version": "==1.3.1" }, "incremental": { "hashes": [ @@ -513,7 +519,7 @@ "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e", "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf" ], - "markers": "sys_platform == 'linux'", + "markers": "python_version >= '3.6' and sys_platform == 'linux'", "version": "==0.4.3" }, "jinja2": { @@ -637,23 +643,23 @@ }, "mypy": { "hashes": [ - "sha256:0a9a45157e532da06fe56adcfef8a74629566b607fa2c1ac0122d1ff995c748a", - "sha256:2c35cae79ceb20d47facfad51f952df16c2ae9f45db6cb38405a3da1cf8fc0a7", - "sha256:4b9365ade157794cef9685791032521233729cb00ce76b0ddc78749abea463d2", - "sha256:53ea810ae3f83f9c9b452582261ea859828a9ed666f2e1ca840300b69322c474", - "sha256:634aef60b4ff0f650d3e59d4374626ca6153fcaff96ec075b215b568e6ee3cb0", - "sha256:7e396ce53cacd5596ff6d191b47ab0ea18f8e0ec04e15d69728d530e86d4c217", - "sha256:7eadc91af8270455e0d73565b8964da1642fe226665dd5c9560067cd64d56749", - "sha256:7f672d02fffcbace4db2b05369142e0506cdcde20cea0e07c7c2171c4fd11dd6", - "sha256:85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf", - "sha256:87c556fb85d709dacd4b4cb6167eecc5bbb4f0a9864b69136a0d4640fdc76a36", - "sha256:a6bd44efee4dc8c3324c13785a9dc3519b3ee3a92cada42d2b57762b7053b49b", - "sha256:c6d27bd20c3ba60d5b02f20bd28e20091d6286a699174dfad515636cb09b5a72", - "sha256:e2bb577d10d09a2d8822a042a23b8d62bc3b269667c9eb8e60a6edfa000211b1", - "sha256:f97a605d7c8bc2c6d1172c2f0d5a65b24142e11a58de689046e62c2d632ca8c1" + "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" ], "markers": "python_version >= '3.4'", - "version": "==0.761" + "version": "==0.770" }, "mypy-extensions": { "hashes": [ @@ -692,6 +698,7 @@ "sha256:db31cef1eb979e4fe4539046cf04311e00f271f8687bde7dfb64d85f4e4d2b1e", "sha256:fd72664f0e2506f2c8002f2ee67ddd50b87604fe8c1bd04d2108dfeacc82420d" ], + "markers": "python_version >= '3.6'", "version": "==1.9.0.post1" }, "nodeenv": { @@ -736,7 +743,7 @@ "sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db", "sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868" ], - "markers": "python_version < '3'", + "markers": "python_version < '3.6'", "version": "==2.3.5" }, "pathspec": { @@ -761,8 +768,8 @@ }, "pip-shims": { "hashes": [ - "sha256:5861da6f48e60b55d40b984795c63681e4db7ac576c1c3b05f4b54a9d508e3da", - "sha256:2b9a88ff0fd31e7d27a362d3e36e6e75d8fbc339c9c4367f4a97b72b22e6f4f4" + "sha256:2b9a88ff0fd31e7d27a362d3e36e6e75d8fbc339c9c4367f4a97b72b22e6f4f4", + "sha256:5861da6f48e60b55d40b984795c63681e4db7ac576c1c3b05f4b54a9d508e3da" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.5.1" @@ -795,11 +802,11 @@ }, "pre-commit": { "hashes": [ - "sha256:09ebe467f43ce24377f8c2f200fe3cd2570d328eb2ce0568c8e96ce19da45fa6", - "sha256:f8d555e31e2051892c7f7b3ad9f620bd2c09271d87e9eedb2ad831737d6211eb" + "sha256:8f48d8637bdae6fa70cc97db9c1dd5aa7c5c8bf71968932a380628c25978b850", + "sha256:f92a359477f3252452ae2e8d3029de77aec59415c16ae4189bcfba40b757e029" ], - "markers": "python_version >= '3.6'", - "version": "==2.1.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.21.0" }, "prompt-toolkit": { "hashes": [ @@ -867,11 +874,11 @@ }, "pytest": { "hashes": [ - "sha256:5d0d20a9a66e39b5845ab14f8989f3463a7aa973700e6cdf02db69da9821e738", - "sha256:692d9351353ef709c1126266579edd4fd469dcf6b5f4f583050f72161d6f3592" + "sha256:19e8f75eac01dd3f211edd465b39efbcbdc8fc5f7866d7dd49fedb30d8adf339", + "sha256:c77a5f30a90e0ce24db9eaa14ddfd38d4afb5ea159309bdd2dae55b931bc9324" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==4.6.6" + "version": "==4.6.9" }, "pytest-cov": { "hashes": [ @@ -914,10 +921,10 @@ }, "pytype": { "hashes": [ - "sha256:53803f0f1fadf4923efc88a0bd0cfa4c242d2fa3f04421b6f8ab4d658ffd2b90" + "sha256:b22aaf5dd125134cad2cb3f45231c2fd4aa158b129bff81f880a0c6d6bb3c2a8" ], - "markers": "python_version >= '3.6'", - "version": "==2020.2.6" + "markers": "python_version >= '3.4' and python_version < '3.8'", + "version": "==2020.2.20" }, "pytz": { "hashes": [ @@ -952,32 +959,6 @@ ], "version": "==24.0" }, - "regex": { - "hashes": [ - "sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431", - "sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242", - "sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1", - "sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d", - "sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045", - "sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b", - "sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400", - "sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa", - "sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0", - "sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69", - "sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74", - "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb", - "sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26", - "sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5", - "sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2", - "sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce", - "sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab", - "sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e", - "sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70", - "sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc", - "sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0" - ], - "version": "==2020.2.20" - }, "requests": { "hashes": [ "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", @@ -1040,7 +1021,7 @@ "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6", "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b" ], - "markers": "sys_platform == 'linux'", + "markers": "python_version >= '3.6' and sys_platform == 'linux'", "version": "==3.1.2" }, "six": { @@ -1241,11 +1222,11 @@ }, "zipp": { "hashes": [ - "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", - "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1", + "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921" ], - "markers": "python_version >= '2.7'", - "version": "==0.6.0" + "markers": "python_version < '3.8'", + "version": "==1.2.0" } } } From 029c430c44b68adef0ea1d34700ed365983a5049 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 11 Mar 2020 14:49:21 -0400 Subject: [PATCH 7/9] Fix pytest-cov execution Signed-off-by: Dan Ryan --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index aed17f8e..4582044c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -103,7 +103,7 @@ universal = 1 [tool:pytest] strict = true plugins = flake8 cov timeout -addopts = -ra --cov -n auto --timeout 300 +addopts = -ra --cov=requirementslib -n auto --timeout 300 testpaths = tests/ norecursedirs = .* build dist news tasks docs tests/artifacts flake8-ignore = From 0242ea710cdaea1df78d8e25094d50856ded5af6 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 11 Mar 2020 18:41:44 -0400 Subject: [PATCH 8/9] Fix test runner and AST parser on python3.5-3.7 Signed-off-by: Dan Ryan --- setup.cfg | 2 +- src/requirementslib/models/setup_info.py | 2 ++ tests/conftest.py | 9 ++++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index 4582044c..c2f85518 100644 --- a/setup.cfg +++ b/setup.cfg @@ -102,7 +102,7 @@ universal = 1 [tool:pytest] strict = true -plugins = flake8 cov timeout +plugins = flake8 cov xdist timeout addopts = -ra --cov=requirementslib -n auto --timeout 300 testpaths = tests/ norecursedirs = .* build dist news tasks docs tests/artifacts diff --git a/src/requirementslib/models/setup_info.py b/src/requirementslib/models/setup_info.py index 96d07fb0..4ccff88c 100644 --- a/src/requirementslib/models/setup_info.py +++ b/src/requirementslib/models/setup_info.py @@ -741,6 +741,8 @@ def ast_unparse(item, initial_mapping=False, analyzer=None, recurse=True): # no unparsed = unparse(item.value) elif any(isinstance(item, k) for k in AST_BINOP_MAP.keys()): unparsed = AST_BINOP_MAP[type(item)] + elif isinstance(item, ast.Num): + unparsed = item.n elif isinstance(item, ast.BinOp): if analyzer and item in analyzer.binOps_map: unparsed = analyzer.binOps_map[item] diff --git a/tests/conftest.py b/tests/conftest.py index dadc6142..0ad56c1d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,9 +10,6 @@ import requests import vistir -import requirementslib.utils -from requirementslib.models.setup_info import SetupInfo - CURRENT_FILE = vistir.compat.Path(__file__).absolute() @@ -107,6 +104,8 @@ def finalize(): @pytest.fixture(autouse=True) def monkeypatch_if_needed(monkeypatch): + from requirementslib.models.setup_info import SetupInfo + with monkeypatch.context() as m: if SKIP_INTERNET: m.setattr(pip_shims.shims, "unpack_url", mock_unpack) @@ -116,6 +115,8 @@ def monkeypatch_if_needed(monkeypatch): @pytest.fixture(scope="session") def artifact_dir(): + import requirementslib.utils + return ( vistir.compat.Path(requirementslib.utils.__file__) .absolute() @@ -145,6 +146,8 @@ def pipfile_dir(fixture_dir): @pytest.fixture def test_artifact(artifact_dir, pathlib_tmpdir, request): + import requirementslib.utils + name = request.param["name"] as_artifact = request.param.get("as_artifact", False) target = artifact_dir.joinpath(name) From 14292e97bfa7e4e9f0f352832d11617915d5670c Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 11 Mar 2020 18:45:17 -0400 Subject: [PATCH 9/9] Update pipeline build file Signed-off-by: Dan Ryan --- azure-pipelines.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e7bb7464..3b01a0c9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,7 +43,7 @@ jobs: - job: TestWindows pool: - vmImage: windows-2019 + vmImage: windows-latest strategy: matrix: Python27: @@ -54,13 +54,15 @@ jobs: python.version: '3.6' Python37: python.version: '3.7' + Python38: + python.version: '3.8' maxParallel: 4 steps: - template: .azure-pipelines/templates/run-tests.yml - job: TestMacOS pool: - vmImage: macOS-10.13 + vmImage: macOS-latest strategy: matrix: Python27: @@ -71,6 +73,8 @@ jobs: python.version: '3.6' Python37: python.version: '3.7' + Python38: + python.version: '3.8' maxParallel: 4 steps: - template: .azure-pipelines/templates/run-tests.yml