jinja: ImportError: cannot import name 'soft_unicode' from 'markupsafe'

Description

Markup has release a new version and now Jinja throws an error.

File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/dbt/utils.py", line 9, in <module>
    import jinja2
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/jinja2/__init__.py", line 12, in <module>
    from .environment import Environment
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/jinja2/environment.py", line [25](https://github.com/cloudfactory/edw-dbt/runs/5243038097?check_suite_focus=true#step:7:25), in <module>
    from .defaults import BLOCK_END_STRING
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/jinja2/defaults.py", line 3, in <module>
    from .filters import FILTERS as DEFAULT_FILTERS  # noqa: F401
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/jinja2/filters.py", line 13, in <module>
    from markupsafe import soft_unicode
ImportError: cannot import name 'soft_unicode' from 'markupsafe' (/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/markupsafe/__init__.py)
Error: Process completed with exit code 1.

Bug Replication

Install Jinja with MarkupSafe 2.1.0

Expected behavior

No errors when importing jinja.

Environment

  • Python version: 3.8.12
  • Jinja version: 2.11.3
  • MarkupSafe: 2.1.0

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 15
  • Comments: 17 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Because I don’t depend on markupsafe, I depend on Jinja. The responsibility for providing compatible dependencies is jinja2, not every project that depends on it.

Edit: By the way, in my case, I develop conan, and I would need to fix versions from 1.0 to 1.43. If I have to do it, I’ll do it because I respect my users, I won’t ask them to pin markupsafe.

Edit2: We already upgraded to Jinja 3 a couple of versions ago, but we understand not all users are able to upgrade Conan for different reasons, so we have to give them a solution.

Hi, jinja2 team. Although the issue is marked as closed, I hope we discuss more about the option to do a patch release for a older version of jinja2.

Since the jinja2==2.11.3 has dependency markupsafe>=0.23 without upper constraints, this led to break all library versions that transitively depends on jinja2<3 (notably, flask<2). That is a wrong constraints, and the most simplest fix would be releasing a patch release jinja2==2.11.4 with markupsafe>=0.23,<2.1.0 constraints.

Application developers can add their constraints.txt file to add an upper cap, but library developers have no way to provide extra constraint for non-direct dependency except for marking it as a direct dependency, which would add up more chaos in python library dependencies. This is not a good way to go.

For example, I’m maintaining tfx library which has extra dependency on airflow, which has a dependency flask<2. This breaks our library. Options that I can choose of:

  1. Ask jinja2 library to release a 2.11.4 patch with markupsafe<2.1 constraints.
  2. Ask flask library to release a 1.1.5 patch with adding markupsafe<2.1 dependency
  3. Ask airflow library to upgrade their flask version to flask>=2.

Option 3 is probably what jinja2 maintainer is thinking about, but IMHO there will be so many other libraries which depends on flask<2, and the holistic effort for the migrations to flask v2 (I don’t know whether there’s a breaking changes introducedd) would be HUGE. Option 2 is the worst idea because it is adding a wrong dependency for a workaround.

I think Option 1 is the easiest and the simplest solution to the current situation. I know it is hard to keep releasing a older version of the library (e.g. tensorflow maintains their 1.x version), but that would greatly help the python community.

I sincerely beg jinja2 team to do a patch release. 🙇

You are using an unsupported version of Jinja, please update to the latest version if possible. Additionally, please read https://hynek.me/articles/semver-will-not-save-you/, then use a tool like pip-tools to pin your dependencies and control when you get updates. Be sure to run your tests with deprecation warnings treated as errors so that you get notified of these types of changes early.

Jinja 2.x has not been supported for some time. Upgrade Jinja, and use something like pip-tools to pin your dependencies.

IMHO that is not reasonable at all. Many projects are still using Jinja 2 and the fix is easy.

Edit: By the way, in my case, I develop conan, and I would need to fix versions from 1.0 to 1.43. If I have to do it, I’ll do it because I respect my users, I won’t ask them to pin markupsafe

That’s actually an end user application, not a library. IMHO it should be installed in an isolated venv where YOU control all the versions (= versions known to work fine with your application).

But for libraries strict pings are actually worse: Sure, in this particular case it’s an ImportError. But do you know how annoying it is if you are using a library and they pin the max version of some dependency, maybe unnecessarily, and you want to use that newer version or install something else that needs it? 😃 By letting the user pin transitive dependencies instead (and ideally use recent versions instead of ancient ones) they can decide whether they’re willing to install a newer version or not.

Now that we know that it is breaking all other libraries that are dependent on Jinja 2.x, including Flask 1.1.4, could we please pin the max version of MarkupSafe?

Hi there! If you’re here to complain about how this broke your workflow, please see https://github.com/pallets/markupsafe/issues/286#issuecomment-1044491026.

Flask uses Jinja2 v3.x. Not v2.x

Jinja is not dead. But old versions are unsupported, and people should pin all their dependencies if they rely on older versions (which is perfectly fine, but not without pinning deps).

Jinja 2.x has not been supported for some time. Upgrade Jinja, and use something like pip-tools to pin your dependencies.

This is a little bit awkward… Flask still uses Jinja2… 😯