From b43531f8d82a68df2338b001fec8c62a42be6ae5 Mon Sep 17 00:00:00 2001 From: David Lord Date: Mon, 21 Oct 2019 07:00:25 -0700 Subject: [PATCH] use fspath instead of str --- CHANGES.rst | 6 +++--- jinja2/_compat.py | 24 +++++++++++++++++++----- jinja2/loaders.py | 31 ++++++++++++++++++------------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 45eab845..bc3114de 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -49,9 +49,9 @@ Unreleased :pr:`993` - ``PackageLoader`` doesn't depend on setuptools or pkg_resources. :issue:`970` -- Allow passing ``pathlib.Path`` as the search path in - :class:`~loader.FileSystemLoader` and - :class:`~loader.ModuleLoader`. :issue:`870` +- Support :class:`os.PathLike` objects in + :class:`~loader.FileSystemLoader` and :class:`~loader.ModuleLoader`. + :issue:`870` Version 2.10.3 diff --git a/jinja2/_compat.py b/jinja2/_compat.py index 65f047e3..814d2246 100644 --- a/jinja2/_compat.py +++ b/jinja2/_compat.py @@ -24,9 +24,6 @@ if not PY2: string_types = (str,) integer_types = (int,) - import pathlib - path_types = (str, pathlib.PurePath) - iterkeys = lambda d: iter(d.keys()) itervalues = lambda d: iter(d.values()) iteritems = lambda d: iter(d.items()) @@ -56,8 +53,6 @@ else: string_types = (str, unicode) integer_types = (int, long) - path_types = string_types - iterkeys = lambda d: d.iterkeys() itervalues = lambda d: d.itervalues() iteritems = lambda d: d.iteritems() @@ -108,3 +103,22 @@ try: from collections import abc except ImportError: import collections as abc + + +try: + from os import fspath +except ImportError: + try: + from pathlib import PurePath + except ImportError: + PurePath = None + + def fspath(path): + if hasattr(path, "__fspath__"): + return path.__fspath__() + + # Python 3.5 doesn't have __fspath__ yet, use str. + if PurePath is not None and isinstance(path, PurePath): + return str(path) + + return path diff --git a/jinja2/loaders.py b/jinja2/loaders.py index 40118fd5..3101bc3a 100644 --- a/jinja2/loaders.py +++ b/jinja2/loaders.py @@ -17,7 +17,7 @@ from os import path from hashlib import sha1 from jinja2.exceptions import TemplateNotFound from jinja2.utils import open_if_exists, internalcode -from jinja2._compat import string_types, path_types, iteritems +from jinja2._compat import string_types, iteritems, fspath, abc def split_template_path(template): @@ -154,18 +154,20 @@ class FileSystemLoader(BaseLoader): >>> loader = FileSystemLoader('/path/to/templates', followlinks=True) - .. versionchanged:: 2.8+ - The *followlinks* parameter was added. + .. versionchanged:: 2.8 + The ``followlinks`` parameter was added. """ def __init__(self, searchpath, encoding='utf-8', followlinks=False): - if isinstance(searchpath, path_types): + if ( + not isinstance(searchpath, abc.Iterable) + or isinstance(searchpath, string_types) + ): searchpath = [searchpath] - # In Python 3.5, os.path.join only supports strings, not instances - # of pathlib.Path. This line can be simplified to list(searchpath) - # when support for Python 3.5 is dropped. - self.searchpath = [str(path) for path in searchpath] + # In Python 3.5, os.path.join doesn't support Path. This can be + # simplified to list(searchpath) when Python 3.5 is dropped. + self.searchpath = [fspath(p) for p in searchpath] self.encoding = encoding self.followlinks = followlinks @@ -489,11 +491,14 @@ class ModuleLoader(BaseLoader): # create a fake module that looks for the templates in the # path given. mod = _TemplateModule(package_name) - if isinstance(path, path_types): - path = [str(path)] - else: - path = [str(p) for p in path] - mod.__path__ = path + + if ( + not isinstance(path, abc.Iterable) + or isinstance(path, string_types) + ): + path = [path] + + mod.__path__ = [fspath(p) for p in path] sys.modules[package_name] = weakref.proxy(mod, lambda x: sys.modules.pop(package_name, None)) -- 2.47.2