poetry: AttributeError : EmptyConstraint object has no attribute allows

  • 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).
  • Linux Pop!_OS 21.04
  • Poetry 1.1.7
[tool.poetry.dependencies]
python = "^3.8"
click = "*"
python-dotenv = "*"
pandas = "*"
requests = "*"
pydantic = "*"
sqlalchemy = "*"

[tool.poetry.dev-dependencies]
pytest = "^6.2.2"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.black]
skip-string-normalization = true

Issue

image

Tried both with python3.8 and python3.9 resulting in this same error.

AttributeError

  'EmptyConstraint' object has no attribute 'allows'

  at ~/anaconda3/envs/py38/lib/python3.8/site-packages/poetry/core/version/markers.py:291 in validate
      287│ 
      288│         if self._name not in environment:
      289│             return True
      290│ 
    → 291│         return self._constraint.allows(self._parser(environment[self._name]))
      292│ 
      293│     def without_extras(self):  # type: () -> MarkerTypes
      294│         return self.exclude("extra")
      295│ 

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 39
  • Comments: 18 (4 by maintainers)

Most upvoted comments

Seems to be an issue with SQLAlchemy 1.4.23 that was released ~3 hours ago. Can someone open an issue with them if not already? After work, I can submit an issue otherwise

A temporary workaround is pinning to 1.4.22 (sqlalchemy="1.4.22")

the problem seems to be with the newest sqlalchemy in my case …

Put up https://github.com/python-poetry/poetry-core/pull/187. Hopefully it’s correct, and fixes this issue.

From inspecting the object with the EmptyMarker:

(Pdb) self
<SingleMarker platform_machine in "x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64 AMD64 win32 WIN32">
(Pdb) vars(self)
{'_name': Token(markers__MARKER_NAME, 'platform_machine'), '_constraint_string': 'inx86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64 AMD64 win32 WIN32', '_operator': 'in', '_value': 'x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64 AMD64 win32 WIN32', '_parser': <function parse_constraint at 0x7fce5f8cc7a0>, '_constraint': <EmptyConstraint >}

And inspecting my lockfile:

[[package]]
name = "sqlalchemy"
version = "1.4.23"
description = "Database Abstraction Library"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"

[package.dependencies]
greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and platform_machine in \"x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64 AMD64 win32 WIN32\""}
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}

I have a hunch the issue might be the greenlet dependency, which in my case is required by sqlalchemy.

Sure, here is the full stacktrace (for python3.9 this time)

Finding the necessary packages for the current system

  Stack trace:

  14  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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

  13  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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():

  12  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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

  11  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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]

  10  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/poetry/console/commands/install.py:71 in handle
        69│         self._installer.verbose(self._io.is_verbose())
        70│ 
     →  71│         return_code = self._installer.run()
        72│ 
        73│         if return_code != 0:

   9  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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

   8  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/poetry/installation/installer.py:305 in _do_install
       303│ 
       304│         with solver.use_environment(self._env):
     → 305│             ops = solver.solve(use_latest=self._whitelist)
       306│ 
       307│         # We need to filter operations so that packages

   7  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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│ 

   6  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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│             )

   5  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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│ 

   4  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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()

   3  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/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

   2  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/poetry/puzzle/provider.py:479 in complete_package
       477│                 continue
       478│ 
     → 479│             if self._env and not dep.marker.validate(self._env.marker_env):
       480│                 continue
       481│ 

   1  ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/poetry/core/version/markers.py:456 in validate
       454│     def validate(self, environment):  # type: (Dict[str, Any]) -> bool
       455│         for m in self._markers:
     → 456│             if not m.validate(environment):
       457│                 return False
       458│ 

  AttributeError

  'EmptyConstraint' object has no attribute 'allows'

  at ~/anaconda3/envs/xploras39/lib/python3.9/site-packages/poetry/core/version/markers.py:291 in validate
      287│ 
      288│         if self._name not in environment:
      289│             return True
      290│ 
    → 291│         return self._constraint.allows(self._parser(environment[self._name]))
      292│ 
      293│     def without_extras(self):  # type: () -> MarkerTypes
      294│         return self.exclude("extra")
      295│

On closer inspection, I’m not sure whether this issue should be raised in poetry core? It does appear the bug exists on master (https://github.com/python-poetry/poetry-core/blob/5812d6db7ae95ac0dd11b498e47f3c3f17a27857/poetry/core/packages/constraints/empty_constraint.py#L10) Edit: Neither BaseConstraint, nor EmptyConstraint have an allows method, even though all the other concrete constraint implementations do. The check in markers.py appears to be crashing with deps that have no constraints as a result of this mismatch in the interface. I’m guess this maybe never came up because it’s extremely rare to have no constraint on a dependency.

hey there -

this is a poetry issue. SQLAlchemy is using https://www.python.org/dev/peps/pep-0508/ specifiers and as far as we can tell, the syntax is valid. There is no issue with our software installing with pip.

I wonder if a single package was pushed to PyPi with an empty constraint and we all happen to reference it? I’m working through the dependencies for our project now

this issue/bug still exists for poetry 1.2.0a2, i think need to be reopened

No, the fix was made in poetry-core. In the 1.0 branch and the master branch. There was a release 1.0.4 which is used by poetry 1.1.8. But the poetry preview release still uses poetry-core 1.1.0a6. I think with the next preview release of poetry, there will be also a new release for poetry-core which then contains the fix…

This is a bug. Is a very obvious bug for 1.1.7. The EmptyConstraint class does not implement the allows method. Just implementing it to return True appeared to fix it in my case, though I’m not clear entirely clear if a blanket True is the correct behaviour.