Skip to content

Commit

Permalink
move wildcard_matcher into separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
jsuchan-reef committed Aug 15, 2023
1 parent 8c53fa2 commit 69b1232
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 20 deletions.
22 changes: 2 additions & 20 deletions b2sdk/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@
######################################################################
from __future__ import annotations

import fnmatch
import logging
from contextlib import suppress
from functools import partial

from wcmatch import glob as wcglob

from b2sdk.session import B2Session

Expand Down Expand Up @@ -53,7 +49,7 @@
limit_trace_arguments,
validate_b2_file_name,
)
from .utils.wildcards import WildcardStyle, get_solid_prefix
from .utils.wildcards import WildcardStyle, get_solid_prefix, get_wildcard_matcher

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -374,21 +370,7 @@ def ls(

if with_wildcard:
prefix = get_solid_prefix(prefix, folder_to_list, wildcard_style)
if wildcard_style == WildcardStyle.GLOB:
wildcard_matcher = partial(
lambda file_name: fnmatch.fnmatchcase(file_name, folder_to_list)
)
else:
wc_flags = (
wcglob.CASE # case sensitive
| wcglob.BRACE # support {} for multiple options
| wcglob.GLOBSTAR # support ** for recursive matching
| wcglob.NEGATE # support [!] for negation
)
wildcard_matcher = partial(
lambda file_name: wcglob.
globmatch(file_name, folder_to_list, flags=wc_flags, limit=100)
)
wildcard_matcher = get_wildcard_matcher(folder_to_list, wildcard_style)
elif prefix != '' and not prefix.endswith('/'):
# we don't assume that this is folder that we're searching through.
# It could be an exact file, e.g. 'a/b.txt' that we're trying to locate.
Expand Down
26 changes: 26 additions & 0 deletions b2sdk/utils/wildcards.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@
######################################################################
from __future__ import annotations

import fnmatch
import pathlib
from enum import Enum
from functools import partial
from typing import Callable

from wcmatch import glob as wcglob


class WildcardStyle(str, Enum):
Expand Down Expand Up @@ -88,3 +93,24 @@ def get_solid_prefix(
# We could receive paths in different stage, e.g. 'a/*/result.[ct]sv' has two
# possible parent paths: 'a/' and 'a/*/', with the first one being the correct one
return min(parent_path, current_prefix, key=len)


def get_wildcard_matcher(match_pattern: str,
wildcard_style: WildcardStyle) -> Callable[[str], bool]:
"""Return a wildcard matcher for chosen style and pattern."""
if wildcard_style == WildcardStyle.SHELL:
wc_flags = (
wcglob.CASE # case sensitive
| wcglob.BRACE # support {} for multiple options
| wcglob.GLOBSTAR # support ** for recursive matching
| wcglob.NEGATE # support [!] for negation
)
wildcard_matcher = partial(
lambda file_name: wcglob.globmatch(file_name, match_pattern, flags=wc_flags, limit=100)
)
elif wildcard_style == WildcardStyle.GLOB:
wildcard_matcher = partial(lambda file_name: fnmatch.fnmatchcase(file_name, match_pattern))
else:
raise ValueError(f"Unknown wildcard style: {wildcard_style}")

return wildcard_matcher

0 comments on commit 69b1232

Please sign in to comment.