mirror of
https://gitee.com/openharmony/third_party_jinja2
synced 2024-11-23 15:19:46 +00:00
commit
e31aef6a9b
28
.flake8
Executable file
28
.flake8
Executable file
@ -0,0 +1,28 @@
|
||||
[flake8]
|
||||
extend-select =
|
||||
# bugbear
|
||||
B
|
||||
# bugbear opinions
|
||||
B9
|
||||
# implicit str concat
|
||||
ISC
|
||||
extend-ignore =
|
||||
# slice notation whitespace, invalid
|
||||
E203
|
||||
# line length, handled by bugbear B950
|
||||
E501
|
||||
# bare except, handled by bugbear B001
|
||||
E722
|
||||
# zip with strict=, requires python >= 3.10
|
||||
B905
|
||||
# string formatting opinion, B028 renamed to B907
|
||||
B028
|
||||
B907
|
||||
# up to 88 allowed by bugbear B950
|
||||
max-line-length = 80
|
||||
per-file-ignores =
|
||||
# __init__ exports names
|
||||
src/jinja2/__init__.py: F401
|
||||
# not relevant to jinja's compiler
|
||||
src/jinja2/compiler.py: B906
|
||||
src/jinja2/idtracking.py: B906
|
14
.github/workflows/lock.yaml
vendored
14
.github/workflows/lock.yaml
vendored
@ -1,15 +1,25 @@
|
||||
name: 'Lock threads'
|
||||
# Lock closed issues that have not received any further activity for
|
||||
# two weeks. This does not close open issues, only humans may do that.
|
||||
# We find that it is easier to respond to new issues with fresh examples
|
||||
# rather than continuing discussions on old issues.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: lock
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v3
|
||||
- uses: dessant/lock-threads@c1b35aecc5cdb1a34539d14196df55838bb2f836
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: 14
|
||||
pr-inactive-days: 14
|
||||
|
67
.github/workflows/publish.yaml
vendored
Executable file
67
.github/workflows/publish.yaml
vendored
Executable file
@ -0,0 +1,67 @@
|
||||
name: Publish
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
hash: ${{ steps.hash.outputs.hash }}
|
||||
steps:
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- uses: actions/setup-python@5ccb29d8773c3f3f653e1705f474dfaa8a06a912
|
||||
with:
|
||||
python-version: '3.x'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'requirements/*.txt'
|
||||
- run: pip install -r requirements/build.txt
|
||||
# Use the commit date instead of the current date during the build.
|
||||
- run: echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
|
||||
- run: python -m build
|
||||
# Generate hashes used for provenance.
|
||||
- name: generate hash
|
||||
id: hash
|
||||
run: cd dist && echo "hash=$(sha256sum * | base64 -w0)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce
|
||||
with:
|
||||
path: ./dist
|
||||
provenance:
|
||||
needs: ['build']
|
||||
permissions:
|
||||
actions: read
|
||||
id-token: write
|
||||
contents: write
|
||||
# Can't pin with hash due to how this workflow works.
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0
|
||||
with:
|
||||
base64-subjects: ${{ needs.build.outputs.hash }}
|
||||
create-release:
|
||||
# Upload the sdist, wheels, and provenance to a GitHub release. They remain
|
||||
# available as build artifacts for a while as well.
|
||||
needs: ['provenance']
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
||||
- name: create release
|
||||
run: >
|
||||
gh release create --draft --repo ${{ github.repository }}
|
||||
${{ github.ref_name }}
|
||||
*.intoto.jsonl/* artifact/*
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
publish-pypi:
|
||||
needs: ['provenance']
|
||||
# Wait for approval before attempting to upload to PyPI. This allows reviewing the
|
||||
# files in the draft release.
|
||||
environment: 'publish'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
||||
- uses: pypa/gh-action-pypi-publish@2f6f737ca5f74c637829c0f5c3acd0e29ea5e8bf
|
||||
with:
|
||||
packages-dir: artifact/
|
21
.github/workflows/tests.yaml
vendored
21
.github/workflows/tests.yaml
vendored
@ -24,18 +24,19 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {name: Linux, python: '3.10', os: ubuntu-latest, tox: py310}
|
||||
- {name: Windows, python: '3.10', os: windows-latest, tox: py310}
|
||||
- {name: Mac, python: '3.10', os: macos-latest, tox: py310}
|
||||
- {name: '3.11-dev', python: '3.11-dev', os: ubuntu-latest, tox: py311}
|
||||
- {name: Linux, python: '3.11', os: ubuntu-latest, tox: py311}
|
||||
- {name: Windows, python: '3.11', os: windows-latest, tox: py311}
|
||||
- {name: Mac, python: '3.11', os: macos-latest, tox: py311}
|
||||
- {name: '3.12-dev', python: '3.12-dev', os: ubuntu-latest, tox: py312}
|
||||
- {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310}
|
||||
- {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39}
|
||||
- {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38}
|
||||
- {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37}
|
||||
- {name: 'PyPy', python: 'pypy-3.7', os: ubuntu-latest, tox: pypy37}
|
||||
- {name: Typing, python: '3.10', os: ubuntu-latest, tox: typing}
|
||||
- {name: 'PyPy', python: 'pypy-3.10', os: ubuntu-latest, tox: pypy310}
|
||||
- {name: Typing, python: '3.11', os: ubuntu-latest, tox: typing}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v3
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- uses: actions/setup-python@5ccb29d8773c3f3f653e1705f474dfaa8a06a912
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: 'pip'
|
||||
@ -46,10 +47,10 @@ jobs:
|
||||
pip install -U setuptools
|
||||
python -m pip install -U pip
|
||||
- name: cache mypy
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@58c146cc91c5b9e778e71775dfe9bf1442ad9a12
|
||||
with:
|
||||
path: ./.mypy_cache
|
||||
key: mypy|${{ matrix.python }}|${{ hashFiles('setup.cfg') }}
|
||||
if: matrix.tox == 'typing'
|
||||
- run: pip install tox
|
||||
- run: tox -e ${{ matrix.tox }}
|
||||
- run: tox run -e ${{ matrix.tox }}
|
||||
|
@ -3,31 +3,30 @@ ci:
|
||||
autoupdate_schedule: monthly
|
||||
repos:
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.32.0
|
||||
rev: v3.15.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: ["--py37-plus"]
|
||||
- repo: https://github.com/asottile/reorder_python_imports
|
||||
rev: v3.1.0
|
||||
- repo: https://github.com/asottile/reorder-python-imports
|
||||
rev: v3.12.0
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
||||
args: ["--application-directories", "src"]
|
||||
additional_dependencies: ["setuptools>60.9"]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.3.0
|
||||
rev: 23.12.1
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 4.0.1
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies: [flake8-bugbear]
|
||||
- repo: https://github.com/peterdemin/pip-compile-multi
|
||||
rev: v2.4.5
|
||||
rev: v2.6.3
|
||||
hooks:
|
||||
- id: pip-compile-multi-verify
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.2.0
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: fix-byte-order-marker
|
||||
- id: trailing-whitespace
|
||||
|
12
CHANGES.rst
12
CHANGES.rst
@ -1,5 +1,17 @@
|
||||
.. currentmodule:: jinja2
|
||||
|
||||
Version 3.1.3
|
||||
-------------
|
||||
|
||||
Released 2024-01-10
|
||||
|
||||
- Fix compiler error when checking if required blocks in parent templates are
|
||||
empty. :pr:`1858`
|
||||
- ``xmlattr`` filter does not allow keys with spaces. GHSA-h5c8-rqwp-cp95
|
||||
- Make error messages stemming from invalid nesting of ``{% trans %}`` blocks
|
||||
more helpful. :pr:`1916`
|
||||
|
||||
|
||||
Version 3.1.2
|
||||
-------------
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"Name": "Jinja2",
|
||||
"License": "BSD 3-clause License",
|
||||
"License File": "LICENSE.rst",
|
||||
"Version Number": "3.1.2",
|
||||
"Version Number": "3.1.3",
|
||||
"Owner": "anguanglin@huawei.com",
|
||||
"Upstream URL": "https://github.com/pallets/jinja",
|
||||
"Description": "Jinja2 is a template engine written in pure Python. It provides a Django inspired non-XML syntax but supports inline expressions and an optional sandboxed environment."
|
||||
|
@ -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
|
||||
|
@ -34,4 +34,4 @@ from .utils import pass_environment as pass_environment
|
||||
from .utils import pass_eval_context as pass_eval_context
|
||||
from .utils import select_autoescape as select_autoescape
|
||||
|
||||
__version__ = "3.1.2"
|
||||
__version__ = "3.1.3"
|
||||
|
@ -74,7 +74,7 @@ async def auto_aiter(
|
||||
async for item in t.cast("t.AsyncIterable[V]", iterable):
|
||||
yield item
|
||||
else:
|
||||
for item in t.cast("t.Iterable[V]", iterable):
|
||||
for item in iterable:
|
||||
yield item
|
||||
|
||||
|
||||
|
@ -993,7 +993,6 @@ class CodeGenerator(NodeVisitor):
|
||||
# far, we don't have to add a check if something extended
|
||||
# the template before this one.
|
||||
if self.extends_so_far > 0:
|
||||
|
||||
# if we have a known extends we just add a template runtime
|
||||
# error into the generated code. We could catch that at compile
|
||||
# time too, but i welcome it not to confuse users by throwing the
|
||||
@ -1407,7 +1406,7 @@ class CodeGenerator(NodeVisitor):
|
||||
|
||||
if pass_arg is None:
|
||||
|
||||
def finalize(value: t.Any) -> t.Any:
|
||||
def finalize(value: t.Any) -> t.Any: # noqa: F811
|
||||
return default(env_finalize(value))
|
||||
|
||||
else:
|
||||
@ -1415,7 +1414,7 @@ class CodeGenerator(NodeVisitor):
|
||||
|
||||
if pass_arg == "environment":
|
||||
|
||||
def finalize(value: t.Any) -> t.Any:
|
||||
def finalize(value: t.Any) -> t.Any: # noqa: F811
|
||||
return default(env_finalize(self.environment, value))
|
||||
|
||||
self._finalize = self._FinalizeInfo(finalize, src)
|
||||
|
@ -701,7 +701,7 @@ class Environment:
|
||||
|
||||
.. versionadded:: 2.5
|
||||
"""
|
||||
return compile(source, filename, "exec") # type: ignore
|
||||
return compile(source, filename, "exec")
|
||||
|
||||
@typing.overload
|
||||
def compile( # type: ignore
|
||||
@ -920,7 +920,7 @@ class Environment:
|
||||
)
|
||||
|
||||
def filter_func(x: str) -> bool:
|
||||
return "." in x and x.rsplit(".", 1)[1] in extensions # type: ignore
|
||||
return "." in x and x.rsplit(".", 1)[1] in extensions
|
||||
|
||||
if filter_func is not None:
|
||||
names = [name for name in names if filter_func(name)]
|
||||
@ -1253,7 +1253,7 @@ class Template:
|
||||
t.blocks = namespace["blocks"]
|
||||
|
||||
# render function and module
|
||||
t.root_render_func = namespace["root"] # type: ignore
|
||||
t.root_render_func = namespace["root"]
|
||||
t._module = None
|
||||
|
||||
# debug and loader helpers
|
||||
@ -1349,7 +1349,7 @@ class Template:
|
||||
ctx = self.new_context(dict(*args, **kwargs))
|
||||
|
||||
try:
|
||||
yield from self.root_render_func(ctx) # type: ignore
|
||||
yield from self.root_render_func(ctx)
|
||||
except Exception:
|
||||
yield self.environment.handle_exception()
|
||||
|
||||
@ -1532,7 +1532,7 @@ class TemplateModule:
|
||||
" API you are using."
|
||||
)
|
||||
|
||||
body_stream = list(template.root_render_func(context)) # type: ignore
|
||||
body_stream = list(template.root_render_func(context))
|
||||
|
||||
self._body_stream = body_stream
|
||||
self.__dict__.update(context.get_exported())
|
||||
@ -1564,7 +1564,7 @@ class TemplateExpression:
|
||||
|
||||
def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Optional[t.Any]:
|
||||
context = self._template.new_context(dict(*args, **kwargs))
|
||||
consume(self._template.root_render_func(context)) # type: ignore
|
||||
consume(self._template.root_render_func(context))
|
||||
rv = context.vars["result"]
|
||||
if self._undefined_to_none and isinstance(rv, Undefined):
|
||||
rv = None
|
||||
|
20
ext.py
20
ext.py
@ -291,14 +291,14 @@ class InternationalizationExtension(Extension):
|
||||
|
||||
if hasattr(translations, "pgettext"):
|
||||
# Python < 3.8
|
||||
pgettext = translations.pgettext # type: ignore
|
||||
pgettext = translations.pgettext
|
||||
else:
|
||||
|
||||
def pgettext(c: str, s: str) -> str:
|
||||
return s
|
||||
|
||||
if hasattr(translations, "npgettext"):
|
||||
npgettext = translations.npgettext # type: ignore
|
||||
npgettext = translations.npgettext
|
||||
else:
|
||||
|
||||
def npgettext(c: str, s: str, p: str, n: int) -> str:
|
||||
@ -495,16 +495,26 @@ class InternationalizationExtension(Extension):
|
||||
parser.stream.expect("variable_end")
|
||||
elif parser.stream.current.type == "block_begin":
|
||||
next(parser.stream)
|
||||
if parser.stream.current.test("name:endtrans"):
|
||||
block_name = (
|
||||
parser.stream.current.value
|
||||
if parser.stream.current.type == "name"
|
||||
else None
|
||||
)
|
||||
if block_name == "endtrans":
|
||||
break
|
||||
elif parser.stream.current.test("name:pluralize"):
|
||||
elif block_name == "pluralize":
|
||||
if allow_pluralize:
|
||||
break
|
||||
parser.fail(
|
||||
"a translatable section can have only one pluralize section"
|
||||
)
|
||||
elif block_name == "trans":
|
||||
parser.fail(
|
||||
"trans blocks can't be nested; did you mean `endtrans`?"
|
||||
)
|
||||
parser.fail(
|
||||
"control structures in translatable sections are not allowed"
|
||||
f"control structures in translatable sections are not allowed; "
|
||||
f"saw `{block_name}`"
|
||||
)
|
||||
elif parser.stream.eos:
|
||||
parser.fail("unclosed translation block")
|
||||
|
38
loaders.py
38
loaders.py
@ -15,7 +15,6 @@ from types import ModuleType
|
||||
|
||||
from .exceptions import TemplateNotFound
|
||||
from .utils import internalcode
|
||||
from .utils import open_if_exists
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from .environment import Environment
|
||||
@ -193,29 +192,30 @@ class FileSystemLoader(BaseLoader):
|
||||
self, environment: "Environment", template: str
|
||||
) -> t.Tuple[str, str, t.Callable[[], bool]]:
|
||||
pieces = split_template_path(template)
|
||||
|
||||
for searchpath in self.searchpath:
|
||||
# Use posixpath even on Windows to avoid "drive:" or UNC
|
||||
# segments breaking out of the search directory.
|
||||
filename = posixpath.join(searchpath, *pieces)
|
||||
f = open_if_exists(filename)
|
||||
if f is None:
|
||||
continue
|
||||
|
||||
if os.path.isfile(filename):
|
||||
break
|
||||
else:
|
||||
raise TemplateNotFound(template)
|
||||
|
||||
with open(filename, encoding=self.encoding) as f:
|
||||
contents = f.read()
|
||||
|
||||
mtime = os.path.getmtime(filename)
|
||||
|
||||
def uptodate() -> bool:
|
||||
try:
|
||||
contents = f.read().decode(self.encoding)
|
||||
finally:
|
||||
f.close()
|
||||
return os.path.getmtime(filename) == mtime
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
mtime = os.path.getmtime(filename)
|
||||
|
||||
def uptodate() -> bool:
|
||||
try:
|
||||
return os.path.getmtime(filename) == mtime
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
# Use normpath to convert Windows altsep to sep.
|
||||
return contents, os.path.normpath(filename), uptodate
|
||||
raise TemplateNotFound(template)
|
||||
# Use normpath to convert Windows altsep to sep.
|
||||
return contents, os.path.normpath(filename), uptodate
|
||||
|
||||
def list_templates(self) -> t.List[str]:
|
||||
found = set()
|
||||
@ -392,7 +392,7 @@ class PackageLoader(BaseLoader):
|
||||
)
|
||||
offset = len(prefix)
|
||||
|
||||
for name in self._loader._files.keys(): # type: ignore
|
||||
for name in self._loader._files.keys():
|
||||
# Find names under the templates directory that aren't directories.
|
||||
if name.startswith(prefix) and name[-1] != os.path.sep:
|
||||
results.append(name[offset:].replace(os.path.sep, "/"))
|
||||
|
@ -106,7 +106,7 @@ class NativeTemplate(Template):
|
||||
|
||||
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()
|
||||
|
16
parser.py
16
parser.py
@ -311,12 +311,14 @@ class Parser:
|
||||
# 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
|
||||
@ -857,7 +859,7 @@ class Parser:
|
||||
else:
|
||||
args.append(None)
|
||||
|
||||
return nodes.Slice(lineno=lineno, *args)
|
||||
return nodes.Slice(lineno=lineno, *args) # noqa: B026
|
||||
|
||||
def parse_call_args(self) -> t.Tuple:
|
||||
token = self.stream.expect("lparen")
|
||||
|
@ -272,9 +272,9 @@ class Context:
|
||||
# Allow callable classes to take a context
|
||||
if (
|
||||
hasattr(__obj, "__call__") # noqa: B004
|
||||
and _PassArg.from_obj(__obj.__call__) is not None # type: ignore
|
||||
and _PassArg.from_obj(__obj.__call__) is not None
|
||||
):
|
||||
__obj = __obj.__call__ # type: ignore
|
||||
__obj = __obj.__call__
|
||||
|
||||
pass_arg = _PassArg.from_obj(__obj)
|
||||
|
||||
@ -927,9 +927,7 @@ def make_logging_undefined(
|
||||
logger.addHandler(logging.StreamHandler(sys.stderr))
|
||||
|
||||
def _log_message(undef: Undefined) -> None:
|
||||
logger.warning( # type: ignore
|
||||
"Template variable warning: %s", undef._undefined_message
|
||||
)
|
||||
logger.warning("Template variable warning: %s", undef._undefined_message)
|
||||
|
||||
class LoggingUndefined(base): # type: ignore
|
||||
__slots__ = ()
|
||||
|
28
setup.cfg
28
setup.cfg
@ -8,12 +8,9 @@ project_urls =
|
||||
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
|
||||
license = BSD-3-Clause
|
||||
license_files = LICENSE.rst
|
||||
author = Armin Ronacher
|
||||
author_email = armin.ronacher@active-4.com
|
||||
maintainer = Pallets
|
||||
maintainer_email = contact@palletsprojects.com
|
||||
description = A very fast and expressive template engine.
|
||||
@ -47,8 +44,6 @@ babel.extractors =
|
||||
testpaths = tests
|
||||
filterwarnings =
|
||||
error
|
||||
# Python 3.9 raises a deprecation from internal asyncio code.
|
||||
ignore:The loop argument:DeprecationWarning:asyncio[.]base_events:542
|
||||
|
||||
[coverage:run]
|
||||
branch = True
|
||||
@ -61,29 +56,6 @@ source =
|
||||
src
|
||||
*/site-packages
|
||||
|
||||
[flake8]
|
||||
# B = bugbear
|
||||
# E = pycodestyle errors
|
||||
# F = flake8 pyflakes
|
||||
# W = pycodestyle warnings
|
||||
# B9 = bugbear opinions
|
||||
# ISC = implicit str concat
|
||||
select = B, E, F, W, B9, ISC
|
||||
ignore =
|
||||
# slice notation whitespace, invalid
|
||||
E203
|
||||
# line length, handled by bugbear B950
|
||||
E501
|
||||
# bare except, handled by bugbear B001
|
||||
E722
|
||||
# bin op line break, invalid
|
||||
W503
|
||||
# up to 88 allowed by bugbear B950
|
||||
max-line-length = 80
|
||||
per-file-ignores =
|
||||
# __init__ exports names
|
||||
src/jinja2/__init__.py: F401
|
||||
|
||||
[mypy]
|
||||
files = src/jinja2
|
||||
python_version = 3.7
|
||||
|
7
tox.ini
7
tox.ini
@ -1,19 +1,22 @@
|
||||
[tox]
|
||||
envlist =
|
||||
py3{11,10,9,8,7},pypy3{8,7}
|
||||
py3{12,11,10,9,8,7}
|
||||
pypy310
|
||||
style
|
||||
typing
|
||||
docs
|
||||
skip_missing_interpreters = true
|
||||
|
||||
[testenv]
|
||||
package = wheel
|
||||
wheel_build_env = .pkg
|
||||
deps = -r requirements/tests.txt
|
||||
commands = pytest -v --tb=short --basetemp={envtmpdir} {posargs}
|
||||
|
||||
[testenv:style]
|
||||
deps = pre-commit
|
||||
skip_install = true
|
||||
commands = pre-commit run --all-files --show-diff-on-failure
|
||||
commands = pre-commit run --all-files
|
||||
|
||||
[testenv:typing]
|
||||
deps = -r requirements/typing.txt
|
||||
|
4
utils.py
4
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)
|
||||
|
||||
@ -259,7 +259,7 @@ def urlize(
|
||||
if trim_url_limit is not None:
|
||||
|
||||
def trim_url(x: str) -> str:
|
||||
if len(x) > trim_url_limit: # type: ignore
|
||||
if len(x) > trim_url_limit:
|
||||
return f"{x[:trim_url_limit]}..."
|
||||
|
||||
return x
|
||||
|
Loading…
Reference in New Issue
Block a user