diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e734c0aa3..620bd11f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ ci: autoupdate_schedule: monthly repos: - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 + rev: v3.4.0 hooks: - id: pyupgrade args: ["--py37-plus"] @@ -14,7 +14,7 @@ repos: args: ["--application-directories", "src"] additional_dependencies: ["setuptools>60.9"] - repo: https://github.com/psf/black - rev: 23.1.0 + rev: 23.3.0 hooks: - id: black - repo: https://github.com/PyCQA/flake8 @@ -23,7 +23,7 @@ repos: - id: flake8 additional_dependencies: [flake8-bugbear] - repo: https://github.com/peterdemin/pip-compile-multi - rev: v2.6.1 + rev: v2.6.3 hooks: - id: pip-compile-multi-verify - repo: https://github.com/pre-commit/pre-commit-hooks diff --git a/CHANGES.rst b/CHANGES.rst index d539a7373..66575ea5e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,15 @@ Unreleased :pr:`1793` +Version 3.1.3 +------------- + +Unreleased + +- Fix compiler error when checking if required blocks in parent templates are + empty. :pr:`1858` + + Version 3.1.2 ------------- diff --git a/README.rst b/README.rst index a197aea64..94b22ecab 100644 --- a/README.rst +++ b/README.rst @@ -73,6 +73,4 @@ Links - PyPI Releases: https://pypi.org/project/Jinja2/ - Source Code: https://github.com/pallets/jinja/ - Issue Tracker: https://github.com/pallets/jinja/issues/ -- Website: https://palletsprojects.com/p/jinja/ -- Twitter: https://twitter.com/PalletsTeam - Chat: https://discord.gg/pallets diff --git a/docs/conf.py b/docs/conf.py index f65d462b3..1483ce6e8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,8 +32,6 @@ ProjectLink("PyPI Releases", "https://pypi.org/project/Jinja2/"), ProjectLink("Source Code", "https://github.com/pallets/jinja/"), ProjectLink("Issue Tracker", "https://github.com/pallets/jinja/issues/"), - ProjectLink("Website", "https://palletsprojects.com/p/jinja/"), - ProjectLink("Twitter", "https://twitter.com/PalletsTeam"), ProjectLink("Chat", "https://discord.gg/pallets"), ] } diff --git a/pyproject.toml b/pyproject.toml index f90576de6..42bfb4417 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,6 @@ description = "A very fast and expressive template engine." readme = "README.rst" license = {text = "BSD-3-Clause"} maintainers = [{name = "Pallets", email = "contact@palletsprojects.com"}] -authors = [{name = "Armin Ronacher", email = "armin.ronacher@active-4.com"}] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", @@ -25,7 +24,6 @@ Documentation = "https://jinja.palletsprojects.com/" Changes = "https://jinja.palletsprojects.com/changes/" "Source Code" = "https://github.com/pallets/jinja/" "Issue Tracker" = "https://github.com/pallets/jinja/issues/" -Twitter = "https://twitter.com/PalletsTeam" Chat = "https://discord.gg/pallets" [project.optional-dependencies] @@ -42,7 +40,11 @@ version = {attr = "jinja2.__version__"} [tool.pytest.ini_options] testpaths = ["tests"] -filterwarnings = ["error"] +filterwarnings = [ + "error", + # change in Python 3.12 beta causes warning from inside pytest + "ignore:ast:DeprecationWarning", +] [tool.coverage.run] branch = true diff --git a/requirements/build.txt b/requirements/build.txt index a735b3d0d..98175b856 100644 --- a/requirements/build.txt +++ b/requirements/build.txt @@ -5,13 +5,11 @@ # # pip-compile-multi # -build==0.9.0 +build==0.10.0 # via -r requirements/build.in -packaging==23.0 +packaging==23.1 # via build -pep517==0.13.0 +pyproject-hooks==1.0.0 # via build tomli==2.0.1 - # via - # build - # pep517 + # via build diff --git a/requirements/dev.txt b/requirements/dev.txt index bde64ee36..99a6f0346 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -8,9 +8,9 @@ -r docs.txt -r tests.txt -r typing.txt -build==0.9.0 +build==0.10.0 # via pip-tools -cachetools==5.2.0 +cachetools==5.3.1 # via tox cfgv==3.3.1 # via pre-commit @@ -24,39 +24,39 @@ colorama==0.4.6 # via tox distlib==0.3.6 # via virtualenv -filelock==3.9.0 +filelock==3.12.0 # via # tox # virtualenv -identify==2.5.11 +identify==2.5.24 # via pre-commit -nodeenv==1.7.0 +nodeenv==1.8.0 # via pre-commit -pep517==0.13.0 - # via build -pip-compile-multi==2.6.1 +pip-compile-multi==2.6.3 # via -r requirements/dev.in -pip-tools==6.12.1 +pip-tools==6.13.0 # via pip-compile-multi -platformdirs==2.6.2 +platformdirs==3.5.1 # via # tox # virtualenv -pre-commit==2.21.0 +pre-commit==3.3.2 # via -r requirements/dev.in -pyproject-api==1.2.1 +pyproject-api==1.5.1 # via tox +pyproject-hooks==1.0.0 + # via build pyyaml==6.0 # via pre-commit -toposort==1.7 +toposort==1.10 # via pip-compile-multi -tox==4.1.0 +tox==4.5.2 # via -r requirements/dev.in -virtualenv==20.17.1 +virtualenv==20.23.0 # via # pre-commit # tox -wheel==0.38.4 +wheel==0.40.0 # via pip-tools # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/docs.txt b/requirements/docs.txt index 618301091..2c36046b0 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -5,15 +5,15 @@ # # pip-compile-multi # -alabaster==0.7.12 +alabaster==0.7.13 # via sphinx -babel==2.11.0 +babel==2.12.1 # via sphinx -certifi==2022.12.7 +certifi==2023.5.7 # via requests -charset-normalizer==2.1.1 +charset-normalizer==3.1.0 # via requests -docutils==0.19 +docutils==0.20.1 # via sphinx idna==3.4 # via requests @@ -21,23 +21,21 @@ imagesize==1.4.1 # via sphinx jinja2==3.1.2 # via sphinx -markupsafe==2.1.1 +markupsafe==2.1.2 # via jinja2 -packaging==22.0 +packaging==23.1 # via # pallets-sphinx-themes # sphinx -pallets-sphinx-themes==2.0.3 +pallets-sphinx-themes==2.1.0 # via -r requirements/docs.in -pygments==2.13.0 +pygments==2.15.1 # via sphinx -pytz==2022.7 - # via babel -requests==2.28.1 +requests==2.31.0 # via sphinx snowballstemmer==2.2.0 # via sphinx -sphinx==6.0.0 +sphinx==7.0.1 # via # -r requirements/docs.in # pallets-sphinx-themes @@ -45,11 +43,11 @@ sphinx==6.0.0 # sphinxcontrib-log-cabinet sphinx-issues==3.0.1 # via -r requirements/docs.in -sphinxcontrib-applehelp==1.0.2 +sphinxcontrib-applehelp==1.0.4 # via sphinx sphinxcontrib-devhelp==1.0.2 # via sphinx -sphinxcontrib-htmlhelp==2.0.0 +sphinxcontrib-htmlhelp==2.0.1 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx @@ -59,5 +57,5 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx -urllib3==1.26.13 +urllib3==2.0.2 # via requests diff --git a/requirements/tests.txt b/requirements/tests.txt index fa8c24a27..70ca162b7 100644 --- a/requirements/tests.txt +++ b/requirements/tests.txt @@ -5,17 +5,15 @@ # # pip-compile-multi # -attrs==22.2.0 +exceptiongroup==1.1.1 # via pytest -exceptiongroup==1.1.0 +iniconfig==2.0.0 # via pytest -iniconfig==1.1.1 - # via pytest -packaging==22.0 +packaging==23.1 # via pytest pluggy==1.0.0 # via pytest -pytest==7.2.0 +pytest==7.3.1 # via -r requirements/tests.in tomli==2.0.1 # via pytest diff --git a/requirements/typing.txt b/requirements/typing.txt index a70f3f5ce..bc63c0f84 100644 --- a/requirements/typing.txt +++ b/requirements/typing.txt @@ -5,11 +5,11 @@ # # pip-compile-multi # -mypy==0.991 +mypy==1.3.0 # via -r requirements/typing.in -mypy-extensions==0.4.3 +mypy-extensions==1.0.0 # via mypy tomli==2.0.1 # via mypy -typing-extensions==4.4.0 +typing-extensions==4.6.2 # via mypy diff --git a/scripts/generate_identifier_pattern.py b/scripts/generate_identifier_pattern.py index 24de8788c..7fc64aed0 100755 --- a/scripts/generate_identifier_pattern.py +++ b/scripts/generate_identifier_pattern.py @@ -29,8 +29,8 @@ def collapse_ranges(data): Source: https://stackoverflow.com/a/4629241/400617 """ - for _, b in itertools.groupby(enumerate(data), lambda x: ord(x[1]) - x[0]): - lb = list(b) + for _, g in itertools.groupby(enumerate(data), lambda x: ord(x[1]) - x[0]): + lb = list(g) yield lb[0][1], lb[-1][1] diff --git a/src/jinja2/environment.py b/src/jinja2/environment.py index 29a1b4e40..5474d56ba 100644 --- a/src/jinja2/environment.py +++ b/src/jinja2/environment.py @@ -703,7 +703,7 @@ def _compile(self, source: str, filename: str) -> CodeType: .. versionadded:: 2.5 """ - return compile(source, filename, "exec") # type: ignore + return compile(source, filename, "exec") @typing.overload def compile( # type: ignore diff --git a/src/jinja2/nativetypes.py b/src/jinja2/nativetypes.py index ac0861034..71db8cc31 100644 --- a/src/jinja2/nativetypes.py +++ b/src/jinja2/nativetypes.py @@ -106,7 +106,7 @@ def render(self, *args: t.Any, **kwargs: t.Any) -> t.Any: try: return self.environment_class.concat( # type: ignore - self.root_render_func(ctx) # type: ignore + self.root_render_func(ctx) ) except Exception: return self.environment.handle_exception() diff --git a/src/jinja2/parser.py b/src/jinja2/parser.py index fb4fd0d11..206e49523 100644 --- a/src/jinja2/parser.py +++ b/src/jinja2/parser.py @@ -311,12 +311,14 @@ def parse_block(self) -> nodes.Block: # enforce that required blocks only contain whitespace or comments # by asserting that the body, if not empty, is just TemplateData nodes # with whitespace data - if node.required and not all( - isinstance(child, nodes.TemplateData) and child.data.isspace() - for body in node.body - for child in body.nodes # type: ignore - ): - self.fail("Required blocks can only contain comments or whitespace") + if node.required: + for body_node in node.body: + if not isinstance(body_node, nodes.Output) or any( + not isinstance(output_node, nodes.TemplateData) + or not output_node.data.isspace() + for output_node in body_node.nodes + ): + self.fail("Required blocks can only contain comments or whitespace") self.stream.skip_if("name:" + node.name) return node diff --git a/src/jinja2/utils.py b/src/jinja2/utils.py index 852d08294..b9511a86c 100644 --- a/src/jinja2/utils.py +++ b/src/jinja2/utils.py @@ -182,7 +182,7 @@ def object_type_repr(obj: t.Any) -> str: def pformat(obj: t.Any) -> str: """Format an object using :func:`pprint.pformat`.""" - from pprint import pformat # type: ignore + from pprint import pformat return pformat(obj) diff --git a/tests/test_filters.py b/tests/test_filters.py index 73f0f0be3..32897c546 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -870,4 +870,6 @@ def test_filter_undefined_in_condexpr(self, env): with pytest.raises(TemplateRuntimeError, match="No filter named 'f'"): t1.render(x=42) + + with pytest.raises(TemplateRuntimeError, match="No filter named 'f'"): t2.render(x=42) diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py index 0c20d4da7..0a525e7ac 100644 --- a/tests/test_inheritance.py +++ b/tests/test_inheritance.py @@ -287,26 +287,34 @@ def test_invalid_required(self, env): env = Environment( loader=DictLoader( { - "default": "{% block x required %}data {# #}{% endblock %}", - "default1": "{% block x required %}{% block y %}" - "{% endblock %} {% endblock %}", - "default2": "{% block x required %}{% if true %}" - "{% endif %} {% endblock %}", - "level1": "{% if default %}{% extends default %}" - "{% else %}{% extends 'default' %}{% endif %}" - "{%- block x %}CHILD{% endblock %}", + "empty": "{% block x required %}{% endblock %}", + "blank": "{% block x required %} {# c #}{% endblock %}", + "text": "{% block x required %}data {# c #}{% endblock %}", + "block": "{% block x required %}{% block y %}" + "{% endblock %}{% endblock %}", + "if": "{% block x required %}{% if true %}" + "{% endif %}{% endblock %}", + "top": "{% extends t %}{% block x %}CHILD{% endblock %}", } ) ) - t = env.get_template("level1") + t = env.get_template("top") + assert t.render(t="empty") == "CHILD" + assert t.render(t="blank") == "CHILD" - with pytest.raises( + required_block_check = pytest.raises( TemplateSyntaxError, match="Required blocks can only contain comments or whitespace", - ): - assert t.render(default="default") - assert t.render(default="default2") - assert t.render(default="default3") + ) + + with required_block_check: + t.render(t="text") + + with required_block_check: + t.render(t="block") + + with required_block_check: + t.render(t="if") def test_required_with_scope(self, env): env = Environment( @@ -347,8 +355,11 @@ def test_duplicate_required_or_scoped(self, env): ) ) tmpl = env.get_template("child") + with pytest.raises(TemplateSyntaxError): tmpl.render(default="default1", seq=list(range(3))) + + with pytest.raises(TemplateSyntaxError): tmpl.render(default="default2", seq=list(range(3)))