Initial import: grid-bot — grid trading bot for BTC-USDT on Cifra Markets
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# mypy: allow-untyped-defs
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from collections.abc import Iterable
|
||||
|
||||
|
||||
GlobPattern = str | Iterable[str]
|
||||
|
||||
|
||||
class GlobGroup:
|
||||
"""A set of patterns that candidate strings will be matched against.
|
||||
|
||||
A candidate is composed of a list of segments separated by ``separator``, e.g. "foo.bar.baz".
|
||||
|
||||
A pattern contains one or more segments. Segments can be:
|
||||
- A literal string (e.g. "foo"), which matches exactly.
|
||||
- A string containing a wildcard (e.g. "torch*", or "foo*baz*"). The wildcard matches
|
||||
any string, including the empty string.
|
||||
- A double wildcard ("**"). This matches against zero or more complete segments.
|
||||
|
||||
Examples:
|
||||
``torch.**``: matches ``torch`` and all its submodules, e.g. ``torch.nn`` and ``torch.nn.functional``.
|
||||
``torch.*``: matches ``torch.nn`` or ``torch.functional``, but not ``torch.nn.functional``.
|
||||
``torch*.**``: matches ``torch``, ``torchvision``, and all their submodules.
|
||||
|
||||
A candidates will match the ``GlobGroup`` if it matches any of the ``include`` patterns and
|
||||
none of the ``exclude`` patterns.
|
||||
|
||||
Args:
|
||||
include (str | Iterable[str]): A string or list of strings,
|
||||
each representing a pattern to be matched against. A candidate
|
||||
will match if it matches *any* include pattern
|
||||
exclude (str | Iterable[str]): A string or list of strings,
|
||||
each representing a pattern to be matched against. A candidate
|
||||
will be excluded from matching if it matches *any* exclude pattern.
|
||||
separator (str): A string that delimits segments in candidates and
|
||||
patterns. By default this is "." which corresponds to how modules are
|
||||
named in Python. Another common value for this is "/", which is
|
||||
the Unix path separator.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, include: GlobPattern, *, exclude: GlobPattern = (), separator: str = "."
|
||||
):
|
||||
self._dbg = f"GlobGroup(include={include}, exclude={exclude})"
|
||||
self.include = GlobGroup._glob_list(include, separator)
|
||||
self.exclude = GlobGroup._glob_list(exclude, separator)
|
||||
self.separator = separator
|
||||
|
||||
def __str__(self):
|
||||
return self._dbg
|
||||
|
||||
def __repr__(self):
|
||||
return self._dbg
|
||||
|
||||
def matches(self, candidate: str) -> bool:
|
||||
candidate = self.separator + candidate
|
||||
return any(p.fullmatch(candidate) for p in self.include) and all(
|
||||
not p.fullmatch(candidate) for p in self.exclude
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _glob_list(elems: GlobPattern, separator: str = "."):
|
||||
if isinstance(elems, str):
|
||||
return [GlobGroup._glob_to_re(elems, separator)]
|
||||
else:
|
||||
return [GlobGroup._glob_to_re(e, separator) for e in elems]
|
||||
|
||||
@staticmethod
|
||||
def _glob_to_re(pattern: str, separator: str = "."):
|
||||
# to avoid corner cases for the first component, we prefix the candidate string
|
||||
# with '.' so `import torch` will regex against `.torch`, assuming '.' is the separator
|
||||
def component_to_re(component):
|
||||
if "**" in component:
|
||||
if component == "**":
|
||||
return "(" + re.escape(separator) + "[^" + separator + "]+)*"
|
||||
else:
|
||||
raise ValueError("** can only appear as an entire path segment")
|
||||
else:
|
||||
return re.escape(separator) + ("[^" + separator + "]*").join(
|
||||
re.escape(x) for x in component.split("*")
|
||||
)
|
||||
|
||||
result = "".join(component_to_re(c) for c in pattern.split(separator))
|
||||
return re.compile(result)
|
||||
Reference in New Issue
Block a user