KeyAlreadyPresent error when adding atlassian-python-api
See original GitHub issue-
I am on the latest Poetry version.
-
I have searched the issues of this repo and believe that this is not a duplicate.
-
If an exception occurs when executing a command, I executed it again in debug mode (
-vvv
option). -
OS version and name: Ubuntu 20.04.2 LTS
-
Poetry version: 1.1.7
-
Link of a Gist with the contents of your pyproject.toml file: https://github.com/austinbutler/poetry-keyalreadypresent/runs/3050293838
Issue
I have an existing project that was working fine with atlassian-python-api
at version 3.5.2
. Running poetry update
resulted in:
KeyAlreadyPresent
Key "REPORTS" already exists.
at /nix/store/jkj0kadrnm5bf2mral3ylkzdbrrf4mwy-python3.9-tomlkit-0.7.0/lib/python3.9/site-packages/tomlkit/container.py:176 in append
172β return self
173β elif current_body_element[0].is_dotted():
174β raise TOMLKitError("Redefinition of an existing table")
175β elif not item.is_super_table():
β 176β raise KeyAlreadyPresent(key)
177β elif isinstance(item, AoT):
178β if not isinstance(current, AoT):
179β # Tried to define an AoT after a table with the same name.
180β raise KeyAlreadyPresent(key)
Iβm using a private PyPi repo, though, so I created a very simple repro that simply tries poetry add atlassian-python-api
on a nearly empty project (linked above), and I get the same error there.
I downloaded the tar file for atlassian-python-api and if I grep for REPORTS
I get one single hit from their pyproject.toml
file:
/Users/abutler/Downloads/atlassian-python-api-3.12.1/pyproject.toml
171:[tool.pylint.REPORTS]
Full log from the GitHub action run:
Creating virtualenv error-repro-VVz8odaq-py3.9 in /home/runner/.cache/pypoetry/virtualenvs
Using virtualenv: /home/runner/.cache/pypoetry/virtualenvs/error-repro-VVz8odaq-py3.9
PyPI: 167 packages found for atlassian-python-api *
Using version ^3.12.1 for atlassian-python-api
Updating dependencies
Resolving dependencies...
1: fact: error-repro is 0.1.0
1: derived: error-repro
1: fact: error-repro depends on atlassian-python-api (^3.12.1)
1: fact: error-repro depends on pytest (^5.2)
1: fact: error-repro depends on pytest (^5.2)
1: selecting error-repro (0.1.0)
1: derived: pytest (>=5.2,<6.0)
1: derived: atlassian-python-api (>=3.12.1,<4.0.0)
PyPI: 15 packages found for pytest >=5.2,<6.0
PyPI: 1 packages found for atlassian-python-api >=3.12.1,<4.0.0
PyPI: Getting info for atlassian-python-api (3.12.1) from PyPI
PyPI: No dependencies found, downloading archives
PyPI: Downloading sdist: atlassian-python-api-3.12.1.tar.gz
1: Version solving took 0.296 seconds.
1: Tried 1 solutions.
Stack trace:
33 ~/.poetry/lib/poetry/_vendor/py3.9/clikit/console_application.py:131 in run
129β parsed_args = resolved_command.args
130β
β 131β status_code = command.handle(parsed_args, io)
132β except KeyboardInterrupt:
133β status_code = 1
32 ~/.poetry/lib/poetry/_vendor/py3.9/clikit/api/command/command.py:120 in handle
118β def handle(self, args, io): # type: (Args, IO) -> int
119β try:
β 120β status_code = self._do_handle(args, io)
121β except KeyboardInterrupt:
122β if io.is_debug():
31 ~/.poetry/lib/poetry/_vendor/py3.9/clikit/api/command/command.py:171 in _do_handle
169β handler_method = self._config.handler_method
170β
β 171β return getattr(handler, handler_method)(args, io, self)
172β
173β def __repr__(self): # type: () -> str
30 ~/.poetry/lib/poetry/_vendor/py3.9/cleo/commands/command.py:92 in wrap_handle
90β self._command = command
91β
β 92β return self.handle()
93β
94β def handle(self): # type: () -> Optional[int]
29 ~/.poetry/lib/poetry/console/commands/add.py:173 in handle
171β self._installer.whitelist([r["name"] for r in requirements])
172β
β 173β status = self._installer.run()
174β except BaseException:
175β # Using BaseException here as some exceptions, eg: KeyboardInterrupt, do not inherit from Exception
28 ~/.poetry/lib/poetry/installation/installer.py:103 in run
101β local_repo = Repository()
102β
β 103β return self._do_install(local_repo)
104β
105β def dry_run(self, dry_run=True): # type: (bool) -> Installer
27 ~/.poetry/lib/poetry/installation/installer.py:235 in _do_install
233β )
234β
β 235β ops = solver.solve(use_latest=self._whitelist)
236β else:
237β self._io.write_line("Installing dependencies from lock file")
26 ~/.poetry/lib/poetry/puzzle/solver.py:65 in solve
63β with self._provider.progress():
64β start = time.time()
β 65β packages, depths = self._solve(use_latest=use_latest)
66β end = time.time()
67β
25 ~/.poetry/lib/poetry/puzzle/solver.py:233 in _solve
231β
232β try:
β 233β result = resolve_version(
234β self._package, self._provider, locked=locked, use_latest=use_latest
235β )
24 ~/.poetry/lib/poetry/mixology/__init__.py:7 in resolve_version
5β solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest)
6β
β 7β return solver.solve()
8β
23 ~/.poetry/lib/poetry/mixology/version_solver.py:84 in solve
82β while next is not None:
83β self._propagate(next)
β 84β next = self._choose_package_version()
85β
86β return self._result()
22 ~/.poetry/lib/poetry/mixology/version_solver.py:400 in _choose_package_version
398β version = locked
399β
β 400β version = self._provider.complete_package(version)
401β
402β conflict = False
21 ~/.poetry/lib/poetry/puzzle/provider.py:433 in complete_package
431β package = DependencyPackage(
432β package.dependency,
β 433β self._pool.package(
434β package.name,
435β package.version.text,
20 ~/.poetry/lib/poetry/repositories/pool.py:135 in package
133β for idx, repo in enumerate(self._repositories):
134β try:
β 135β package = repo.package(name, version, extras=extras)
136β except PackageNotFound:
137β continue
19 ~/.poetry/lib/poetry/repositories/pypi_repository.py:158 in package
156β extras=None, # type: (Union[list, None])
157β ): # type: (...) -> Package
β 158β return self.get_release_info(name, version).to_package(name=name, extras=extras)
159β
160β def search(self, query):
18 ~/.poetry/lib/poetry/repositories/pypi_repository.py:223 in get_release_info
221β return PackageInfo.load(self._get_release_info(name, version))
222β
β 223β cached = self._cache.remember_forever(
224β "{}:{}".format(name, version), lambda: self._get_release_info(name, version)
225β )
17 ~/.poetry/lib/poetry/_vendor/py3.9/cachy/repository.py:174 in remember_forever
172β return val
173β
β 174β val = value(callback)
175β
176β self.forever(key, val)
16 ~/.poetry/lib/poetry/_vendor/py3.9/cachy/helpers.py:6 in value
4β def value(val):
5β if callable(val):
β 6β return val()
7β
8β return val
15 ~/.poetry/lib/poetry/repositories/pypi_repository.py:224 in <lambda>
222β
223β cached = self._cache.remember_forever(
β 224β "{}:{}".format(name, version), lambda: self._get_release_info(name, version)
225β )
226β
14 ~/.poetry/lib/poetry/repositories/pypi_repository.py:304 in _get_release_info
302β return data.asdict()
303β
β 304β info = self._get_info_from_urls(urls)
305β
306β data.requires_dist = info.requires_dist
13 ~/.poetry/lib/poetry/repositories/pypi_repository.py:419 in _get_info_from_urls
417β return self._get_info_from_wheel(platform_specific_wheels[0])
418β
β 419β return self._get_info_from_sdist(urls["sdist"][0])
420β
421β def _get_info_from_wheel(self, url): # type: (str) -> PackageInfo
12 ~/.poetry/lib/poetry/repositories/pypi_repository.py:447 in _get_info_from_sdist
445β self._download(url, str(filepath))
446β
β 447β return PackageInfo.from_sdist(filepath)
448β
449β def _download(self, url, dest): # type: (str, str) -> None
11 ~/.poetry/lib/poetry/inspection/info.py:561 in from_sdist
559β """
560β if path.is_file():
β 561β return cls._from_sdist_file(path=path)
562β
563β # if we get here then it is neither an sdist instance nor a file
10 ~/.poetry/lib/poetry/inspection/info.py:291 in _from_sdist_file
289β
290β # now this is an unpacked directory we know how to deal with
β 291β new_info = cls.from_directory(path=sdist_dir)
292β
293β if not info:
9 ~/.poetry/lib/poetry/inspection/info.py:530 in from_directory
528β order to gather metadata.
529β """
β 530β project_package = cls._get_poetry_package(path)
531β if project_package:
532β info = cls.from_package(project_package)
8 ~/.poetry/lib/poetry/inspection/info.py:439 in _get_poetry_package
437β # Note: we ignore any setup.py file at this step
438β # TODO: add support for handling non-poetry PEP-517 builds
β 439β if PyProjectTOML(path.joinpath("pyproject.toml")).is_poetry_project():
440β return Factory().create_poetry(path).package
441β
7 ~/.poetry/lib/poetry/_vendor/py3.9/poetry/core/pyproject/toml.py:64 in is_poetry_project
62β if self.file.exists():
63β try:
β 64β _ = self.poetry_config
65β return True
66β except PyProjectException:
6 ~/.poetry/lib/poetry/_vendor/py3.9/poetry/core/pyproject/toml.py:54 in poetry_config
52β def poetry_config(self): # type: () -> Optional[TOMLDocument]
53β if self._poetry_config is None:
β 54β self._poetry_config = self.data.get("tool", {}).get("poetry")
55β if self._poetry_config is None:
56β raise PyProjectException(
5 /opt/hostedtoolcache/Python/3.9.5/x64/lib/python3.9/_collections_abc.py:762 in get
760β 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.'
761β try:
β 762β return self[key]
763β except KeyError:
764β return default
4 ~/.poetry/lib/poetry/_vendor/py3.9/tomlkit/container.py:559 in __getitem__
557β # so we need a proxy to retrieve the proper objects
558β # from the parent container
β 559β return OutOfOrderTableProxy(self, idx)
560β
561β item = self._body[idx][1]
3 ~/.poetry/lib/poetry/_vendor/py3.9/tomlkit/container.py:699 in __init__
697β table_idx = len(self._tables) - 1
698β for k, v in item.value.body:
β 699β self._internal_container.append(k, v)
700β self._tables_map[k] = table_idx
701β if k is not None:
2 ~/.poetry/lib/poetry/_vendor/py3.9/tomlkit/container.py:169 in append
167β
168β for k, v in item.value.body:
β 169β current.append(k, v)
170β
171β return self
1 ~/.poetry/lib/poetry/_vendor/py3.9/tomlkit/items.py:922 in append
920β _item = item(_item)
921β
β 922β self._value.append(key, _item)
923β
924β if isinstance(key, Key):
KeyAlreadyPresent
Key "REPORTS" already exists.
at ~/.poetry/lib/poetry/_vendor/py3.9/tomlkit/container.py:175 in append
171β return self
172β elif current_body_element[0].is_dotted():
173β raise TOMLKitError("Redefinition of an existing table")
174β elif not item.is_super_table():
β 175β raise KeyAlreadyPresent(key)
176β elif isinstance(item, AoT):
177β if not isinstance(current, AoT):
178β # Tried to define an AoT after a table with the same name.
179β raise KeyAlreadyPresent(key)
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:7 (1 by maintainers)
You can install from my fork to get around this for now.
Note though that I branched from master, which has some commits not yet released.
Seems like TOML Kit is tripped up by
['tool.pylint.MESSAGES CONTROL']
in thepyproject.toml
. If I change that to[tool.pylint.'MESSAGES CONTROL']
thereβs no longer a duplicate table name. Opened a PRatlassian-python-api
to βfixβ that (not intimately familiar with TOML so not entirely sure whether itβs actually invalid). Also created an issue with TOML Kit. Since Poetry is not at fault this can probably be closed. I could close it myself, but not sure if itβs handy to have open in case others end up with the same issue and come here.