1"""
2This module provides aggregated private data and utilities functions about the
3available backends.
4
5WARNING: The *pathspec._backends* package is not part of the public API. Its
6contents and structure are likely to change.
7"""
8
9from collections.abc import (
10 Sequence)
11from typing import (
12 cast)
13
14from pathspec.backend import (
15 BackendNamesHint,
16 _Backend)
17from pathspec.pattern import (
18 Pattern,
19 RegexPattern)
20
21from ._utils import (
22 has_unsupported_flags)
23
24from .hyperscan.base import (
25 hyperscan_error)
26from .hyperscan.gitignore import (
27 HyperscanGiBackend)
28from .hyperscan.pathspec import (
29 HyperscanPsBackend)
30from .re2.base import (
31 re2_error)
32from .re2.gitignore import (
33 Re2GiBackend)
34from .re2.pathspec import (
35 Re2PsBackend)
36from .simple.gitignore import (
37 SimpleGiBackend)
38from .simple.pathspec import (
39 SimplePsBackend)
40
41_BEST_BACKEND: BackendNamesHint
42"""
43The best available backend.
44"""
45
46if re2_error is None:
47 _BEST_BACKEND = 're2'
48elif hyperscan_error is None:
49 _BEST_BACKEND = 'hyperscan'
50else:
51 _BEST_BACKEND = 'simple'
52
53
54def make_gitignore_backend(
55 name: BackendNamesHint,
56 patterns: Sequence[Pattern],
57) -> _Backend:
58 """
59 Create the specified backend with the supplied patterns for
60 :class:`~pathspec.gitignore.GitIgnoreSpec`.
61
62 *name* (:class:`str`) is the name of the backend.
63
64 *patterns* (:class:`.Iterable` of :class:`.Pattern`) contains the compiled
65 patterns.
66
67 Returns the backend (:class:`._Backend`).
68 """
69 if name == 'best':
70 name = _BEST_BACKEND
71 if name != 'simple' and has_unsupported_flags(patterns):
72 # Only the simple backend can keep the compile flags of the patterns it
73 # was given.
74 name = 'simple'
75
76 if name == 'hyperscan':
77 return HyperscanGiBackend(cast(Sequence[RegexPattern], patterns))
78 elif name == 're2':
79 return Re2GiBackend(cast(Sequence[RegexPattern], patterns))
80 elif name == 'simple':
81 return SimpleGiBackend(cast(Sequence[RegexPattern], patterns))
82 else:
83 raise ValueError(f"Backend {name=!r} is invalid.")
84
85
86def make_pathspec_backend(
87 name: BackendNamesHint,
88 patterns: Sequence[Pattern],
89) -> _Backend:
90 """
91 Create the specified backend with the supplied patterns for
92 :class:`~pathspec.pathspec.PathSpec`.
93
94 *name* (:class:`str`) is the name of the backend.
95
96 *patterns* (:class:`Iterable` of :class:`Pattern`) contains the compiled
97 patterns.
98
99 Returns the backend (:class:`._Backend`).
100 """
101 if name == 'best':
102 name = _BEST_BACKEND
103 if name != 'simple' and (
104 any(not isinstance(pattern, RegexPattern) for pattern in patterns)
105 or has_unsupported_flags(patterns)
106 ):
107 # Only the simple backend supports custom patterns and compile flags that
108 # cannot be translated.
109 name = 'simple'
110
111 if name == 'hyperscan':
112 return HyperscanPsBackend(cast(Sequence[RegexPattern], patterns))
113 elif name == 're2':
114 return Re2PsBackend(cast(Sequence[RegexPattern], patterns))
115 elif name == 'simple':
116 return SimplePsBackend(patterns)
117 else:
118 raise ValueError(f"Backend {name=!r} is invalid.")