mirror of
https://github.com/python-poetry/install.python-poetry.org.git
synced 2024-11-23 06:20:57 -05:00
Compare commits
43 commits
07185e6663
...
2b71f2bd03
Author | SHA1 | Date | |
---|---|---|---|
|
2b71f2bd03 | ||
|
29ac4557b7 | ||
|
d3ff39aaef | ||
|
c762e1bc54 | ||
|
89e0b6f7b9 | ||
|
f9ec0dc5c2 | ||
|
76183eebc8 | ||
|
d62875fc05 | ||
|
e518c55933 | ||
|
348d37f67f | ||
|
04dd4769d5 | ||
|
34305a09a1 | ||
|
aebbeda95f | ||
|
ac8231e7e0 | ||
|
b9cf4334bc | ||
|
385616cd90 | ||
|
07ccfe459b | ||
|
e69417b029 | ||
|
fcd759d6fe | ||
|
649e855f81 | ||
|
64b3848647 | ||
|
42a10434ed | ||
|
fb4d36d19d | ||
|
89f4049e20 | ||
|
c776287cbd | ||
|
6362d37d57 | ||
|
6161821b1d | ||
|
c8c3ce44ff | ||
|
6fd4578c5f | ||
|
fb3ae6a4ee | ||
|
e8d8f76750 | ||
|
206447fcd4 | ||
|
9b64f71d73 | ||
|
ae8a9ad9a8 | ||
|
c71c7d6c22 | ||
|
edbdec9887 | ||
|
ac6fb50a38 | ||
|
07dd8a55c5 | ||
|
e837f27653 | ||
|
5ad0932c19 | ||
|
d2a07fc9f1 | ||
|
be23be56c5 | ||
|
303392379b |
7 changed files with 320 additions and 157 deletions
3
.flake8
3
.flake8
|
@ -1,3 +0,0 @@
|
||||||
[flake8]
|
|
||||||
max-line-length = 88
|
|
||||||
ignore = E501, E203, W503
|
|
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: monthly
|
76
.github/workflows/installer.yml
vendored
76
.github/workflows/installer.yml
vendored
|
@ -15,7 +15,7 @@ on:
|
||||||
- '**'
|
- '**'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: installer-${{ github.head_ref || github.ref }}
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -25,27 +25,32 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [Ubuntu, macOS, Windows]
|
os: [Ubuntu, macOS, Windows]
|
||||||
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11-dev"]
|
python-version:
|
||||||
|
- "3.9"
|
||||||
|
- "3.10"
|
||||||
|
- "3.11"
|
||||||
|
- "3.12"
|
||||||
|
- "3.13"
|
||||||
args:
|
args:
|
||||||
- ""
|
- ""
|
||||||
- "--preview"
|
- "--preview"
|
||||||
- "--git https://github.com/python-poetry/poetry.git"
|
- "--git https://github.com/python-poetry/poetry.git"
|
||||||
- "--version 1.1.14"
|
|
||||||
include:
|
include:
|
||||||
- os: Ubuntu
|
- os: Ubuntu
|
||||||
image: ubuntu-latest
|
image: ubuntu-22.04
|
||||||
- os: Windows
|
- os: Windows
|
||||||
image: windows-2022
|
image: windows-2022
|
||||||
- os: macOS
|
- os: macOS
|
||||||
image: macos-11
|
image: macos-12
|
||||||
|
fail-fast: false
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
@ -58,10 +63,10 @@ jobs:
|
||||||
run: echo "$APPDATA\Python\Scripts" >> $GITHUB_PATH
|
run: echo "$APPDATA\Python\Scripts" >> $GITHUB_PATH
|
||||||
|
|
||||||
- name: Install Poetry
|
- name: Install Poetry
|
||||||
run: python install-poetry.py -y
|
run: python install-poetry.py -y ${{ matrix.args }}
|
||||||
|
|
||||||
- name: Upload Failure Log
|
- name: Upload Failure Log
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: poetry-installer-error.log
|
name: poetry-installer-error.log
|
||||||
|
@ -81,3 +86,56 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
python install-poetry.py -y --uninstall
|
python install-poetry.py -y --uninstall
|
||||||
{ type poetry 2>/dev/null >&2 && exit 1; } || exit 0
|
{ type poetry 2>/dev/null >&2 && exit 1; } || exit 0
|
||||||
|
|
||||||
|
# debian/ubuntu needs special testing due to various issues around python packaging
|
||||||
|
# and configuration
|
||||||
|
integration-ubuntu:
|
||||||
|
name: Integration Test / Ubuntu / ${{ matrix.tag }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: docker.io/ubuntu:${{ matrix.tag }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
tag:
|
||||||
|
- focal
|
||||||
|
- jammy
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Packages
|
||||||
|
run: |
|
||||||
|
apt-get -y update
|
||||||
|
apt-get -y install python3 ca-certificates
|
||||||
|
apt-get -y install --reinstall python3-distutils
|
||||||
|
|
||||||
|
- name: Update PATH
|
||||||
|
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Install Poetry
|
||||||
|
env:
|
||||||
|
DEB_PYTHON_INSTALL_LAYOUT: "deb"
|
||||||
|
run: python3 install-poetry.py -y
|
||||||
|
|
||||||
|
- name: Upload Failure Log
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: poetry-installer-error.log
|
||||||
|
path: poetry-installer-error-*.log
|
||||||
|
|
||||||
|
- name: Verify Installation
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
poetry new foobar
|
||||||
|
cd foobar
|
||||||
|
poetry config virtualenvs.in-project true
|
||||||
|
poetry env use python3
|
||||||
|
[ "$(poetry run python --version)" == "$(python3 --version)" ] \
|
||||||
|
|| { echo >&2 "ERROR: Virtual environment Python version do not match system version." && exit 1; }
|
||||||
|
|
||||||
|
- name: Uninstall Poetry
|
||||||
|
run: |
|
||||||
|
python3 install-poetry.py -y --uninstall
|
||||||
|
{ type poetry 2>/dev/null >&2 && exit 1; } || exit 0
|
||||||
|
|
|
@ -1,28 +1,20 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||||
rev: 22.6.0
|
rev: 23.9.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
|
||||||
rev: 4.0.1
|
|
||||||
hooks:
|
|
||||||
- id: flake8
|
|
||||||
additional_dependencies:
|
|
||||||
- flake8-bugbear==22.4.25
|
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/isort
|
|
||||||
rev: 5.10.1
|
|
||||||
hooks:
|
|
||||||
- id: isort
|
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.3.0
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: debug-statements
|
- id: debug-statements
|
||||||
- id: pretty-format-json
|
- id: pretty-format-json
|
||||||
args:
|
args: [--autofix]
|
||||||
- --autofix
|
|
||||||
- id: check-json
|
- id: check-json
|
||||||
|
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.0.290
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
|
92
README.md
92
README.md
|
@ -1,4 +1,7 @@
|
||||||
# Python Poetry Installer
|
# Python Poetry Installer
|
||||||
|
|
||||||
|
[![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
|
||||||
|
|
||||||
This repository contains Poetry's official installation script, installer source and
|
This repository contains Poetry's official installation script, installer source and
|
||||||
related hosting configuration.
|
related hosting configuration.
|
||||||
|
|
||||||
|
@ -11,16 +14,21 @@ Poetry provides a custom installer that will install `poetry` isolated
|
||||||
from the rest of your system.
|
from the rest of your system.
|
||||||
|
|
||||||
### osx / linux / bashonwindows / Windows+MinGW install instructions
|
### osx / linux / bashonwindows / Windows+MinGW install instructions
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sSL https://install.python-poetry.org | python -
|
curl -sSL https://install.python-poetry.org | python3 -
|
||||||
```
|
|
||||||
### windows powershell install instructions
|
|
||||||
```powershell
|
|
||||||
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### windows powershell install instructions
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
|
||||||
|
```
|
||||||
|
|
||||||
|
> If you have installed Python through the Microsoft Store, replace `py` with `python` in the command above.
|
||||||
|
|
||||||
**Warning**: The previous `get-poetry.py` installer is now deprecated, if you are currently using it
|
**Warning**: The previous `get-poetry.py` installer is now deprecated, if you are currently using it
|
||||||
you should migrate to the new, supported, `install-poetry.py` installer.
|
you should migrate to the new, supported, `install.python-poetry.org` installer.
|
||||||
|
|
||||||
The installer installs the `poetry` tool to Poetry's `bin` directory. This location depends on your system:
|
The installer installs the `poetry` tool to Poetry's `bin` directory. This location depends on your system:
|
||||||
|
|
||||||
|
@ -41,40 +49,88 @@ poetry --version
|
||||||
If you see something like `Poetry (version 1.2.0)` then you are ready to use Poetry.
|
If you see something like `Poetry (version 1.2.0)` then you are ready to use Poetry.
|
||||||
If you decide Poetry isn't your thing, you can completely remove it from your system
|
If you decide Poetry isn't your thing, you can completely remove it from your system
|
||||||
by running the installer again with the `--uninstall` option or by setting
|
by running the installer again with the `--uninstall` option or by setting
|
||||||
the `POETRY_UNINSTALL` environment variable before executing the installer.
|
the `POETRY_UNINSTALL` environment variable before executing the installer:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python install-poetry.py --uninstall
|
curl -sSL https://install.python-poetry.org | python3 - --uninstall
|
||||||
POETRY_UNINSTALL=1 python install-poetry.py
|
curl -sSL https://install.python-poetry.org | POETRY_UNINSTALL=1 python3 -
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, Poetry is installed into the user's platform-specific home directory.
|
By default, Poetry is installed into the user's platform-specific home directory.
|
||||||
If you wish to change this, you may define the `POETRY_HOME` environment variable:
|
If you wish to change this, you may define the `POETRY_HOME` environment variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
POETRY_HOME=/etc/poetry python install-poetry.py
|
curl -sSL https://install.python-poetry.org | POETRY_HOME=/etc/poetry python3 -
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to install prerelease versions, you can do so by passing `--preview` option to `install-poetry.py`
|
If you want to install prerelease versions, you can do so by passing `--preview` option or by using the `POETRY_PREVIEW`
|
||||||
or by using the `POETRY_PREVIEW` environment variable:
|
environment variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python install-poetry.py --preview
|
curl -sSL https://install.python-poetry.org | python3 - --preview
|
||||||
POETRY_PREVIEW=1 python install-poetry.py
|
curl -sSL https://install.python-poetry.org | POETRY_PREVIEW=1 python3 -
|
||||||
```
|
```
|
||||||
|
|
||||||
Similarly, if you want to install a specific version, you can use `--version` option or the `POETRY_VERSION`
|
Similarly, if you want to install a specific version, you can use `--version` option or the `POETRY_VERSION`
|
||||||
environment variable:
|
environment variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python install-poetry.py --version 1.2.0
|
curl -sSL https://install.python-poetry.org | python3 - --version 1.2.0
|
||||||
POETRY_VERSION=1.2.0 python install-poetry.py
|
curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.2.0 python3 -
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also install Poetry for a `git` repository by using the `--git` option:
|
You can also install Poetry for a `git` repository by using the `--git` option:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python install-poetry.py --git https://github.com/python-poetry/poetry.git@master
|
curl -sSL https://install.python-poetry.org | python3 - --git https://github.com/python-poetry/poetry.git@master
|
||||||
````
|
````
|
||||||
|
|
||||||
**Note**: Note that the installer does not support Python < 3.6.
|
> **Note**: The installer does not support Python < 3.6.
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
### Debian/Ubuntu
|
||||||
|
|
||||||
|
On Debian and Ubuntu systems, there are various issues that maybe caused due to how
|
||||||
|
various Python standard library components are packaged and configured. The following
|
||||||
|
details issues we are presently aware of, and potential workarounds.
|
||||||
|
|
||||||
|
> **Note:** This can also affect WSL users on Windows.
|
||||||
|
|
||||||
|
#### Installation Layout
|
||||||
|
|
||||||
|
If you encounter an error similar to the following, this might be due to
|
||||||
|
[pypa/virtualenv#2350](https://github.com/pypa/virtualenv/issues/2350).
|
||||||
|
|
||||||
|
```console
|
||||||
|
FileNotFoundError: [Errno 2] No such file or directory: '/root/.local/share/pypoetry/venv/bin/python'
|
||||||
|
```
|
||||||
|
|
||||||
|
You can work around this issue by setting the `DEB_PYTHON_INSTALL_LAYOUT` environment
|
||||||
|
variable to `deb` in order to emulate previously working behaviour.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DEB_PYTHON_INSTALL_LAYOUT=deb
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Missing `distutils` Module
|
||||||
|
|
||||||
|
In certain Debian/Ubuntu environments, you might encounter the following error message
|
||||||
|
in error logs (`poetry-installer-error-*.log`) provided when the installer fails.
|
||||||
|
|
||||||
|
```console
|
||||||
|
ModuleNotFoundError: No module named 'distutils.cmd'
|
||||||
|
```
|
||||||
|
|
||||||
|
This is probably due to [this bug](https://bugs.launchpad.net/ubuntu/+source/python3.10/+bug/1940705).
|
||||||
|
See also [pypa/get-pip#124](https://github.com/pypa/get-pip/issues/124).
|
||||||
|
|
||||||
|
The known workaround for this issue is to reinstall the `distutils` package provided by
|
||||||
|
the distribution.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt-get install --reinstall python3-distutils
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have installed a specific python version, eg: `3.10`, you might have to use the
|
||||||
|
package name `python3.10-distutils`.
|
||||||
|
|
|
@ -1,27 +1,43 @@
|
||||||
"""
|
#!/usr/bin/env python3
|
||||||
This script will install Poetry and its dependencies.
|
r"""
|
||||||
|
This script will install Poetry and its dependencies in an isolated fashion.
|
||||||
|
|
||||||
It does, in order:
|
It will perform the following steps:
|
||||||
|
* Create a new virtual environment using the built-in venv module, or the virtualenv zipapp if venv is unavailable.
|
||||||
|
This will be created at a platform-specific path (or `$POETRY_HOME` if `$POETRY_HOME` is set:
|
||||||
|
- `~/Library/Application Support/pypoetry` on macOS
|
||||||
|
- `$XDG_DATA_HOME/pypoetry` on Linux/Unix (`$XDG_DATA_HOME` is `~/.local/share` if unset)
|
||||||
|
- `%APPDATA%\pypoetry` on Windows
|
||||||
|
* Update pip inside the virtual environment to avoid bugs in older versions.
|
||||||
|
* Install the latest (or a given) version of Poetry inside this virtual environment using pip.
|
||||||
|
* Install a `poetry` script into a platform-specific path (or `$POETRY_HOME/bin` if `$POETRY_HOME` is set):
|
||||||
|
- `~/.local/bin` on Unix
|
||||||
|
- `%APPDATA%\Python\Scripts` on Windows
|
||||||
|
* Attempt to inform the user if they need to add this bin directory to their `$PATH`, as well as how to do so.
|
||||||
|
* Upon failure, write an error log to `poetry-installer-error-<hash>.log and restore any previous environment.
|
||||||
|
|
||||||
|
This script performs minimal magic, and should be relatively stable. However, it is optimized for interactive developer
|
||||||
|
use and trivial pipelines. If you are considering using this script in production, you should consider manually-managed
|
||||||
|
installs, or use of pipx as alternatives to executing arbitrary, unversioned code from the internet. If you prefer this
|
||||||
|
script to alternatives, consider maintaining a local copy as part of your infrastructure.
|
||||||
|
|
||||||
|
For full documentation, visit https://python-poetry.org/docs/#installation.
|
||||||
|
""" # noqa: E501
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# Eager version check so we fail nicely before possible syntax errors
|
||||||
|
if sys.version_info < (3, 6): # noqa: UP036
|
||||||
|
sys.stdout.write("Poetry installer requires Python 3.6 or newer to run!\n")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
- Creates a virtual environment using venv (or virtualenv zipapp) 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).
|
|
||||||
- On failure, the error log is written to poetry-installer-error-*.log and any previously existing environment
|
|
||||||
is restored.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import site
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
|
||||||
import sysconfig
|
import sysconfig
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
@ -98,8 +114,8 @@ def is_decorated():
|
||||||
if WINDOWS:
|
if WINDOWS:
|
||||||
return (
|
return (
|
||||||
os.getenv("ANSICON") is not None
|
os.getenv("ANSICON") is not None
|
||||||
or "ON" == os.getenv("ConEmuANSI")
|
or os.getenv("ConEmuANSI") == "ON" # noqa: SIM112
|
||||||
or "xterm" == os.getenv("Term")
|
or os.getenv("Term") == "xterm" # noqa: SIM112
|
||||||
)
|
)
|
||||||
|
|
||||||
if not hasattr(sys.stdout, "fileno"):
|
if not hasattr(sys.stdout, "fileno"):
|
||||||
|
@ -125,7 +141,7 @@ def colorize(style, text):
|
||||||
if not is_decorated():
|
if not is_decorated():
|
||||||
return text
|
return text
|
||||||
|
|
||||||
return "{}{}\033[0m".format(STYLES[style], text)
|
return f"{STYLES[style]}{text}\033[0m"
|
||||||
|
|
||||||
|
|
||||||
def string_to_bool(value):
|
def string_to_bool(value):
|
||||||
|
@ -134,38 +150,29 @@ def string_to_bool(value):
|
||||||
return value in {"true", "1", "y", "yes"}
|
return value in {"true", "1", "y", "yes"}
|
||||||
|
|
||||||
|
|
||||||
def data_dir(version: Optional[str] = None) -> Path:
|
def data_dir() -> Path:
|
||||||
if os.getenv("POETRY_HOME"):
|
if os.getenv("POETRY_HOME"):
|
||||||
return Path(os.getenv("POETRY_HOME")).expanduser()
|
return Path(os.getenv("POETRY_HOME")).expanduser()
|
||||||
|
|
||||||
if WINDOWS:
|
if WINDOWS:
|
||||||
const = "CSIDL_APPDATA"
|
base_dir = Path(_get_win_folder("CSIDL_APPDATA"))
|
||||||
path = os.path.normpath(_get_win_folder(const))
|
|
||||||
path = os.path.join(path, "pypoetry")
|
|
||||||
elif MACOS:
|
elif MACOS:
|
||||||
path = os.path.expanduser("~/Library/Application Support/pypoetry")
|
base_dir = Path("~/Library/Application Support").expanduser()
|
||||||
else:
|
else:
|
||||||
path = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share"))
|
base_dir = Path(os.getenv("XDG_DATA_HOME", "~/.local/share")).expanduser()
|
||||||
path = os.path.join(path, "pypoetry")
|
|
||||||
|
|
||||||
if version:
|
base_dir = base_dir.resolve()
|
||||||
path = os.path.join(path, version)
|
return base_dir / "pypoetry"
|
||||||
|
|
||||||
return Path(path)
|
|
||||||
|
|
||||||
|
|
||||||
def bin_dir(version: Optional[str] = None) -> Path:
|
def bin_dir() -> Path:
|
||||||
if os.getenv("POETRY_HOME"):
|
if os.getenv("POETRY_HOME"):
|
||||||
return Path(os.getenv("POETRY_HOME"), "bin").expanduser()
|
return Path(os.getenv("POETRY_HOME")).expanduser() / "bin"
|
||||||
|
|
||||||
user_base = site.getuserbase()
|
|
||||||
|
|
||||||
if WINDOWS and not MINGW:
|
if WINDOWS and not MINGW:
|
||||||
bin_dir = os.path.join(user_base, "Scripts")
|
return Path(_get_win_folder("CSIDL_APPDATA")) / "Python/Scripts"
|
||||||
else:
|
else:
|
||||||
bin_dir = os.path.join(user_base, "bin")
|
return Path("~/.local/bin").expanduser()
|
||||||
|
|
||||||
return Path(bin_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def _get_win_folder_from_registry(csidl_name):
|
def _get_win_folder_from_registry(csidl_name):
|
||||||
|
@ -181,9 +188,9 @@ def _get_win_folder_from_registry(csidl_name):
|
||||||
_winreg.HKEY_CURRENT_USER,
|
_winreg.HKEY_CURRENT_USER,
|
||||||
r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders",
|
r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders",
|
||||||
)
|
)
|
||||||
dir, type = _winreg.QueryValueEx(key, shell_folder_name)
|
path, _ = _winreg.QueryValueEx(key, shell_folder_name)
|
||||||
|
|
||||||
return dir
|
return path
|
||||||
|
|
||||||
|
|
||||||
def _get_win_folder_with_ctypes(csidl_name):
|
def _get_win_folder_with_ctypes(csidl_name):
|
||||||
|
@ -265,7 +272,7 @@ You can execute `set -U fish_user_paths {poetry_home_bin} $fish_user_paths`
|
||||||
POST_MESSAGE_CONFIGURE_WINDOWS = """
|
POST_MESSAGE_CONFIGURE_WINDOWS = """
|
||||||
You can choose and execute one of the following commands in PowerShell:
|
You can choose and execute one of the following commands in PowerShell:
|
||||||
|
|
||||||
A. Appends the bin directory to your user environment variable `PATH`:
|
A. Append the bin directory to your user environment variable `PATH`:
|
||||||
|
|
||||||
```
|
```
|
||||||
[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";{poetry_home_bin}", "User")
|
[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";{poetry_home_bin}", "User")
|
||||||
|
@ -281,7 +288,7 @@ echo 'if (-not (Get-Command poetry -ErrorAction Ignore)) {{ $env:Path += ";{poet
|
||||||
|
|
||||||
class PoetryInstallationError(RuntimeError):
|
class PoetryInstallationError(RuntimeError):
|
||||||
def __init__(self, return_code: int = 0, log: Optional[str] = None):
|
def __init__(self, return_code: int = 0, log: Optional[str] = None):
|
||||||
super(PoetryInstallationError, self).__init__()
|
super().__init__()
|
||||||
self.return_code = return_code
|
self.return_code = return_code
|
||||||
self.log = log
|
self.log = log
|
||||||
|
|
||||||
|
@ -292,7 +299,7 @@ class VirtualEnvironment:
|
||||||
self._bin_path = self._path.joinpath(
|
self._bin_path = self._path.joinpath(
|
||||||
"Scripts" if WINDOWS and not MINGW else "bin"
|
"Scripts" if WINDOWS and not MINGW else "bin"
|
||||||
)
|
)
|
||||||
# str is required for compatibility with subprocess run on CPython <= 3.7 on Windows
|
# str is for compatibility with subprocess.run on CPython <= 3.7 on Windows
|
||||||
self._python = str(
|
self._python = str(
|
||||||
self._path.joinpath(self._bin_path, "python.exe" if WINDOWS else "python")
|
self._path.joinpath(self._bin_path, "python.exe" if WINDOWS else "python")
|
||||||
)
|
)
|
||||||
|
@ -307,7 +314,18 @@ class VirtualEnvironment:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make(cls, target: Path) -> "VirtualEnvironment":
|
def make(cls, target: Path) -> "VirtualEnvironment":
|
||||||
|
if not sys.executable:
|
||||||
|
raise ValueError(
|
||||||
|
"Unable to determine sys.executable. Set PATH to a sane value or set it"
|
||||||
|
" explicitly with PYTHONEXECUTABLE."
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# on some linux distributions (eg: debian), the distribution provided python
|
||||||
|
# installation might not include ensurepip, causing the venv module to
|
||||||
|
# fail when attempting to create a virtual environment
|
||||||
|
# we import ensurepip but do not use it explicitly here
|
||||||
|
import ensurepip # noqa: F401
|
||||||
import venv
|
import venv
|
||||||
|
|
||||||
builder = venv.EnvBuilder(clear=True, with_pip=True, symlinks=False)
|
builder = venv.EnvBuilder(clear=True, with_pip=True, symlinks=False)
|
||||||
|
@ -344,7 +362,7 @@ class VirtualEnvironment:
|
||||||
|
|
||||||
env = cls(target)
|
env = cls(target)
|
||||||
|
|
||||||
# we do this here to ensure that outdated system default pip does not trigger older bugs
|
# this ensures that outdated system default pip does not trigger older bugs
|
||||||
env.pip("install", "--disable-pip-version-check", "--upgrade", "pip")
|
env.pip("install", "--disable-pip-version-check", "--upgrade", "pip")
|
||||||
|
|
||||||
return env
|
return env
|
||||||
|
@ -376,32 +394,32 @@ class Cursor:
|
||||||
self._output = sys.stdout
|
self._output = sys.stdout
|
||||||
|
|
||||||
def move_up(self, lines: int = 1) -> "Cursor":
|
def move_up(self, lines: int = 1) -> "Cursor":
|
||||||
self._output.write("\x1b[{}A".format(lines))
|
self._output.write(f"\x1b[{lines}A")
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def move_down(self, lines: int = 1) -> "Cursor":
|
def move_down(self, lines: int = 1) -> "Cursor":
|
||||||
self._output.write("\x1b[{}B".format(lines))
|
self._output.write(f"\x1b[{lines}B")
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def move_right(self, columns: int = 1) -> "Cursor":
|
def move_right(self, columns: int = 1) -> "Cursor":
|
||||||
self._output.write("\x1b[{}C".format(columns))
|
self._output.write(f"\x1b[{columns}C")
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def move_left(self, columns: int = 1) -> "Cursor":
|
def move_left(self, columns: int = 1) -> "Cursor":
|
||||||
self._output.write("\x1b[{}D".format(columns))
|
self._output.write(f"\x1b[{columns}D")
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def move_to_column(self, column: int) -> "Cursor":
|
def move_to_column(self, column: int) -> "Cursor":
|
||||||
self._output.write("\x1b[{}G".format(column))
|
self._output.write(f"\x1b[{column}G")
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def move_to_position(self, column: int, row: int) -> "Cursor":
|
def move_to_position(self, column: int, row: int) -> "Cursor":
|
||||||
self._output.write("\x1b[{};{}H".format(row + 1, column))
|
self._output.write(f"\x1b[{row + 1};{column}H")
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -486,9 +504,26 @@ class Installer:
|
||||||
self._accept_all = accept_all
|
self._accept_all = accept_all
|
||||||
self._git = git
|
self._git = git
|
||||||
self._path = path
|
self._path = path
|
||||||
self._data_dir = data_dir()
|
|
||||||
self._bin_dir = bin_dir()
|
|
||||||
self._cursor = Cursor()
|
self._cursor = Cursor()
|
||||||
|
self._bin_dir = None
|
||||||
|
self._data_dir = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bin_dir(self) -> Path:
|
||||||
|
if not self._bin_dir:
|
||||||
|
self._bin_dir = bin_dir()
|
||||||
|
return self._bin_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data_dir(self) -> Path:
|
||||||
|
if not self._data_dir:
|
||||||
|
self._data_dir = data_dir()
|
||||||
|
return self._data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def version_file(self) -> Path:
|
||||||
|
return self.data_dir.joinpath("VERSION")
|
||||||
|
|
||||||
def allows_prereleases(self) -> bool:
|
def allows_prereleases(self) -> bool:
|
||||||
return self._preview
|
return self._preview
|
||||||
|
@ -514,18 +549,20 @@ class Installer:
|
||||||
mx = self.VERSION_REGEX.match(x)
|
mx = self.VERSION_REGEX.match(x)
|
||||||
|
|
||||||
if mx is None:
|
if mx is None:
|
||||||
# the version is not semver, perhaps scm or file, we assume upgrade is supported
|
# the version is not semver, perhaps scm or file
|
||||||
|
# we assume upgrade is supported
|
||||||
return True
|
return True
|
||||||
|
|
||||||
vx = tuple(int(p) for p in mx.groups()[:3]) + (mx.group(5),)
|
vx = (*tuple(int(p) for p in mx.groups()[:3]), mx.group(5))
|
||||||
return vx >= (1, 1, 7)
|
return vx >= (1, 1, 7)
|
||||||
|
|
||||||
if version and not _is_self_upgrade_supported(version):
|
if version and not _is_self_upgrade_supported(version):
|
||||||
self._write(
|
self._write(
|
||||||
colorize(
|
colorize(
|
||||||
"warning",
|
"warning",
|
||||||
f"You are installing {version}. When using the current installer, this version does not support "
|
f"You are installing {version}. When using the current installer, "
|
||||||
f"updating using the 'self update' command. Please use 1.1.7 or later.",
|
"this version does not support updating using the 'self update' "
|
||||||
|
"command. Please use 1.1.7 or later.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if not self._accept_all:
|
if not self._accept_all:
|
||||||
|
@ -538,14 +575,14 @@ class Installer:
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
raise PoetryInstallationError(
|
raise PoetryInstallationError(
|
||||||
return_code=e.returncode, log=e.output.decode()
|
return_code=e.returncode, log=e.output.decode()
|
||||||
)
|
) from e
|
||||||
|
|
||||||
self._write("")
|
self._write("")
|
||||||
self.display_post_message(version)
|
self.display_post_message(version)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def install(self, version, upgrade=False):
|
def install(self, version):
|
||||||
"""
|
"""
|
||||||
Installs Poetry in $POETRY_HOME.
|
Installs Poetry in $POETRY_HOME.
|
||||||
"""
|
"""
|
||||||
|
@ -558,13 +595,13 @@ class Installer:
|
||||||
with self.make_env(version) as env:
|
with self.make_env(version) as env:
|
||||||
self.install_poetry(version, env)
|
self.install_poetry(version, env)
|
||||||
self.make_bin(version, env)
|
self.make_bin(version, env)
|
||||||
self._data_dir.joinpath("VERSION").write_text(version)
|
self.version_file.write_text(version)
|
||||||
self._install_comment(version, "Done")
|
self._install_comment(version, "Done")
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def uninstall(self) -> int:
|
def uninstall(self) -> int:
|
||||||
if not self._data_dir.exists():
|
if not self.data_dir.exists():
|
||||||
self._write(
|
self._write(
|
||||||
"{} is not currently installed.".format(colorize("info", "Poetry"))
|
"{} is not currently installed.".format(colorize("info", "Poetry"))
|
||||||
)
|
)
|
||||||
|
@ -572,8 +609,8 @@ class Installer:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
version = None
|
version = None
|
||||||
if self._data_dir.joinpath("VERSION").exists():
|
if self.version_file.exists():
|
||||||
version = self._data_dir.joinpath("VERSION").read_text().strip()
|
version = self.version_file.read_text().strip()
|
||||||
|
|
||||||
if version:
|
if version:
|
||||||
self._write(
|
self._write(
|
||||||
|
@ -584,10 +621,10 @@ class Installer:
|
||||||
else:
|
else:
|
||||||
self._write("Removing {}".format(colorize("info", "Poetry")))
|
self._write("Removing {}".format(colorize("info", "Poetry")))
|
||||||
|
|
||||||
shutil.rmtree(str(self._data_dir))
|
shutil.rmtree(str(self.data_dir))
|
||||||
for script in ["poetry", "poetry.bat"]:
|
for script in ["poetry", "poetry.bat", "poetry.exe"]:
|
||||||
if self._bin_dir.joinpath(script).exists():
|
if self.bin_dir.joinpath(script).exists():
|
||||||
self._bin_dir.joinpath(script).unlink()
|
self.bin_dir.joinpath(script).unlink()
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ -602,7 +639,7 @@ class Installer:
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def make_env(self, version: str) -> VirtualEnvironment:
|
def make_env(self, version: str) -> VirtualEnvironment:
|
||||||
env_path = self._data_dir.joinpath("venv")
|
env_path = self.data_dir.joinpath("venv")
|
||||||
env_path_saved = env_path.with_suffix(".save")
|
env_path_saved = env_path.with_suffix(".save")
|
||||||
|
|
||||||
if env_path.exists():
|
if env_path.exists():
|
||||||
|
@ -634,20 +671,20 @@ class Installer:
|
||||||
|
|
||||||
def make_bin(self, version: str, env: VirtualEnvironment) -> None:
|
def make_bin(self, version: str, env: VirtualEnvironment) -> None:
|
||||||
self._install_comment(version, "Creating script")
|
self._install_comment(version, "Creating script")
|
||||||
self._bin_dir.mkdir(parents=True, exist_ok=True)
|
self.bin_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
script = "poetry.exe" if WINDOWS else "poetry"
|
script = "poetry.exe" if WINDOWS else "poetry"
|
||||||
target_script = env.bin_path.joinpath(script)
|
target_script = env.bin_path.joinpath(script)
|
||||||
|
|
||||||
if self._bin_dir.joinpath(script).exists():
|
if self.bin_dir.joinpath(script).exists():
|
||||||
self._bin_dir.joinpath(script).unlink()
|
self.bin_dir.joinpath(script).unlink()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._bin_dir.joinpath(script).symlink_to(target_script)
|
self.bin_dir.joinpath(script).symlink_to(target_script)
|
||||||
except OSError:
|
except OSError:
|
||||||
# This can happen if the user
|
# This can happen if the user
|
||||||
# does not have the correct permission on Windows
|
# does not have the correct permission on Windows
|
||||||
shutil.copy(target_script, self._bin_dir.joinpath(script))
|
shutil.copy(target_script, self.bin_dir.joinpath(script))
|
||||||
|
|
||||||
def install_poetry(self, version: str, env: VirtualEnvironment) -> None:
|
def install_poetry(self, version: str, env: VirtualEnvironment) -> None:
|
||||||
self._install_comment(version, "Installing Poetry")
|
self._install_comment(version, "Installing Poetry")
|
||||||
|
@ -664,7 +701,7 @@ class Installer:
|
||||||
def display_pre_message(self) -> None:
|
def display_pre_message(self) -> None:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"poetry": colorize("info", "Poetry"),
|
"poetry": colorize("info", "Poetry"),
|
||||||
"poetry_home_bin": colorize("comment", self._bin_dir),
|
"poetry_home_bin": colorize("comment", self.bin_dir),
|
||||||
}
|
}
|
||||||
self._write(PRE_MESSAGE.format(**kwargs))
|
self._write(PRE_MESSAGE.format(**kwargs))
|
||||||
|
|
||||||
|
@ -681,17 +718,17 @@ class Installer:
|
||||||
path = self.get_windows_path_var()
|
path = self.get_windows_path_var()
|
||||||
|
|
||||||
message = POST_MESSAGE_NOT_IN_PATH
|
message = POST_MESSAGE_NOT_IN_PATH
|
||||||
if path and str(self._bin_dir) in path:
|
if path and str(self.bin_dir) in path:
|
||||||
message = POST_MESSAGE
|
message = POST_MESSAGE
|
||||||
|
|
||||||
self._write(
|
self._write(
|
||||||
message.format(
|
message.format(
|
||||||
poetry=colorize("info", "Poetry"),
|
poetry=colorize("info", "Poetry"),
|
||||||
version=colorize("b", version),
|
version=colorize("b", version),
|
||||||
poetry_home_bin=colorize("comment", self._bin_dir),
|
poetry_home_bin=colorize("comment", self.bin_dir),
|
||||||
poetry_executable=colorize("b", self._bin_dir.joinpath("poetry")),
|
poetry_executable=colorize("b", self.bin_dir.joinpath("poetry")),
|
||||||
configure_message=POST_MESSAGE_CONFIGURE_WINDOWS.format(
|
configure_message=POST_MESSAGE_CONFIGURE_WINDOWS.format(
|
||||||
poetry_home_bin=colorize("comment", self._bin_dir)
|
poetry_home_bin=colorize("comment", self.bin_dir)
|
||||||
),
|
),
|
||||||
test_command=colorize("b", "poetry --version"),
|
test_command=colorize("b", "poetry --version"),
|
||||||
)
|
)
|
||||||
|
@ -700,11 +737,12 @@ class Installer:
|
||||||
def get_windows_path_var(self) -> Optional[str]:
|
def get_windows_path_var(self) -> Optional[str]:
|
||||||
import winreg
|
import winreg
|
||||||
|
|
||||||
with winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) as root:
|
with winreg.ConnectRegistry(
|
||||||
with winreg.OpenKey(root, "Environment", 0, winreg.KEY_ALL_ACCESS) as key:
|
None, winreg.HKEY_CURRENT_USER
|
||||||
path, _ = winreg.QueryValueEx(key, "PATH")
|
) as root, winreg.OpenKey(root, "Environment", 0, winreg.KEY_ALL_ACCESS) as key:
|
||||||
|
path, _ = winreg.QueryValueEx(key, "PATH")
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def display_post_message_fish(self, version: str) -> None:
|
def display_post_message_fish(self, version: str) -> None:
|
||||||
fish_user_paths = subprocess.check_output(
|
fish_user_paths = subprocess.check_output(
|
||||||
|
@ -712,17 +750,17 @@ class Installer:
|
||||||
).decode("utf-8")
|
).decode("utf-8")
|
||||||
|
|
||||||
message = POST_MESSAGE_NOT_IN_PATH
|
message = POST_MESSAGE_NOT_IN_PATH
|
||||||
if fish_user_paths and str(self._bin_dir) in fish_user_paths:
|
if fish_user_paths and str(self.bin_dir) in fish_user_paths:
|
||||||
message = POST_MESSAGE
|
message = POST_MESSAGE
|
||||||
|
|
||||||
self._write(
|
self._write(
|
||||||
message.format(
|
message.format(
|
||||||
poetry=colorize("info", "Poetry"),
|
poetry=colorize("info", "Poetry"),
|
||||||
version=colorize("b", version),
|
version=colorize("b", version),
|
||||||
poetry_home_bin=colorize("comment", self._bin_dir),
|
poetry_home_bin=colorize("comment", self.bin_dir),
|
||||||
poetry_executable=colorize("b", self._bin_dir.joinpath("poetry")),
|
poetry_executable=colorize("b", self.bin_dir.joinpath("poetry")),
|
||||||
configure_message=POST_MESSAGE_CONFIGURE_FISH.format(
|
configure_message=POST_MESSAGE_CONFIGURE_FISH.format(
|
||||||
poetry_home_bin=colorize("comment", self._bin_dir)
|
poetry_home_bin=colorize("comment", self.bin_dir)
|
||||||
),
|
),
|
||||||
test_command=colorize("b", "poetry --version"),
|
test_command=colorize("b", "poetry --version"),
|
||||||
)
|
)
|
||||||
|
@ -732,30 +770,30 @@ class Installer:
|
||||||
paths = os.getenv("PATH", "").split(":")
|
paths = os.getenv("PATH", "").split(":")
|
||||||
|
|
||||||
message = POST_MESSAGE_NOT_IN_PATH
|
message = POST_MESSAGE_NOT_IN_PATH
|
||||||
if paths and str(self._bin_dir) in paths:
|
if paths and str(self.bin_dir) in paths:
|
||||||
message = POST_MESSAGE
|
message = POST_MESSAGE
|
||||||
|
|
||||||
self._write(
|
self._write(
|
||||||
message.format(
|
message.format(
|
||||||
poetry=colorize("info", "Poetry"),
|
poetry=colorize("info", "Poetry"),
|
||||||
version=colorize("b", version),
|
version=colorize("b", version),
|
||||||
poetry_home_bin=colorize("comment", self._bin_dir),
|
poetry_home_bin=colorize("comment", self.bin_dir),
|
||||||
poetry_executable=colorize("b", self._bin_dir.joinpath("poetry")),
|
poetry_executable=colorize("b", self.bin_dir.joinpath("poetry")),
|
||||||
configure_message=POST_MESSAGE_CONFIGURE_UNIX.format(
|
configure_message=POST_MESSAGE_CONFIGURE_UNIX.format(
|
||||||
poetry_home_bin=colorize("comment", self._bin_dir)
|
poetry_home_bin=colorize("comment", self.bin_dir)
|
||||||
),
|
),
|
||||||
test_command=colorize("b", "poetry --version"),
|
test_command=colorize("b", "poetry --version"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def ensure_directories(self) -> None:
|
def ensure_directories(self) -> None:
|
||||||
self._data_dir.mkdir(parents=True, exist_ok=True)
|
self.data_dir.mkdir(parents=True, exist_ok=True)
|
||||||
self._bin_dir.mkdir(parents=True, exist_ok=True)
|
self.bin_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
def get_version(self):
|
def get_version(self):
|
||||||
current_version = None
|
current_version = None
|
||||||
if self._data_dir.joinpath("VERSION").exists():
|
if self.version_file.exists():
|
||||||
current_version = self._data_dir.joinpath("VERSION").read_text().strip()
|
current_version = self.version_file.read_text().strip()
|
||||||
|
|
||||||
self._write(colorize("info", "Retrieving Poetry metadata"))
|
self._write(colorize("info", "Retrieving Poetry metadata"))
|
||||||
|
|
||||||
|
@ -765,8 +803,8 @@ class Installer:
|
||||||
mx = self.VERSION_REGEX.match(x)
|
mx = self.VERSION_REGEX.match(x)
|
||||||
my = self.VERSION_REGEX.match(y)
|
my = self.VERSION_REGEX.match(y)
|
||||||
|
|
||||||
vx = tuple(int(p) for p in mx.groups()[:3]) + (mx.group(5),)
|
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),)
|
vy = (*tuple(int(p) for p in my.groups()[:3]), my.group(5))
|
||||||
|
|
||||||
if vx < vy:
|
if vx < vy:
|
||||||
return -1
|
return -1
|
||||||
|
@ -781,7 +819,7 @@ class Installer:
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._version and self._version not in releases:
|
if self._version and self._version not in releases:
|
||||||
msg = "Version {} does not exist.".format(self._version)
|
msg = f"Version {self._version} does not exist."
|
||||||
self._write(colorize("error", msg))
|
self._write(colorize("error", msg))
|
||||||
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
@ -799,9 +837,7 @@ class Installer:
|
||||||
|
|
||||||
if current_version == version and not self._force:
|
if current_version == version and not self._force:
|
||||||
self._write(
|
self._write(
|
||||||
"The latest version ({}) is already installed.".format(
|
f'The latest version ({colorize("b", version)}) is already installed.'
|
||||||
colorize("b", version)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return None, current_version
|
return None, current_version
|
||||||
|
@ -912,7 +948,8 @@ def main():
|
||||||
text=True,
|
text=True,
|
||||||
)
|
)
|
||||||
installer._write(colorize("error", f"See {path} for error logs."))
|
installer._write(colorize("error", f"See {path} for error logs."))
|
||||||
text = f"{e.log}\nTraceback:\n\n{''.join(traceback.format_tb(e.__traceback__))}"
|
tb = "".join(traceback.format_tb(e.__traceback__))
|
||||||
|
text = f"{e.log}\nTraceback:\n\n{tb}"
|
||||||
Path(path).write_text(text)
|
Path(path).write_text(text)
|
||||||
|
|
||||||
return e.return_code
|
return e.return_code
|
||||||
|
|
|
@ -1,12 +1,29 @@
|
||||||
[tool.isort]
|
[tool.ruff]
|
||||||
profile = "black"
|
fix = true
|
||||||
force_single_line = true
|
unfixable = [
|
||||||
atomic = true
|
"ERA", # do not autoremove commented out code
|
||||||
lines_after_imports = 2
|
]
|
||||||
lines_between_types = 1
|
target-version = "py37"
|
||||||
filter_files = true
|
|
||||||
|
|
||||||
|
|
||||||
[tool.black]
|
|
||||||
line-length = 88
|
line-length = 88
|
||||||
include = '\.pyi?$'
|
extend-select = [
|
||||||
|
"B", # flake8-bugbear
|
||||||
|
"C4", # flake8-comprehensions
|
||||||
|
"ERA", # flake8-eradicate/eradicate
|
||||||
|
"I", # isort
|
||||||
|
"N", # pep8-naming
|
||||||
|
"PIE", # flake8-pie
|
||||||
|
"PGH", # pygrep
|
||||||
|
"RUF", # ruff checks
|
||||||
|
"SIM", # flake8-simplify
|
||||||
|
"TCH", # flake8-type-checking
|
||||||
|
"TID", # flake8-tidy-imports
|
||||||
|
"UP", # pyupgrade
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.flake8-tidy-imports]
|
||||||
|
ban-relative-imports = "all"
|
||||||
|
|
||||||
|
[tool.ruff.isort]
|
||||||
|
force-single-line = true
|
||||||
|
lines-between-types = 1
|
||||||
|
lines-after-imports = 2
|
||||||
|
|
Loading…
Reference in a new issue