Created
October 31, 2021 12:52
-
-
Save awilkins/286220b87a49899aa03f7286912fce4e to your computer and use it in GitHub Desktop.
Install poetry 1.1.11 with the depdencies locked at tag time.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This script will install Poetry and its dependencies. | |
It does, in order: | |
- Downloads the virtualenv package to a temporary directory and add it to sys.path. | |
- Creates a virtual environment in the correct OS data dir which will be | |
- `%APPDATA%\\pypoetry` on Windows | |
- ~/Library/Application Support/pypoetry on MacOS | |
- `${XDG_DATA_HOME}/pypoetry` (or `~/.local/share/pypoetry` if it's not set) on UNIX systems | |
- In `${POETRY_HOME}` if it's set. | |
- Installs the latest or given version of Poetry inside this virtual environment. | |
- Installs a `poetry` script in the Python user directory (or `${POETRY_HOME/bin}` if `POETRY_HOME` is set). | |
""" | |
import argparse | |
import json | |
import os | |
import re | |
import shutil | |
import site | |
import subprocess | |
import sys | |
import tempfile | |
from contextlib import closing | |
from contextlib import contextmanager | |
from functools import cmp_to_key | |
from io import UnsupportedOperation | |
from pathlib import Path | |
from typing import Optional | |
from urllib.request import Request | |
from urllib.request import urlopen | |
SHELL = os.getenv("SHELL", "") | |
WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt") | |
MACOS = sys.platform == "darwin" | |
FOREGROUND_COLORS = { | |
"black": 30, | |
"red": 31, | |
"green": 32, | |
"yellow": 33, | |
"blue": 34, | |
"magenta": 35, | |
"cyan": 36, | |
"white": 37, | |
} | |
BACKGROUND_COLORS = { | |
"black": 40, | |
"red": 41, | |
"green": 42, | |
"yellow": 43, | |
"blue": 44, | |
"magenta": 45, | |
"cyan": 46, | |
"white": 47, | |
} | |
OPTIONS = {"bold": 1, "underscore": 4, "blink": 5, "reverse": 7, "conceal": 8} | |
VERSIONS = { | |
"1.1.11": """ | |
backports.entry-points-selectable==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "2.7" \\ | |
--hash=sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc \\ | |
--hash=sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a | |
cachecontrol[filecache]==0.12.6; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \\ | |
--hash=sha256:10d056fa27f8563a271b345207402a6dcce8efab7e5b377e270329c62471b10d \\ | |
--hash=sha256:be9aa45477a134aee56c8fac518627e1154df063e85f67d4f83ce0ccc23688e8 | |
cachy==0.3.0; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \\ | |
--hash=sha256:338ca09c8860e76b275aff52374330efedc4d5a5e45dc1c5b539c1ead0786fe7 \\ | |
--hash=sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1 | |
certifi==2021.5.30; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" \\ | |
--hash=sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8 \\ | |
--hash=sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee | |
cffi==1.14.6 \\ | |
--hash=sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c \\ | |
--hash=sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99 \\ | |
--hash=sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819 \\ | |
--hash=sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20 \\ | |
--hash=sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224 \\ | |
--hash=sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7 \\ | |
--hash=sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33 \\ | |
--hash=sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534 \\ | |
--hash=sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a \\ | |
--hash=sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5 \\ | |
--hash=sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca \\ | |
--hash=sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218 \\ | |
--hash=sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f \\ | |
--hash=sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872 \\ | |
--hash=sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195 \\ | |
--hash=sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d \\ | |
--hash=sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b \\ | |
--hash=sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb \\ | |
--hash=sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a \\ | |
--hash=sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e \\ | |
--hash=sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5 \\ | |
--hash=sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf \\ | |
--hash=sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69 \\ | |
--hash=sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56 \\ | |
--hash=sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c \\ | |
--hash=sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762 \\ | |
--hash=sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771 \\ | |
--hash=sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a \\ | |
--hash=sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0 \\ | |
--hash=sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e \\ | |
--hash=sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346 \\ | |
--hash=sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc \\ | |
--hash=sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd \\ | |
--hash=sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc \\ | |
--hash=sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548 \\ | |
--hash=sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156 \\ | |
--hash=sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d \\ | |
--hash=sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e \\ | |
--hash=sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c \\ | |
--hash=sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202 \\ | |
--hash=sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f \\ | |
--hash=sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87 \\ | |
--hash=sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728 \\ | |
--hash=sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2 \\ | |
--hash=sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd | |
chardet==4.0.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" \\ | |
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 \\ | |
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa | |
cleo==0.8.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \\ | |
--hash=sha256:141cda6dc94a92343be626bb87a0b6c86ae291dfc732a57bf04310d4b4201753 \\ | |
--hash=sha256:3d0e22d30117851b45970b6c14aca4ab0b18b1b53c8af57bed13208147e4069f | |
clikit==0.6.2; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \\ | |
--hash=sha256:71268e074e68082306e23d7369a7b99f824a0ef926e55ba2665e911f7208489e \\ | |
--hash=sha256:442ee5db9a14120635c5990bcdbfe7c03ada5898291f0c802f77be71569ded59 | |
configparser==4.0.2; python_version == "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version == "2.7" \\ | |
--hash=sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c \\ | |
--hash=sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df | |
contextlib2==0.6.0.post1; python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "2.8" or python_full_version >= "3.5.0" and python_version < "2.8" and python_version >= "2.7" \\ | |
--hash=sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b \\ | |
--hash=sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e | |
crashtest==0.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0") or python_version >= "3.6" and python_version < "4.0" \\ | |
--hash=sha256:300f4b0825f57688b47b6d70c6a31de33512eb2fa1ac614f780939aa0cf91680 \\ | |
--hash=sha256:42ca7b6ce88b6c7433e2ce47ea884e91ec93104a4b754998be498a8e6c3d37dd | |
cryptography==35.0.0 \\ | |
--hash=sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9 \\ | |
--hash=sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6 \\ | |
--hash=sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d \\ | |
--hash=sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa \\ | |
--hash=sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e \\ | |
--hash=sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992 \\ | |
--hash=sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6 \\ | |
--hash=sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d \\ | |
--hash=sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6 \\ | |
--hash=sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8 \\ | |
--hash=sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588 \\ | |
--hash=sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953 \\ | |
--hash=sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6 \\ | |
--hash=sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd \\ | |
--hash=sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76 \\ | |
--hash=sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999 \\ | |
--hash=sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad \\ | |
--hash=sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2 \\ | |
--hash=sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c \\ | |
--hash=sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d | |
distlib==0.3.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" \\ | |
--hash=sha256:c8b54e8454e5bf6237cc84c20e8264c3e991e824ef27e8f1e81049867d861e31 \\ | |
--hash=sha256:d982d0751ff6eaaab5e2ec8e691d949ee80eddf01a62eaa96ddb11531fe16b05 | |
entrypoints==0.3; python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 \\ | |
--hash=sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451 | |
enum34==1.1.10; python_version >= "2.7" and python_version < "2.8" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0") \\ | |
--hash=sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53 \\ | |
--hash=sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328 \\ | |
--hash=sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248 | |
filelock==3.2.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" \\ | |
--hash=sha256:7f07b08d731907441ff40d0c5b81f9512cd968842e0b6264c8bd18a8ce877760 \\ | |
--hash=sha256:9cdd29c411ab196cf4c35a1da684f7b9da723696cb356efa45bf5eb1ff313ee3 | |
functools32==3.2.3-2; python_version >= "2.7" and python_version < "2.8" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0") or python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d \\ | |
--hash=sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0 | |
futures==3.3.0; python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:49b3f5b064b6e3afc3316421a3f25f66c137ae88f068abbf72830170033c5e16 \\ | |
--hash=sha256:7e033af76a5e35f58e56da7a91e687706faf4e7bdfb2cbc3f2cca6b9bcda9794 | |
glob2==0.6; python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:f5b0a686ff21f820c4d3f0c4edd216704cea59d79d00fa337e244a2f2ff83ed6 | |
html5lib==1.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") \\ | |
--hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \\ | |
--hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f | |
idna==2.10; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" \\ | |
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 \\ | |
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 | |
importlib-metadata==1.7.0; python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.5.0" and python_version >= "2.7" and python_version < "3.8" or python_version < "3.8" \\ | |
--hash=sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070 \\ | |
--hash=sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83 | |
importlib-resources==3.2.1; python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "3.7" or python_full_version >= "3.5.0" and python_version < "3.7" \\ | |
--hash=sha256:e2860cf0c4bc999947228d18be154fa3779c5dde0b882bd2d7b3f4d25e698bd6 \\ | |
--hash=sha256:a9fe213ab6452708ec1b3f4ec6f2881b8ab3645cb4e5efb7fea2bbf05a91db3b | |
jeepney==0.7.1; python_version >= "3.6" and python_version < "4.0" and sys_platform == "linux" \\ | |
--hash=sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac \\ | |
--hash=sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f | |
keyring==18.0.1; python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:7b29ebfcf8678c4da531b2478a912eea01e80007e5ddca9ee0c7038cb3489ec6 \\ | |
--hash=sha256:67d6cc0132bd77922725fae9f18366bb314fd8f95ff4d323a4df41890a96a838 \\ | |
--hash=sha256:c674f032424b4bffc62abeac5523ec49cc84aed07a480c3233e0baf618efc15c \\ | |
--hash=sha256:963bfa7f090269d30bdc5e25589e5fd9dad2cf2a7c6f176a7f2386910e5d0d8d \\ | |
--hash=sha256:4be9cbaaaf83e61d6399f733d113ede7d1c73bc75cb6aeb64eee0f6ac39b30ea \\ | |
--hash=sha256:1746d3ac913d449a090caf11e9e4af00e26c3f7f7e81027872192b2398b98675 | |
keyring==20.0.1; python_version >= "3.5" and python_version < "3.6" \\ | |
--hash=sha256:7b29ebfcf8678c4da531b2478a912eea01e80007e5ddca9ee0c7038cb3489ec6 \\ | |
--hash=sha256:67d6cc0132bd77922725fae9f18366bb314fd8f95ff4d323a4df41890a96a838 \\ | |
--hash=sha256:c674f032424b4bffc62abeac5523ec49cc84aed07a480c3233e0baf618efc15c \\ | |
--hash=sha256:963bfa7f090269d30bdc5e25589e5fd9dad2cf2a7c6f176a7f2386910e5d0d8d \\ | |
--hash=sha256:4be9cbaaaf83e61d6399f733d113ede7d1c73bc75cb6aeb64eee0f6ac39b30ea \\ | |
--hash=sha256:1746d3ac913d449a090caf11e9e4af00e26c3f7f7e81027872192b2398b98675 | |
keyring==21.8.0; python_version >= "3.6" and python_version < "4.0" \\ | |
--hash=sha256:7b29ebfcf8678c4da531b2478a912eea01e80007e5ddca9ee0c7038cb3489ec6 \\ | |
--hash=sha256:67d6cc0132bd77922725fae9f18366bb314fd8f95ff4d323a4df41890a96a838 \\ | |
--hash=sha256:c674f032424b4bffc62abeac5523ec49cc84aed07a480c3233e0baf618efc15c \\ | |
--hash=sha256:963bfa7f090269d30bdc5e25589e5fd9dad2cf2a7c6f176a7f2386910e5d0d8d \\ | |
--hash=sha256:4be9cbaaaf83e61d6399f733d113ede7d1c73bc75cb6aeb64eee0f6ac39b30ea \\ | |
--hash=sha256:1746d3ac913d449a090caf11e9e4af00e26c3f7f7e81027872192b2398b98675 | |
lockfile==0.12.2; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" \\ | |
--hash=sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa \\ | |
--hash=sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799 | |
msgpack==1.0.2; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" \\ | |
--hash=sha256:b6d9e2dae081aa35c44af9c4298de4ee72991305503442a5c74656d82b581fe9 \\ | |
--hash=sha256:a99b144475230982aee16b3d249170f1cccebf27fb0a08e9f603b69637a62192 \\ | |
--hash=sha256:1026dcc10537d27dd2d26c327e552f05ce148977e9d7b9f1718748281b38c841 \\ | |
--hash=sha256:fe07bc6735d08e492a327f496b7850e98cb4d112c56df69b0c844dbebcbb47f6 \\ | |
--hash=sha256:9ea52fff0473f9f3000987f313310208c879493491ef3ccf66268eff8d5a0326 \\ | |
--hash=sha256:26a1759f1a88df5f1d0b393eb582ec022326994e311ba9c5818adc5374736439 \\ | |
--hash=sha256:497d2c12426adcd27ab83144057a705efb6acc7e85957a51d43cdcf7f258900f \\ | |
--hash=sha256:e89ec55871ed5473a041c0495b7b4e6099f6263438e0bd04ccd8418f92d5d7f2 \\ | |
--hash=sha256:a4355d2193106c7aa77c98fc955252a737d8550320ecdb2e9ac701e15e2943bc \\ | |
--hash=sha256:d6c64601af8f3893d17ec233237030e3110f11b8a962cb66720bf70c0141aa54 \\ | |
--hash=sha256:f484cd2dca68502de3704f056fa9b318c94b1539ed17a4c784266df5d6978c87 \\ | |
--hash=sha256:f3e6aaf217ac1c7ce1563cf52a2f4f5d5b1f64e8729d794165db71da57257f0c \\ | |
--hash=sha256:8521e5be9e3b93d4d5e07cb80b7e32353264d143c1f072309e1863174c6aadb1 \\ | |
--hash=sha256:31c17bbf2ae5e29e48d794c693b7ca7a0c73bd4280976d408c53df421e838d2a \\ | |
--hash=sha256:8ffb24a3b7518e843cd83538cf859e026d24ec41ac5721c18ed0c55101f9775b \\ | |
--hash=sha256:b28c0876cce1466d7c2195d7658cf50e4730667196e2f1355c4209444717ee06 \\ | |
--hash=sha256:87869ba567fe371c4555d2e11e4948778ab6b59d6cc9d8460d543e4cfbbddd1c \\ | |
--hash=sha256:b55f7db883530b74c857e50e149126b91bb75d35c08b28db12dcb0346f15e46e \\ | |
--hash=sha256:ac25f3e0513f6673e8b405c3a80500eb7be1cf8f57584be524c4fa78fe8e0c83 \\ | |
--hash=sha256:0cb94ee48675a45d3b86e61d13c1e6f1696f0183f0715544976356ff86f741d9 \\ | |
--hash=sha256:e36a812ef4705a291cdb4a2fd352f013134f26c6ff63477f20235138d1d21009 \\ | |
--hash=sha256:2a5866bdc88d77f6e1370f82f2371c9bc6fc92fe898fa2dec0c5d4f5435a2694 \\ | |
--hash=sha256:92be4b12de4806d3c36810b0fe2aeedd8d493db39e2eb90742b9c09299eb5759 \\ | |
--hash=sha256:de6bd7990a2c2dabe926b7e62a92886ccbf809425c347ae7de277067f97c2887 \\ | |
--hash=sha256:5a9ee2540c78659a1dd0b110f73773533ee3108d4e1219b5a15a8d635b7aca0e \\ | |
--hash=sha256:c747c0cc08bd6d72a586310bda6ea72eeb28e7505990f342552315b229a19b33 \\ | |
--hash=sha256:d8167b84af26654c1124857d71650404336f4eb5cc06900667a493fc619ddd9f \\ | |
--hash=sha256:fae04496f5bc150eefad4e9571d1a76c55d021325dcd484ce45065ebbdd00984 | |
packaging==20.9; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \\ | |
--hash=sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a \\ | |
--hash=sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5 | |
pastel==0.2.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" \\ | |
--hash=sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364 \\ | |
--hash=sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d | |
pathlib2==2.3.6; python_version >= "2.7" and python_version < "2.8" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0") and sys_platform != "win32" and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "2.8" or python_full_version >= "3.5.0" and python_version < "2.8" and python_version >= "2.7") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "3" or python_full_version >= "3.5.0" and python_version < "3") or python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:3a130b266b3a36134dcc79c17b3c7ac9634f083825ca6ea9d8f557ee6195c9c8 \\ | |
--hash=sha256:7d8bcb5555003cdf4a8d2872c538faa3a0f5d20630cb360e518ca3b981795e5f | |
pexpect==4.8.0 \\ | |
--hash=sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937 \\ | |
--hash=sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c | |
pkginfo==1.7.1 \\ | |
--hash=sha256:37ecd857b47e5f55949c41ed061eb51a0bee97a87c969219d144c0e023982779 \\ | |
--hash=sha256:e7432f81d08adec7297633191bbf0bd47faf13cd8724c3a13250e51d542635bd | |
platformdirs==2.0.2; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" \\ | |
--hash=sha256:0b9547541f599d3d242078ae60b927b3e453f0ad52f58b4d4bc3be86aed3ec41 \\ | |
--hash=sha256:3b00d081227d9037bbbca521a5787796b5ef5000faea1e43fd76f1d44b06fcfa | |
poetry-core==1.0.7; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") \\ | |
--hash=sha256:98c11c755a16ef6c5673c22ca94a3802a7df4746a0853a70b6fae8b9f5cac206 \\ | |
--hash=sha256:4f8a7f5390d772f42c4c4c3f188e6424b802cb4b57466c6633a1b9ac36f18a43 | |
poetry==1.1.11 \\ | |
--hash=sha256:628e2a933c9f7c28fa0edbee09f9e2e6b25301e610929b5414f3d55ed40fc712 \\ | |
--hash=sha256:7d7d22f55fbebb830cc85b1c69cd7a91fd85f49e5396e7a14b953645a470f69e | |
ptyprocess==0.7.0 \\ | |
--hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \\ | |
--hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220 | |
pycparser==2.20 \\ | |
--hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 \\ | |
--hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 | |
pylev==1.4.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" \\ | |
--hash=sha256:7b2e2aa7b00e05bb3f7650eb506fc89f474f70493271a35c242d9a92188ad3dd \\ | |
--hash=sha256:9e77e941042ad3a4cc305dcdf2b2dec1aec2fbe3dd9015d2698ad02b173006d1 | |
pyparsing==2.4.7; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" \\ | |
--hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \\ | |
--hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 | |
pywin32-ctypes==0.2.0 \\ | |
--hash=sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942 \\ | |
--hash=sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98 | |
requests-toolbelt==0.9.1 \\ | |
--hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0 \\ | |
--hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f | |
requests==2.25.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") \\ | |
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e \\ | |
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 | |
scandir==1.10.0; python_version >= "2.7" and python_version < "2.8" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0") \\ | |
--hash=sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188 \\ | |
--hash=sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac \\ | |
--hash=sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f \\ | |
--hash=sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e \\ | |
--hash=sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f \\ | |
--hash=sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32 \\ | |
--hash=sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022 \\ | |
--hash=sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4 \\ | |
--hash=sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173 \\ | |
--hash=sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d \\ | |
--hash=sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae | |
secretstorage==2.3.1; python_version < "3.6" and sys_platform == "linux" \\ | |
--hash=sha256:3af65c87765323e6f64c83575b05393f9e003431959c9395d1791d51497f29b6 \\ | |
--hash=sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f \\ | |
--hash=sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195 | |
secretstorage==3.3.1; python_version >= "3.6" and python_version < "4.0" and sys_platform == "linux" \\ | |
--hash=sha256:3af65c87765323e6f64c83575b05393f9e003431959c9395d1791d51497f29b6 \\ | |
--hash=sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f \\ | |
--hash=sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195 | |
shellingham==1.4.0; (python_version >= "2.6" and python_version < "3.0") or (python_version > "3.0" and python_version < "3.1") or (python_version > "3.1" and python_version < "3.2") or (python_version > "3.2" and python_version < "3.3") or (python_version > "3.3") \\ | |
--hash=sha256:536b67a0697f2e4af32ab176c00a50ac2899c5a05e0d8e2dadac8e58888283f9 \\ | |
--hash=sha256:4855c2458d6904829bd34c299f11fdeed7cfefbf8a2c522e4caea6cd76b3171e | |
singledispatch==3.7.0; python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "3.4" or python_full_version >= "3.5.0" and python_version < "3.4" and python_version >= "2.6" \\ | |
--hash=sha256:bc77afa97c8a22596d6d4fc20f1b7bdd2b86edc2a65a4262bdd7cc3cc19aa989 \\ | |
--hash=sha256:c1a4d5c1da310c3fd8fccfb8d4e1cb7df076148fd5d858a819e37fffe44f3092 | |
six==1.16.0 \\ | |
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 \\ | |
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 | |
subprocess32==3.5.4; python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:88e37c1aac5388df41cc8a8456bb49ebffd321a3ad4d70358e3518176de3a56b \\ | |
--hash=sha256:e45d985aef903c5b7444d34350b05da91a9e0ea015415ab45a21212786c649d0 \\ | |
--hash=sha256:eb2937c80497978d181efa1b839ec2d9622cf9600a039a79d0e108d1f9aec79d | |
tomlkit==0.7.2; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") \\ | |
--hash=sha256:173ad840fa5d2aac140528ca1933c29791b79a374a0861a80347f42ec9328117 \\ | |
--hash=sha256:d7a454f319a7e9bd2e249f239168729327e4dd2d27b17dc68be264ad1ce36754 | |
typing-extensions==3.10.0.2; python_version >= "3.5" and python_full_version < "3.5.4" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0") \\ | |
--hash=sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7 \\ | |
--hash=sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34 \\ | |
--hash=sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e | |
typing==3.10.0.0; python_version >= "2.7" and python_version < "2.8" \\ | |
--hash=sha256:c7219ef20c5fbf413b4567092adfc46fa6203cb8454eda33c3fc1afe1398a308 \\ | |
--hash=sha256:12fbdfbe7d6cca1a42e485229afcb0b0c8259258cfb919b8a5e2a5c953742f89 \\ | |
--hash=sha256:13b4ad211f54ddbf93e5901a9967b1e07720c1d1b78d596ac6a439641aa1b130 | |
urllib3==1.25.11; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0" and python_version < "4") \\ | |
--hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e \\ | |
--hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 | |
virtualenv==20.8.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") \\ | |
--hash=sha256:10062e34c204b5e4ec5f62e6ef2473f8ba76513a9a617e873f1f8fb4a519d300 \\ | |
--hash=sha256:bcc17f0b3a29670dd777d6f0755a4c04f28815395bca279cdcb213b97199a6b8 | |
webencodings==0.5.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" \\ | |
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \\ | |
--hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 | |
zipp==1.2.0; python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "2.8" or python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "3.7" or python_full_version >= "3.5.0" and python_version < "2.8" and python_version >= "2.7" or python_full_version >= "3.5.0" and python_version < "3.7" and python_version >= "3.5" \\ | |
--hash=sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921 \\ | |
--hash=sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1 | |
""" | |
# == END VERSIONS | |
} | |
def style(fg, bg, options): | |
codes = [] | |
if fg: | |
codes.append(FOREGROUND_COLORS[fg]) | |
if bg: | |
codes.append(BACKGROUND_COLORS[bg]) | |
if options: | |
if not isinstance(options, (list, tuple)): | |
options = [options] | |
for option in options: | |
codes.append(OPTIONS[option]) | |
return "\033[{}m".format(";".join(map(str, codes))) | |
STYLES = { | |
"info": style("cyan", None, None), | |
"comment": style("yellow", None, None), | |
"success": style("green", None, None), | |
"error": style("red", None, None), | |
"warning": style("yellow", None, None), | |
"b": style(None, None, ("bold",)), | |
} | |
def is_decorated(): | |
if WINDOWS: | |
return ( | |
os.getenv("ANSICON") is not None | |
or "ON" == os.getenv("ConEmuANSI") | |
or "xterm" == os.getenv("Term") | |
) | |
if not hasattr(sys.stdout, "fileno"): | |
return False | |
try: | |
return os.isatty(sys.stdout.fileno()) | |
except UnsupportedOperation: | |
return False | |
def is_interactive(): | |
if not hasattr(sys.stdin, "fileno"): | |
return False | |
try: | |
return os.isatty(sys.stdin.fileno()) | |
except UnsupportedOperation: | |
return False | |
def colorize(style, text): | |
if not is_decorated(): | |
return text | |
return "{}{}\033[0m".format(STYLES[style], text) | |
def string_to_bool(value): | |
value = value.lower() | |
return value in {"true", "1", "y", "yes"} | |
def data_dir(version: Optional[str] = None) -> Path: | |
if os.getenv("POETRY_HOME"): | |
return Path(os.getenv("POETRY_HOME")).expanduser() | |
if WINDOWS: | |
const = "CSIDL_APPDATA" | |
path = os.path.normpath(_get_win_folder(const)) | |
path = os.path.join(path, "pypoetry") | |
elif MACOS: | |
path = os.path.expanduser("~/Library/Application Support/pypoetry") | |
else: | |
path = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share")) | |
path = os.path.join(path, "pypoetry") | |
if version: | |
path = os.path.join(path, version) | |
return Path(path) | |
def bin_dir(version: Optional[str] = None) -> Path: | |
if os.getenv("POETRY_HOME"): | |
return Path(os.getenv("POETRY_HOME"), "bin").expanduser() | |
user_base = site.getuserbase() | |
if WINDOWS: | |
bin_dir = os.path.join(user_base, "Scripts") | |
else: | |
bin_dir = os.path.join(user_base, "bin") | |
return Path(bin_dir) | |
def _get_win_folder_from_registry(csidl_name): | |
import winreg as _winreg | |
shell_folder_name = { | |
"CSIDL_APPDATA": "AppData", | |
"CSIDL_COMMON_APPDATA": "Common AppData", | |
"CSIDL_LOCAL_APPDATA": "Local AppData", | |
}[csidl_name] | |
key = _winreg.OpenKey( | |
_winreg.HKEY_CURRENT_USER, | |
r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", | |
) | |
dir, type = _winreg.QueryValueEx(key, shell_folder_name) | |
return dir | |
def _get_win_folder_with_ctypes(csidl_name): | |
import ctypes | |
csidl_const = { | |
"CSIDL_APPDATA": 26, | |
"CSIDL_COMMON_APPDATA": 35, | |
"CSIDL_LOCAL_APPDATA": 28, | |
}[csidl_name] | |
buf = ctypes.create_unicode_buffer(1024) | |
ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) | |
# Downgrade to short path name if have highbit chars. See | |
# <http://bugs.activestate.com/show_bug.cgi?id=85099>. | |
has_high_char = False | |
for c in buf: | |
if ord(c) > 255: | |
has_high_char = True | |
break | |
if has_high_char: | |
buf2 = ctypes.create_unicode_buffer(1024) | |
if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): | |
buf = buf2 | |
return buf.value | |
if WINDOWS: | |
try: | |
from ctypes import windll # noqa | |
_get_win_folder = _get_win_folder_with_ctypes | |
except ImportError: | |
_get_win_folder = _get_win_folder_from_registry | |
@contextmanager | |
def temporary_directory(*args, **kwargs): | |
try: | |
from tempfile import TemporaryDirectory | |
except ImportError: | |
name = tempfile.mkdtemp(*args, **kwargs) | |
yield name | |
shutil.rmtree(name) | |
else: | |
with TemporaryDirectory(*args, **kwargs) as name: | |
yield name | |
PRE_MESSAGE = """# Welcome to {poetry}! | |
This will download and install the latest version of {poetry}, | |
a dependency and package manager for Python. | |
It will add the `poetry` command to {poetry}'s bin directory, located at: | |
{poetry_home_bin} | |
You can uninstall at any time by executing this script with the --uninstall option, | |
and these changes will be reverted. | |
""" | |
POST_MESSAGE = """{poetry} ({version}) is installed now. Great! | |
You can test that everything is set up by executing: | |
`{test_command}` | |
""" | |
POST_MESSAGE_NOT_IN_PATH = """{poetry} ({version}) is installed now. Great! | |
To get started you need {poetry}'s bin directory ({poetry_home_bin}) in your `PATH` | |
environment variable. | |
{configure_message} | |
Alternatively, you can call {poetry} explicitly with `{poetry_executable}`. | |
You can test that everything is set up by executing: | |
`{test_command}` | |
""" | |
POST_MESSAGE_CONFIGURE_UNIX = """ | |
Add `export PATH="{poetry_home_bin}:$PATH"` to your shell configuration file. | |
""" | |
POST_MESSAGE_CONFIGURE_FISH = """ | |
You can execute `set -U fish_user_paths {poetry_home_bin} $fish_user_paths` | |
""" | |
POST_MESSAGE_CONFIGURE_WINDOWS = """""" | |
class Cursor: | |
def __init__(self) -> None: | |
self._output = sys.stdout | |
def move_up(self, lines: int = 1) -> "Cursor": | |
self._output.write("\x1b[{}A".format(lines)) | |
return self | |
def move_down(self, lines: int = 1) -> "Cursor": | |
self._output.write("\x1b[{}B".format(lines)) | |
return self | |
def move_right(self, columns: int = 1) -> "Cursor": | |
self._output.write("\x1b[{}C".format(columns)) | |
return self | |
def move_left(self, columns: int = 1) -> "Cursor": | |
self._output.write("\x1b[{}D".format(columns)) | |
return self | |
def move_to_column(self, column: int) -> "Cursor": | |
self._output.write("\x1b[{}G".format(column)) | |
return self | |
def move_to_position(self, column: int, row: int) -> "Cursor": | |
self._output.write("\x1b[{};{}H".format(row + 1, column)) | |
return self | |
def save_position(self) -> "Cursor": | |
self._output.write("\x1b7") | |
return self | |
def restore_position(self) -> "Cursor": | |
self._output.write("\x1b8") | |
return self | |
def hide(self) -> "Cursor": | |
self._output.write("\x1b[?25l") | |
return self | |
def show(self) -> "Cursor": | |
self._output.write("\x1b[?25h\x1b[?0c") | |
return self | |
def clear_line(self) -> "Cursor": | |
""" | |
Clears all the output from the current line. | |
""" | |
self._output.write("\x1b[2K") | |
return self | |
def clear_line_after(self) -> "Cursor": | |
""" | |
Clears all the output from the current line after the current position. | |
""" | |
self._output.write("\x1b[K") | |
return self | |
def clear_output(self) -> "Cursor": | |
""" | |
Clears all the output from the cursors' current position | |
to the end of the screen. | |
""" | |
self._output.write("\x1b[0J") | |
return self | |
def clear_screen(self) -> "Cursor": | |
""" | |
Clears the entire screen. | |
""" | |
self._output.write("\x1b[2J") | |
return self | |
class Installer: | |
METADATA_URL = "https://pypi.org/pypi/poetry/json" | |
VERSION_REGEX = re.compile( | |
r"v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?" | |
"(" | |
"[._-]?" | |
r"(?:(stable|beta|b|rc|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*)?)?" | |
"([.-]?dev)?" | |
")?" | |
r"(?:\+[^\s]+)?" | |
) | |
def __init__( | |
self, | |
version: Optional[str] = None, | |
preview: bool = False, | |
force: bool = False, | |
accept_all: bool = False, | |
git: Optional[str] = None, | |
path: Optional[str] = None, | |
) -> None: | |
self._version = version | |
self._preview = preview | |
self._force = force | |
self._accept_all = accept_all | |
self._git = git | |
self._path = path | |
self._data_dir = data_dir() | |
self._bin_dir = bin_dir() | |
self._cursor = Cursor() | |
def allows_prereleases(self) -> bool: | |
return self._preview | |
def run(self) -> int: | |
if self._git: | |
version = self._git | |
elif self._path: | |
version = self._path | |
else: | |
version, current_version = self.get_version() | |
if version is None: | |
return 0 | |
self.display_pre_message() | |
self.ensure_directories() | |
def _is_self_upgrade_supported(x): | |
mx = self.VERSION_REGEX.match(x) | |
if mx is None: | |
# the version is not semver, perhaps scm or file, we assume upgrade is supported | |
return True | |
vx = tuple(int(p) for p in mx.groups()[:3]) + (mx.group(5),) | |
return vx >= (1, 1, 7) | |
if version and not _is_self_upgrade_supported(version): | |
self._write( | |
colorize( | |
"warning", | |
f"You are installing {version}. When using the current installer, this version does not support " | |
f"updating using the 'self update' command. Please use 1.1.7 or later.", | |
) | |
) | |
if not self._accept_all: | |
continue_install = input("Do you want to continue? ([y]/n) ") or "y" | |
if continue_install.lower() in {"n", "no"}: | |
return 0 | |
try: | |
self.install(version) | |
except subprocess.CalledProcessError as e: | |
print( | |
colorize("error", f"\nAn error has occurred: {e}\n{e.stdout.decode()}") | |
) | |
return e.returncode | |
self._write("") | |
self.display_post_message(version) | |
return 0 | |
def install(self, version, upgrade=False): | |
""" | |
Installs Poetry in $POETRY_HOME. | |
""" | |
self._write( | |
"Installing {} ({})".format( | |
colorize("info", "Poetry"), colorize("info", version) | |
) | |
) | |
env_path = self.make_env(version) | |
self.install_poetry(version, env_path) | |
self.make_bin(version) | |
self._overwrite( | |
"Installing {} ({}): {}".format( | |
colorize("info", "Poetry"), | |
colorize("b", version), | |
colorize("success", "Done"), | |
) | |
) | |
self._data_dir.joinpath("VERSION").write_text(version) | |
return 0 | |
def uninstall(self) -> int: | |
if not self._data_dir.exists(): | |
self._write( | |
"{} is not currently installed.".format(colorize("info", "Poetry")) | |
) | |
return 1 | |
version = None | |
if self._data_dir.joinpath("VERSION").exists(): | |
version = self._data_dir.joinpath("VERSION").read_text().strip() | |
if version: | |
self._write( | |
"Removing {} ({})".format( | |
colorize("info", "Poetry"), colorize("b", version) | |
) | |
) | |
else: | |
self._write("Removing {}".format(colorize("info", "Poetry"))) | |
shutil.rmtree(str(self._data_dir)) | |
for script in ["poetry", "poetry.bat"]: | |
if self._bin_dir.joinpath(script).exists(): | |
self._bin_dir.joinpath(script).unlink() | |
return 0 | |
def make_env(self, version: str) -> Path: | |
self._overwrite( | |
"Installing {} ({}): {}".format( | |
colorize("info", "Poetry"), | |
colorize("b", version), | |
colorize("comment", "Creating environment"), | |
) | |
) | |
env_path = self._data_dir.joinpath("venv") | |
with temporary_directory() as tmp_dir: | |
subprocess.call( | |
[sys.executable, "-m", "pip", "install", "virtualenv", "-t", tmp_dir], | |
stdout=subprocess.PIPE, | |
stderr=subprocess.STDOUT, | |
) | |
sys.path.insert(0, tmp_dir) | |
import virtualenv | |
virtualenv.cli_run([str(env_path), "--clear"]) | |
# We add a special file so that Poetry can detect | |
# its own virtual environment | |
env_path.joinpath("poetry_env").touch() | |
return env_path | |
def make_bin(self, version: str) -> None: | |
self._overwrite( | |
"Installing {} ({}): {}".format( | |
colorize("info", "Poetry"), | |
colorize("b", version), | |
colorize("comment", "Creating script"), | |
) | |
) | |
self._bin_dir.mkdir(parents=True, exist_ok=True) | |
script = "poetry" | |
target_script = "venv/bin/poetry" | |
if WINDOWS: | |
script = "poetry.exe" | |
target_script = "venv/Scripts/poetry.exe" | |
if self._bin_dir.joinpath(script).exists(): | |
self._bin_dir.joinpath(script).unlink() | |
try: | |
self._bin_dir.joinpath(script).symlink_to( | |
self._data_dir.joinpath(target_script) | |
) | |
except OSError: | |
exit(1) | |
# This can happen if the user | |
# does not have the correct permission on Windows | |
shutil.copy( | |
self._data_dir.joinpath(target_script), self._bin_dir.joinpath(script) | |
) | |
def install_poetry(self, version: str, env_path: Path) -> None: | |
self._overwrite( | |
"Installing {} ({}): {}".format( | |
colorize("info", "Poetry"), | |
colorize("b", version), | |
colorize("comment", "Installing Poetry"), | |
) | |
) | |
if WINDOWS: | |
python = env_path.joinpath("Scripts/python.exe") | |
else: | |
python = env_path.joinpath("bin/python") | |
# if self._git: | |
# specification = "git+" + version | |
# elif self._path: | |
# specification = version | |
# else: | |
# specification = f"poetry=={version}" | |
with tempfile.NamedTemporaryFile(delete=False) as requirements_file: | |
requirements_file.write(VERSIONS[version].encode("utf-8")) | |
requirements_file.close() | |
subprocess.run( | |
[str(python), "-m", "pip", "install", "-r", requirements_file.name], | |
stdout=subprocess.PIPE, | |
stderr=subprocess.STDOUT, | |
check=True, | |
) | |
os.unlink(requirements_file.name) | |
def display_pre_message(self) -> None: | |
kwargs = { | |
"poetry": colorize("info", "Poetry"), | |
"poetry_home_bin": colorize("comment", self._bin_dir), | |
} | |
self._write(PRE_MESSAGE.format(**kwargs)) | |
def display_post_message(self, version: str) -> None: | |
if WINDOWS: | |
return self.display_post_message_windows(version) | |
if SHELL == "fish": | |
return self.display_post_message_fish(version) | |
return self.display_post_message_unix(version) | |
def display_post_message_windows(self, version: str) -> None: | |
path = self.get_windows_path_var() | |
message = POST_MESSAGE_NOT_IN_PATH | |
if path and str(self._bin_dir) in path: | |
message = POST_MESSAGE | |
self._write( | |
message.format( | |
poetry=colorize("info", "Poetry"), | |
version=colorize("b", version), | |
poetry_home_bin=colorize("comment", self._bin_dir), | |
poetry_executable=colorize("b", self._bin_dir.joinpath("poetry")), | |
configure_message=POST_MESSAGE_CONFIGURE_WINDOWS.format( | |
poetry_home_bin=colorize("comment", self._bin_dir) | |
), | |
test_command=colorize("b", "poetry --version"), | |
) | |
) | |
def get_windows_path_var(self) -> Optional[str]: | |
import winreg | |
with winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) as root: | |
with winreg.OpenKey(root, "Environment", 0, winreg.KEY_ALL_ACCESS) as key: | |
path, _ = winreg.QueryValueEx(key, "PATH") | |
return path | |
def display_post_message_fish(self, version: str) -> None: | |
fish_user_paths = subprocess.check_output( | |
["fish", "-c", "echo $fish_user_paths"] | |
).decode("utf-8") | |
message = POST_MESSAGE_NOT_IN_PATH | |
if fish_user_paths and str(self._bin_dir) in fish_user_paths: | |
message = POST_MESSAGE | |
self._write( | |
message.format( | |
poetry=colorize("info", "Poetry"), | |
version=colorize("b", version), | |
poetry_home_bin=colorize("comment", self._bin_dir), | |
poetry_executable=colorize("b", self._bin_dir.joinpath("poetry")), | |
configure_message=POST_MESSAGE_CONFIGURE_FISH.format( | |
poetry_home_bin=colorize("comment", self._bin_dir) | |
), | |
test_command=colorize("b", "poetry --version"), | |
) | |
) | |
def display_post_message_unix(self, version: str) -> None: | |
paths = os.getenv("PATH", "").split(":") | |
message = POST_MESSAGE_NOT_IN_PATH | |
if paths and str(self._bin_dir) in paths: | |
message = POST_MESSAGE | |
self._write( | |
message.format( | |
poetry=colorize("info", "Poetry"), | |
version=colorize("b", version), | |
poetry_home_bin=colorize("comment", self._bin_dir), | |
poetry_executable=colorize("b", self._bin_dir.joinpath("poetry")), | |
configure_message=POST_MESSAGE_CONFIGURE_UNIX.format( | |
poetry_home_bin=colorize("comment", self._bin_dir) | |
), | |
test_command=colorize("b", "poetry --version"), | |
) | |
) | |
def ensure_directories(self) -> None: | |
self._data_dir.mkdir(parents=True, exist_ok=True) | |
self._bin_dir.mkdir(parents=True, exist_ok=True) | |
def get_version(self): | |
current_version = None | |
if self._data_dir.joinpath("VERSION").exists(): | |
current_version = self._data_dir.joinpath("VERSION").read_text().strip() | |
self._write(colorize("info", "Retrieving Poetry metadata")) | |
metadata = json.loads(self._get(self.METADATA_URL).decode()) | |
def _compare_versions(x, y): | |
mx = self.VERSION_REGEX.match(x) | |
my = self.VERSION_REGEX.match(y) | |
vx = tuple(int(p) for p in mx.groups()[:3]) + (mx.group(5),) | |
vy = tuple(int(p) for p in my.groups()[:3]) + (my.group(5),) | |
if vx < vy: | |
return -1 | |
elif vx > vy: | |
return 1 | |
return 0 | |
self._write("") | |
releases = sorted( | |
metadata["releases"].keys(), key=cmp_to_key(_compare_versions) | |
) | |
if self._version and self._version not in releases: | |
self._write( | |
colorize("error", "Version {} does not exist.".format(self._version)) | |
) | |
return None, None | |
version = self._version | |
if not version: | |
for release in reversed(releases): | |
m = self.VERSION_REGEX.match(release) | |
if m.group(5) and not self.allows_prereleases(): | |
continue | |
version = release | |
break | |
if current_version == version and not self._force: | |
self._write( | |
"The latest version ({}) is already installed.".format( | |
colorize("b", version) | |
) | |
) | |
return None, current_version | |
return version, current_version | |
def _write(self, line) -> None: | |
sys.stdout.write(line + "\n") | |
def _overwrite(self, line) -> None: | |
if not is_decorated(): | |
return self._write(line) | |
self._cursor.move_up() | |
self._cursor.clear_line() | |
self._write(line) | |
def _get(self, url): | |
request = Request(url, headers={"User-Agent": "Python Poetry"}) | |
with closing(urlopen(request)) as r: | |
return r.read() | |
def main(): | |
parser = argparse.ArgumentParser( | |
description="Installs the latest (or given) version of poetry" | |
) | |
parser.add_argument( | |
"-p", | |
"--preview", | |
help="install preview version", | |
dest="preview", | |
action="store_true", | |
default=False, | |
) | |
parser.add_argument("--version", help="install named version", dest="version") | |
parser.add_argument( | |
"-f", | |
"--force", | |
help="install on top of existing version", | |
dest="force", | |
action="store_true", | |
default=False, | |
) | |
parser.add_argument( | |
"-y", | |
"--yes", | |
help="accept all prompts", | |
dest="accept_all", | |
action="store_true", | |
default=False, | |
) | |
parser.add_argument( | |
"--uninstall", | |
help="uninstall poetry", | |
dest="uninstall", | |
action="store_true", | |
default=False, | |
) | |
parser.add_argument( | |
"--path", | |
dest="path", | |
action="store", | |
help=( | |
"Install from a given path (file or directory) instead of " | |
"fetching the latest version of Poetry available online." | |
), | |
) | |
parser.add_argument( | |
"--git", | |
dest="git", | |
action="store", | |
help=( | |
"Install from a git repository instead of fetching the latest version " | |
"of Poetry available online." | |
), | |
) | |
args = parser.parse_args() | |
installer = Installer( | |
version=args.version or os.getenv("POETRY_VERSION"), | |
preview=args.preview or string_to_bool(os.getenv("POETRY_PREVIEW", "0")), | |
force=args.force, | |
accept_all=args.accept_all | |
or string_to_bool(os.getenv("POETRY_ACCEPT", "0")) | |
or not is_interactive(), | |
path=args.path, | |
git=args.git, | |
) | |
if args.uninstall or string_to_bool(os.getenv("POETRY_UNINSTALL", "0")): | |
return installer.uninstall() | |
return installer.run() | |
if __name__ == "__main__": | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment