Skip to content

Commit

Permalink
Merge 6f2fa13 into 12cd2f4
Browse files Browse the repository at this point in the history
  • Loading branch information
atollk committed Sep 5, 2021
2 parents 12cd2f4 + 6f2fa13 commit c31bbaa
Show file tree
Hide file tree
Showing 8 changed files with 616 additions and 158 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

- Added `filter_glob` and `exclude_glob` parameters to `fs.walk.Walker`.
Closes [#459](https://github.com/PyFilesystem/pyfilesystem2/issues/459).
- Added `fs.copy.copy_file_if`, `fs.copy.copy_dir_if`, and `fs.copy.copy_fs_if`.
Closes [#458](https://github.com/PyFilesystem/pyfilesystem2/issues/458).
- Added `fs.base.FS.getmodified`.
Expand All @@ -22,6 +24,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

- Elaborated documentation of `filter_dirs` and `exclude_dirs` in `fs.walk.Walker`.
Closes [#371](https://github.com/PyFilesystem/pyfilesystem2/issues/371).
- Fixed performance bugs in `fs.copy.copy_dir_if_newer`. Test cases were adapted to catch those bugs in the future.
- Fixed precision bug for timestamps in `fs.OSFS.setinfo`.

Expand Down
59 changes: 58 additions & 1 deletion fs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import six

from . import copy, errors, fsencode, iotools, move, tools, walk, wildcard
from . import copy, errors, fsencode, iotools, move, tools, walk, wildcard, glob
from .copy import copy_modified_time
from .glob import BoundGlobber
from .mode import validate_open_mode
Expand Down Expand Up @@ -1691,6 +1691,63 @@ def match(self, patterns, name):
matcher = wildcard.get_matcher(patterns, case_sensitive)
return matcher(name)

def match_glob(self, patterns, path, accept_prefix=False):
# type: (Optional[Iterable[Text]], Text, bool) -> bool
"""Check if a path matches any of a list of glob patterns.
If a filesystem is case *insensitive* (such as Windows) then
this method will perform a case insensitive match (i.e. ``*.py``
will match the same names as ``*.PY``). Otherwise the match will
be case sensitive (``*.py`` and ``*.PY`` will match different
names).
Arguments:
patterns (list, optional): A list of patterns, e.g.
``['*.py']``, or `None` to match everything.
path (str): A resource path, starting with "/".
accept_prefix (bool): If ``True``, the path is
not required to match the patterns themselves
but only need to be a prefix of a string that does.
Returns:
bool: `True` if ``path`` matches any of the patterns.
Raises:
TypeError: If ``patterns`` is a single string instead of
a list (or `None`).
ValueError: If ``path`` is not a string starting with "/".
Example:
>>> my_fs.match_glob(['*.py'], '/__init__.py')
True
>>> my_fs.match_glob(['*.jpg', '*.png'], '/foo.gif')
False
>>> my_fs.match_glob(['dir/file.txt'], '/dir/', accept_prefix=True)
True
>>> my_fs.match_glob(['dir/file.txt'], '/dir/', accept_prefix=False)
False
>>> my_fs.match_glob(['dir/file.txt'], '/dir/gile.txt', accept_prefix=True)
False
Note:
If ``patterns`` is `None` (or ``['*']``), then this
method will always return `True`.
"""
if patterns is None:
return True
if not path or path[0] != "/":
raise ValueError("%s needs to be a string starting with /" % path)
if isinstance(patterns, six.text_type):
raise TypeError("patterns must be a list or sequence")
case_sensitive = not typing.cast(
bool, self.getmeta().get("case_insensitive", False)
)
matcher = glob.get_matcher(
patterns, case_sensitive, accept_prefix=accept_prefix
)
return matcher(path)

def tree(self, **kwargs):
# type: (**Any) -> None
"""Render a tree view of the filesystem to stdout or a file.
Expand Down
18 changes: 18 additions & 0 deletions fs/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"OperationFailed",
"OperationTimeout",
"PathError",
"PatternError",
"PermissionDenied",
"RemoteConnectionError",
"RemoveRootError",
Expand All @@ -51,6 +52,7 @@
"ResourceNotFound",
"ResourceReadOnly",
"Unsupported",
"UnsupportedHash",
]


Expand Down Expand Up @@ -346,3 +348,19 @@ class UnsupportedHash(ValueError):
not supported by hashlib.
"""


class PatternError(ValueError):
"""A string pattern with invalid syntax was given."""

default_message = "pattern '{pattern}' is invalid at position {position}"

def __init__(self, pattern, position, exc=None, msg=None): # noqa: D107
# type: (Text, int, Optional[Exception], Optional[Text]) -> None
self.pattern = pattern
self.position = position
self.exc = exc
super(ValueError, self).__init__()

def __reduce__(self):
return type(self), (self.path, self.position, self.exc, self._msg)
Loading

0 comments on commit c31bbaa

Please sign in to comment.