typer icon indicating copy to clipboard operation
typer copied to clipboard

ImportError: cannot import name 'get_terminal_size' from 'click.termui'

Open jmhummel opened this issue 4 years ago • 26 comments

First Check

  • [X] I added a very descriptive title to this issue.
  • [X] I used the GitHub search to find a similar issue and didn't find it.
  • [X] I searched the Typer documentation, with the integrated search.
  • [X] I already searched in Google "How to X in Typer" and didn't find any information.
  • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [X] I already checked if it is not related to Typer but to Click.

Commit to Help

  • [X] I commit to help with one of those options 👆

Example Code

import typer

Description

  • Install latest versions of typer (0.4.0) and click (8.1.0)
  • Run script with single line import typer
  • Import fails due to method get_terminal_size having been removed in click 8.1.0 (https://github.com/pallets/click/pull/2130)
Traceback (most recent call last):
  File "test.py", line 1, in <module>
    import typer
  File "/.venv/lib/python3.8/site-packages/typer/__init__.py", line 12, in <module>
    from click.termui import get_terminal_size as get_terminal_size
ImportError: cannot import name 'get_terminal_size' from 'click.termui' (/.venv/lib/python3.8/site-packages/click/termui.py)

Operating System

Linux

Operating System Details

Ubunutu 20.04

Typer Version

0.4.0

Python Version

Python 3.8.10

Additional Context

No response

jmhummel avatar Mar 28 '22 19:03 jmhummel

I think that'll be fixed in #375

browniebroke avatar Mar 28 '22 19:03 browniebroke

confirm the problem appeared on import

import spacy

image

DimIsaev avatar Mar 29 '22 05:03 DimIsaev

Same here, also running into this exception with import spacy for spacy version 3.2.3. Reverting to spacy version 3.1.3 "solves" the problem for now.

CORRECTION: It wasn't the spacy version... It's click (direct dependency from typer). In both projects I have typer version 0.4.0 installed, the one which installed the newer click version 8.1.0 (and spacy 3.2.3) doesn't work, the older one (spacy 3.1.3) which installed click version 8.0.4 works.

tl;dr: Check your click version and force it <8.1.0.

fkoehlin avatar Mar 29 '22 07:03 fkoehlin

Same issue also with the minimal example from the docs on a clean Conda environment with Python 3.9.11. Actually, the error is raised when merely running import typer in the Python console:

➜ python
Python 3.9.11 (main, Mar 28 2022, 05:06:49)
[Clang 12.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import typer
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/drorata/anaconda3/envs/foo/lib/python3.9/site-packages/typer/__init__.py", line 12, in <module>
    from click.termui import get_terminal_size as get_terminal_size
ImportError: cannot import name 'get_terminal_size' from 'click.termui' (/Users/drorata/anaconda3/envs/foo/lib/python3.9/site-packages/click/termui.py)

drorata avatar Mar 29 '22 09:03 drorata

Exactly the same error for me with Python 3.7.13 :

Python 3.7.13 (default, Mar 18 2022, 17:46:12) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import typer
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/var/www/ai/env/lib/python3.7/site-packages/typer/__init__.py", line 12, in <module>
    from click.termui import get_terminal_size as get_terminal_size
ImportError: cannot import name 'get_terminal_size' from 'click.termui' (/var/www/ai/env/lib/python3.7/site-packages/click/termui.py)

Achuttarsing avatar Mar 29 '22 10:03 Achuttarsing

After downgrading Typer to 0.3.2 the problem is gone.

drorata avatar Mar 29 '22 10:03 drorata

After downgrading Click to 0.4.1 the problem is gone.

DimIsaev avatar Mar 29 '22 10:03 DimIsaev

This temporary solution : https://github.com/explosion/spaCy/issues/10564#issuecomment-1081570327 works for me → pip install click==8.0.4

Achuttarsing avatar Mar 29 '22 10:03 Achuttarsing

This temporary solution : explosion/spaCy#10564 (comment) works for me → pip install click==8.0.4

That correct !! I just fix the same your way. I downgrade click from 8.1.0 to 8.0.4 It's working now.

KritsanaMike avatar Mar 29 '22 10:03 KritsanaMike

I am seeing the same on a dependabot PR proposing to update the click version to 8.1 All my "import typer" statements fail with this error:

.tox/py3/lib/python3.8/site-packages/typer/__init__.py:12: in <module>
    from click.termui import get_terminal_size as get_terminal_size
E   ImportError: cannot import name 'get_terminal_size' from 'click.termui' (/home/feganj/wip/.tox/py3/lib/python3.8/

jofegan avatar Mar 29 '22 11:03 jofegan

This temporary solution : explosion/spaCy#10564 (comment) works for me → pip install click==8.0.4

Thanks, I uninstall click and install again with 8.0.4 and works

caetanovidal avatar Mar 29 '22 11:03 caetanovidal

Click makes deprecation warning one minor version ahead for functions that do reimport and could be working for years.

That's a terrible management for such a wide dependency, and now all tools are split into demanding click <8.1, demanding 7.* and demanding > 8.1.

If you fix black, prefect and typer are still not working. 😠

arogozhnikov avatar Mar 30 '22 09:03 arogozhnikov

@arogozhnikov I understand the frustration; we've been impacted at work too. However, I think the reaction you had could be a bit more tempered.

The decision may have been disruptive, and the points you make after your first line are valid (even if worded strongly), but I disagree with the act of calling Click an "absolutely terrible dependency". That act is disheartening for an OSS dev, for which I am one myself, and my heart sank when I read your comment, even though I don't maintain Click or Typer myself. Having provided so much value to the community, it is my opinion that the dev team does not deserve that initial reaction you posted. If you would be open to tempering your comment for posterity, I think that would reflect positively on your character as a fellow OSS user, scientist, and developer.

ericmjl avatar Mar 30 '22 13:03 ericmjl

I removed that first line.

arogozhnikov avatar Mar 30 '22 17:03 arogozhnikov

disagree with the act of calling Click an "absolutely terrible dependency".

if it shatters environment (as I point, not the first time), that's a bad dependency. Your best move is to untie from it as there is no reason to expect this won't repeat.

Click does not use any sophisticated building process neither has too hard nor fragile dependencies. Multiple python packages are in times harder position (all scientific stack basically) but their devs are careful about deprecation cycles and warnings.

Typer previous time was broken for like a year because of click changes. Now we're back here again (fix is trivial, but tiangolo and other people have their schedule - why shouldn't they?).

So maybe @ericmjl you suggest a way that I can use other libraries (like typer) and not be affected by click API changes?

If not, that gets to initial point - I'm asking for minimizing / removing dependency on click, as multiple tools can't change simultaneously, but click does not provide any alternative plan for them.

arogozhnikov avatar Mar 30 '22 17:03 arogozhnikov

I think the basic point is that Click has caused problems for their consumers, including typer, by breaking backward compatibility without a lot of warning or prep time. Have you (or anyone) reported that to the Click project? Maybe they would choose to reintroduce this symbol in a 8.1.1 to restore compatibility, and then set about removing it again in a more controlled fashion. That seems the best solution to me. As far as the typer project goes... I don't know the history, but if Click do this sort of thing a lot then I agree it would make sense for their consumers to try to limit vulnerability to it where possible.

jofegan avatar Mar 30 '22 18:03 jofegan

@jofegan yes, that was done before me several times. You can track their reaction is the Click repo.

Maybe they would choose to reintroduce this symbol in a 8.1.1 to restore compatibility

That what I expected being done. You're very welcome to suggest this to click team.

arogozhnikov avatar Mar 30 '22 18:03 arogozhnikov

Maybe they would choose to reintroduce this symbol in a 8.1.1 to restore compatibility, and then set about removing it again in a more controlled fashion.

But we did remove it in a controlled fashion. Using this function issued a DeprecationWarning starting in 8.0, released 10 months ago. The deprecation was mentioned high up in the changelog, as was the removal. If projects didn't respond to the deprecation yet, why would adding it back in and then removing it again change anything? It would just delay the same events, and then when we removed it again we'd be in the same situation.

It doesn't matter how long we provided warning, because Typer (and apparently no one using Typer either) wasn't testing with deprecation warnings treated as errors, so they would never have been able to proactively respond to the deprecation. I've opened #379 to show how that can be enabled. This is not a problem specific to Click: Python itself, or any libraries used in test/docs environments, can also be issuing deprecation warnings that Typer (or applications using it) is unaware of right now.

One way you, or applications you use, can control this is to use a project management tool like pip-tools, pipenv, pdm, or poetry to pin your dependencies and control when updates are seen and applied. Again, this is not specific to Click. If you pin any dependency (or if a library you use doesn't proactively test warnings), then you need to pin your entire dependency tree to avoid one library updating while another is pinned or not updated yet.

I'm sorry this was disruptive, I get the frustration. Controlling updates is a general problem in Python packaging. It's something everyone's going to run into, whether with this library or another, eventually.

I know @tiangolo is aware of this, although he's currently at a conference right now, but I'm sure he will make a release when he is able.

davidism avatar Mar 30 '22 18:03 davidism

It doesn't matter how long we provided warning, because Typer (and apparently no one using Typer either) wasn't testing with deprecation warnings treated as errors, so they would never have been able to proactively respond to the deprecation.

If nobody does, you still insist that's the way?

I know most of my projects just can't pass such testing because click is not the only dependency, and there are always some things that are not yet fixed in the freshest versions of deps (pandas-depending stack, numba-depending stack, torch and tf are other snowflakes).

Once again, you can just reintroduce function because its existence does not break anything and unlikely will. Absence of it already breaks a lot.

arogozhnikov avatar Mar 30 '22 18:03 arogozhnikov

@davidism please verbalize your position, that was your diff. Thumbs are not an argument.

arogozhnikov avatar Mar 30 '22 18:03 arogozhnikov

I hear what you're saying. In my case, the package versions are pinned and all that has happened is that dependabot proposed an upgrade to Click 8.1.0 and that PR failed CI because it would break Typer. Not a big deal; there's nothing in 8.1.0 that I specifically need and that's just my pins and CI doing their job and stopping me from breaking my own build. But this incompatibility does mean that I won't be able to accept any future updates to Click at all until Typer makes a change to compensate. That can be the tricky part - if one of the affected packages isn't well maintained I may be stuck on the old click version for a long time. But it sounds like that will be okay here.

jofegan avatar Mar 30 '22 19:03 jofegan

But it sounds like that will be okay here.

Unless other project you depend critically on requires fresh black (updated after recent Click update), which requires fresh Click. Which typer can't work with.

arogozhnikov avatar Mar 30 '22 19:03 arogozhnikov

Thanks for the report @jmhummel!

And thanks everyone for the conversation.

I just released Typer 0.4.1 that should handle this. :rocket: :nerd_face:


Thank you very much for the understanding, in particular to those showing your support to these free, open source projects, and the maintainers, like David and me. :heart: :bow:


I'm sorry this made your lives and work difficult for these last couple of days. What happened was that Typer was importing and exporting that utility function from Click just as a convenience for users, but it wasn't used internally, it wasn't called, and that way I didn't catch the deprecation warning.

It was unfortunate indeed, but I wouldn't actually think it's something worth shaming me very aggressively and even less the maintainer(s) of Click that always do an amazing and thorough job.

These types of errors and accidents happen, they happen in open source and even more in closed source, they happen to projects of all sizes and types. The best we can do is to continue to try and make the whole community a welcoming place where we try to help each other instead of blaming and shaming others.


@jmhummel if you confirm that the new release solves your problem you can then close this issue. :nerd_face:

tiangolo avatar Mar 30 '22 20:03 tiangolo

Thank you!

arogozhnikov avatar Mar 30 '22 20:03 arogozhnikov

I can happily confirm that the issue mentioned in this comment above is removed once updating typer to 0.4.1. Thanks!

drorata avatar Mar 31 '22 06:03 drorata

Apologies to add to noise. Reinforcing @drorata's comment that upgrading Typer to 0.4.1 resolved the issue and managed not to break any other dependencies in my gcp + pandas data pipeline.

michael-wise avatar Jun 16 '22 22:06 michael-wise

Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues.

github-actions[bot] avatar Nov 10 '22 13:11 github-actions[bot]

Bot closed this but it appears to be unresolved.

RileyMShea avatar Oct 19 '23 13:10 RileyMShea

Here's the definition of the missing function at the time of removal:

def get_terminal_size() -> os.terminal_size:
    """Returns the current size of the terminal as tuple in the form
    ``(width, height)`` in columns and rows.

    .. deprecated:: 8.0
        Will be removed in Click 8.1. Use
        :func:`shutil.get_terminal_size` instead.
    """
    import shutil
    import warnings

    warnings.warn(
        "'click.get_terminal_size()' is deprecated and will be removed"
        " in Click 8.1. Use 'shutil.get_terminal_size()' instead.",
        DeprecationWarning,
        stacklevel=2,
    )
    return shutil.get_terminal_size()

I believe it should be trivial to fix this particular issue (and it wouldn't even break compatibility with click-8.0).

LeXofLeviafan avatar Oct 21 '23 12:10 LeXofLeviafan

…Waitaminute

According to release notes, this was fixed back in v0.4.1 over a year ago.

LeXofLeviafan avatar Oct 21 '23 12:10 LeXofLeviafan