Skip to content

Instantly share code, notes, and snippets.

@awilkins
Created October 31, 2021 12:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save awilkins/286220b87a49899aa03f7286912fce4e to your computer and use it in GitHub Desktop.
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 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