Skip to content

Commit bf12e42

Browse files
sdispatertommilligandcramerfinswimmeraltendky
authored
Merge master into develop (#2206)
* export: fix exporting extras sub-dependencies (#1294) * Support POETRY_HOME for install (#794) Allow the `POETRY_HOME` environment variable to be passed during installation to change the default installation directory of `~/.poetry`: ``` POETRY_HOME=/etc/poetry python get-poetry.py ``` * * check if relative filename is in excluded file list (#1459) * * check if relative filename is in excluded file list * removed find_excluded_files() method from wheel.py * added test for excluding files in wheels * creating an own test data folder, for testing excluding files by pyproject.toml * use as_posix() to respect windows file path delimiters * Exclude nested items (#784) (#1464) * This PR impliments the feature request #784. When a folder is explicit defined in `pyproject.toml` as excluded, all nested data, including subfolder, are excluded. It is no longer neccessary to use the glob `folder/**/*` * use `Path` instead of `os.path.join` to create string for globbing * try to fix linting error * create glob pattern string by concatenating and not using Path * using `os.path.isdir()`` for checking of explicit excluded name is a folder, because pathlib's `is_dir()` raises in exception under windows of name contains globing characters * Remove nested data when wildcards where used. Steps to do this are: 1. expand any wildcard used 2. if expanded path is a folder append **/* and expand again * fix linting * only glob a second time if path is dir * implement @sdispater 's suggestion for better readability * fix glob for windows? * On Windows, testing if a path with a glob is a directory will raise an OSError * pathlibs glob function doesn't return the correct case (https://bugs.python.org/issue26655). So switching back to glob.glob() * removing obsolete imports * Update dependencies * Deprecate allows-prereleases in favor of allow-prereleases for consistency * Fix tests for Python 2.7 * Fix linting * Fix linting * Fix linting * Fix typing import * Correct a couple typos in get-poetry.py (#573) * Docs: `self:update` changed to `self update` (#1588) * Fix GitHub actions cache issues on develop (#1918) * Fix Github actions cache issues * Fix Github Actions cache issues (#1928) * Add --source option to "poetry add" (#1912) * Add --source option to 'poetry add' * Add tests for 'poetry add --source' * Merge master into develop (#2070) * Fix Github actions cache issues (#1908) * Fix case of `-f` flag * Make it clearer what options to pass to `--format` * fix (masonry.api): `get_requires_for_build_wheel` must return additional list of requirements for building a package, not listed in `pyproject.toml` and not dependencies for the package itself (#1875) fix (tests): adopted tests * Lazy Keyring intialization for PasswordManager (#1892) * Fix Github Actions cache issues (#1928) * Avoid nested quantifiers with overlapping character space on git url parsing (#1902 (#1913) * fix (git): match for `\w` instead of `.` for getting user * change (vcs.git): hold pattern of the regex parts in a dictionary to be consistent over all regexs * new (vcs.git): test for `parse_url` and some fixes for the regex pattern * new (vcs.git): test for `parse_url` with string that should fail * fix (test.vcs.git): make flake8 happy * fix: correct parsing of wheel version with regex. (#1932) The previous regexp was only taking the first integer of the version number, this presented problems when the major version number reached double digits. Poetry would determine that the version of the dependency is '1', rather than, ie: '14'. This caused failures to solve versions. * Fix errors when using the --help option (#1910) * Fix how repository credentials are retrieved from env vars (#1909) # Conflicts: # poetry/utils/password_manager.py * Fix downloading packages from Simplepypi (#1851) * fix downloading packages from simplepypi * unused code removed * remove unused imports * Upgrade dependencies for the 1.0.3 release (#1965) * Bump version to 1.0.3 (#1966) * Fix non-compliant Git URL matching RFC 3986 § 2.3 permits more characters in a URL than were matched. This corrects that, though there may be other deficiencies. This was a regression from v1.0.2, where at least “.” was matched without error. * Update README.md "Updating Poetry" Currently the note in "Updating Poetry" is different from the one below in "Enable tab completion for Bash, Fish, or Zsh". This MR is to make them more consistent. * init: change dev dependency prompt * Fix CI issues (#2069) Co-authored-by: brandonaut <[email protected]> Co-authored-by: finswimmer <[email protected]> Co-authored-by: Yannick PÉROUX <[email protected]> Co-authored-by: Edward George <[email protected]> Co-authored-by: Jan Škoda <[email protected]> Co-authored-by: Andrew Marshall <[email protected]> Co-authored-by: Andrew Selzer <[email protected]> Co-authored-by: Andrii Maletskyi <[email protected]> * pre-commit: replace isort mirror with isort upstream (#2118) The isort pre-commit mirror has been deprecated. This change updates configuration to use the upstream package repository instead of the mirror. * Add cache list command (#1187) * Add poetry.locations.REPOSITORY_CACHE_DIR The repository cache directory is used in multiple places in the codebase. This change ensures that the value is reused. * Add cache list command This introduces a new cache sub-command that lists all available caches. Relates-to: #1162 Co-authored-by: Tom Milligan <[email protected]> Co-authored-by: David Cramer <[email protected]> Co-authored-by: finswimmer <[email protected]> Co-authored-by: Kyle Altendorf <[email protected]> Co-authored-by: Justin Mayer <[email protected]> Co-authored-by: Yannick PÉROUX <[email protected]> Co-authored-by: brandonaut <[email protected]> Co-authored-by: Edward George <[email protected]> Co-authored-by: Jan Škoda <[email protected]> Co-authored-by: Andrew Marshall <[email protected]> Co-authored-by: Andrew Selzer <[email protected]> Co-authored-by: Andrii Maletskyi <[email protected]> Co-authored-by: Arun Babu Neelicattu <[email protected]>
1 parent d27a119 commit bf12e42

File tree

14 files changed

+197
-19
lines changed

14 files changed

+197
-19
lines changed

.pre-commit-config.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ repos:
99
hooks:
1010
- id: flake8
1111

12-
- repo: https://github.com/pre-commit/mirrors-isort
13-
rev: v4.3.21
12+
- repo: https://github.com/timothycrosley/isort
13+
rev: 4.3.21
1414
hooks:
1515
- id: isort
1616
additional_dependencies: [toml]

CHANGELOG.md

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
- Fixed an error when parsing some git URLs ([#2018](https://github.com/python-poetry/poetry/pull/2018)).
2828

2929

30-
3130
## [1.0.3] - 2020-01-31
3231

3332
### Fixed

docs/docs/cli.md

+12
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,15 @@ The `env` command regroups sub commands to interact with the virtualenvs
452452
associated with a specific project.
453453

454454
See [Managing environments](./managing-environments.md) for more information about these commands.
455+
456+
## cache
457+
458+
The `cache` command regroups sub commands to interact with Poetry's cache.
459+
460+
### cache list
461+
462+
The `cache list` command lists Poetry's available caches.
463+
464+
```bash
465+
poetry cache list
466+
```

poetry/console/commands/add.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ class AddCommand(EnvCommand, InitCommand):
3333
"Platforms for which the dependency must be installed.",
3434
flag=False,
3535
),
36+
option(
37+
"source",
38+
None,
39+
"Name of the source to use to install the package.",
40+
flag=False,
41+
),
3642
option("allow-prereleases", None, "Accept prereleases."),
3743
option(
3844
"dry-run",
@@ -86,7 +92,9 @@ def handle(self):
8692
raise ValueError("Package {} is already present".format(name))
8793

8894
requirements = self._determine_requirements(
89-
packages, allow_prereleases=self.option("allow-prereleases")
95+
packages,
96+
allow_prereleases=self.option("allow-prereleases"),
97+
source=self.option("source"),
9098
)
9199

92100
for _constraint in requirements:
@@ -123,6 +131,9 @@ def handle(self):
123131
if self.option("platform"):
124132
constraint["platform"] = self.option("platform")
125133

134+
if self.option("source"):
135+
constraint["source"] = self.option("source")
136+
126137
if len(constraint) == 1 and "version" in constraint:
127138
constraint = constraint["version"]
128139

poetry/console/commands/cache/cache.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from poetry.console.commands.cache.list import CacheListCommand
2+
13
from ..command import Command
24
from .clear import CacheClearCommand
35

@@ -7,7 +9,7 @@ class CacheCommand(Command):
79
name = "cache"
810
description = "Interact with Poetry's cache"
911

10-
commands = [CacheClearCommand()]
12+
commands = [CacheClearCommand(), CacheListCommand()]
1113

1214
def handle(self):
1315
return self.call("help", self._config.name)

poetry/console/commands/cache/clear.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,17 @@ class CacheClearCommand(Command):
1616

1717
def handle(self):
1818
from cachy import CacheManager
19-
from poetry.locations import CACHE_DIR
20-
from poetry.utils._compat import Path
19+
from poetry.locations import REPOSITORY_CACHE_DIR
2120

2221
cache = self.argument("cache")
2322

2423
parts = cache.split(":")
2524
root = parts[0]
2625

27-
base_cache = Path(CACHE_DIR) / "cache" / "repositories"
28-
cache_dir = base_cache / root
26+
cache_dir = REPOSITORY_CACHE_DIR / root
2927

3028
try:
31-
cache_dir.relative_to(base_cache)
29+
cache_dir.relative_to(REPOSITORY_CACHE_DIR)
3230
except ValueError:
3331
raise ValueError("{} is not a valid repository cache".format(root))
3432

poetry/console/commands/cache/list.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import os
2+
3+
from ..command import Command
4+
5+
6+
class CacheListCommand(Command):
7+
8+
name = "list"
9+
description = "List Poetry's caches."
10+
11+
def handle(self):
12+
from poetry.locations import REPOSITORY_CACHE_DIR
13+
14+
if os.path.exists(str(REPOSITORY_CACHE_DIR)):
15+
caches = list(sorted(REPOSITORY_CACHE_DIR.iterdir()))
16+
if caches:
17+
for cache in caches:
18+
self.line("<info>{}</>".format(cache.name))
19+
return 0
20+
21+
self.line("<warning>No caches found</>")

poetry/console/commands/init.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def handle(self):
203203
f.write(content)
204204

205205
def _determine_requirements(
206-
self, requires, allow_prereleases=False
206+
self, requires, allow_prereleases=False, source=None
207207
): # type: (List[str], bool) -> List[Dict[str, str]]
208208
if not requires:
209209
requires = []
@@ -299,7 +299,9 @@ def _determine_requirements(
299299
elif "version" not in requirement:
300300
# determine the best version automatically
301301
name, version = self._find_best_version_for_package(
302-
requirement["name"], allow_prereleases=allow_prereleases
302+
requirement["name"],
303+
allow_prereleases=allow_prereleases,
304+
source=source,
303305
)
304306
requirement["version"] = version
305307
requirement["name"] = name
@@ -314,6 +316,7 @@ def _determine_requirements(
314316
requirement["name"],
315317
requirement["version"],
316318
allow_prereleases=allow_prereleases,
319+
source=source,
317320
)
318321

319322
requirement["name"] = name
@@ -323,13 +326,13 @@ def _determine_requirements(
323326
return result
324327

325328
def _find_best_version_for_package(
326-
self, name, required_version=None, allow_prereleases=False
329+
self, name, required_version=None, allow_prereleases=False, source=None
327330
): # type: (...) -> Tuple[str, str]
328331
from poetry.version.version_selector import VersionSelector
329332

330333
selector = VersionSelector(self._get_pool())
331334
package = selector.find_best_candidate(
332-
name, required_version, allow_prereleases=allow_prereleases
335+
name, required_version, allow_prereleases=allow_prereleases, source=source
333336
)
334337

335338
if not package:

poetry/locations.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
from .utils._compat import Path
12
from .utils.appdirs import user_cache_dir
23
from .utils.appdirs import user_config_dir
34

45

56
CACHE_DIR = user_cache_dir("pypoetry")
67
CONFIG_DIR = user_config_dir("pypoetry")
8+
9+
REPOSITORY_CACHE_DIR = Path(CACHE_DIR) / "cache" / "repositories"

poetry/repositories/legacy_repository.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import poetry.packages
1717

18-
from poetry.locations import CACHE_DIR
18+
from poetry.locations import REPOSITORY_CACHE_DIR
1919
from poetry.packages import Package
2020
from poetry.packages import dependency_from_pep_508
2121
from poetry.packages.utils.link import Link
@@ -174,7 +174,7 @@ def __init__(
174174
self._client_cert = client_cert
175175
self._cert = cert
176176
self._inspector = Inspector()
177-
self._cache_dir = Path(CACHE_DIR) / "cache" / "repositories" / name
177+
self._cache_dir = REPOSITORY_CACHE_DIR / name
178178
self._cache = CacheManager(
179179
{
180180
"default": "releases",

poetry/repositories/pypi_repository.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from requests import session
1616
from requests.exceptions import TooManyRedirects
1717

18-
from poetry.locations import CACHE_DIR
18+
from poetry.locations import REPOSITORY_CACHE_DIR
1919
from poetry.packages import Package
2020
from poetry.packages import dependency_from_pep_508
2121
from poetry.packages.utils.link import Link
@@ -57,7 +57,7 @@ def __init__(self, url="https://pypi.org/", disable_cache=False, fallback=True):
5757
self._disable_cache = disable_cache
5858
self._fallback = fallback
5959

60-
release_cache_dir = Path(CACHE_DIR) / "cache" / "repositories" / "pypi"
60+
release_cache_dir = REPOSITORY_CACHE_DIR / "pypi"
6161
self._cache = CacheManager(
6262
{
6363
"default": "releases",

poetry/version/version_selector.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def find_best_candidate(
1515
package_name, # type: str
1616
target_package_version=None, # type: Union[str, None]
1717
allow_prereleases=False, # type: bool
18+
source=None, # type: str
1819
): # type: (...) -> Union[Package, bool]
1920
"""
2021
Given a package name and optional version,
@@ -26,7 +27,7 @@ def find_best_candidate(
2627
constraint = parse_constraint("*")
2728

2829
candidates = self._pool.find_packages(
29-
package_name, constraint, allow_prereleases=True
30+
package_name, constraint, allow_prereleases=True, repository=source
3031
)
3132
only_prereleases = all([c.version.is_prerelease() for c in candidates])
3233

tests/console/commands/test_add.py

+68
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from cleo.testers import CommandTester
66

7+
from poetry.repositories.legacy_repository import LegacyRepository
8+
from poetry.semver import Version
79
from poetry.utils._compat import Path
810
from tests.helpers import get_dependency
911
from tests.helpers import get_package
@@ -634,6 +636,72 @@ def test_add_constraint_with_platform(app, repo, installer):
634636
}
635637

636638

639+
def test_add_constraint_with_source(app, poetry, installer):
640+
repo = LegacyRepository(name="my-index", url="https://my-index.fake")
641+
repo.add_package(get_package("cachy", "0.2.0"))
642+
repo._cache.store("matches").put("cachy:0.2.0", [Version.parse("0.2.0")], 5)
643+
644+
poetry.pool.add_repository(repo)
645+
646+
command = app.find("add")
647+
tester = CommandTester(command)
648+
649+
tester.execute("cachy=0.2.0 --source my-index")
650+
651+
expected = """\
652+
653+
Updating dependencies
654+
Resolving dependencies...
655+
656+
Writing lock file
657+
658+
659+
Package operations: 1 install, 0 updates, 0 removals
660+
661+
- Installing cachy (0.2.0)
662+
"""
663+
664+
assert expected == tester.io.fetch_output()
665+
666+
assert len(installer.installs) == 1
667+
668+
content = app.poetry.file.read()["tool"]["poetry"]
669+
670+
assert "cachy" in content["dependencies"]
671+
assert content["dependencies"]["cachy"] == {
672+
"version": "0.2.0",
673+
"source": "my-index",
674+
}
675+
676+
677+
def test_add_constraint_with_source_that_does_not_exist(app):
678+
command = app.find("add")
679+
tester = CommandTester(command)
680+
681+
with pytest.raises(ValueError) as e:
682+
tester.execute("foo --source i-dont-exist")
683+
684+
assert 'Repository "i-dont-exist" does not exist.' == str(e.value)
685+
686+
687+
def test_add_constraint_not_found_with_source(app, poetry, mocker):
688+
repo = LegacyRepository(name="my-index", url="https://my-index.fake")
689+
mocker.patch.object(repo, "find_packages", return_value=[])
690+
691+
poetry.pool.add_repository(repo)
692+
693+
pypi = poetry.pool.repositories[0]
694+
pypi.add_package(get_package("cachy", "0.2.0"))
695+
696+
command = app.find("add")
697+
tester = CommandTester(command)
698+
699+
with pytest.raises(ValueError) as e:
700+
tester.execute("cachy --source my-index")
701+
702+
assert "Could not find a matching version of package cachy" == str(e.value)
703+
704+
637705
def test_add_to_section_that_does_no_exist_yet(app, repo, installer):
638706
command = app.find("add")
639707
tester = CommandTester(command)

tests/console/commands/test_cache.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import uuid
2+
3+
import pytest
4+
5+
from cleo.testers import CommandTester
6+
7+
8+
@pytest.fixture
9+
def repository_cache_dir(monkeypatch, tmpdir):
10+
import poetry.locations
11+
from poetry.utils._compat import Path
12+
13+
path = Path(str(tmpdir))
14+
monkeypatch.setattr(poetry.locations, "REPOSITORY_CACHE_DIR", path)
15+
return path
16+
17+
18+
@pytest.fixture
19+
def repository_one():
20+
return "01_{}".format(uuid.uuid4())
21+
22+
23+
@pytest.fixture
24+
def repository_two():
25+
return "02_{}".format(uuid.uuid4())
26+
27+
28+
@pytest.fixture
29+
def mock_caches(repository_cache_dir, repository_one, repository_two):
30+
(repository_cache_dir / repository_one).mkdir()
31+
(repository_cache_dir / repository_two).mkdir()
32+
33+
34+
def test_cache_list(app, mock_caches, repository_one, repository_two):
35+
command = app.find("cache list")
36+
tester = CommandTester(command)
37+
38+
tester.execute()
39+
40+
expected = """\
41+
{}
42+
{}
43+
""".format(
44+
repository_one, repository_two
45+
)
46+
47+
assert expected == tester.io.fetch_output()
48+
49+
50+
def test_cache_list_empty(app, repository_cache_dir):
51+
command = app.find("cache list")
52+
tester = CommandTester(command)
53+
54+
tester.execute()
55+
56+
expected = """\
57+
No caches found
58+
"""
59+
60+
assert expected == tester.io.fetch_output()

0 commit comments

Comments
 (0)