diff --git a/.github/.gitignore b/.github/.gitignore
deleted file mode 100644
index b9bdbd9..0000000
--- a/.github/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!actions/
-!actions/*
-!ISSUE_TEMPLATE/
-!ISSUE_TEMPLATE/*
-!workflows/
-!workflows/*
-
-!.gitignore
diff --git a/.github/ISSUE_TEMPLATE/.gitignore b/.github/ISSUE_TEMPLATE/.gitignore
deleted file mode 100644
index fc83fe4..0000000
--- a/.github/ISSUE_TEMPLATE/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!bug_report.yml
-!feature_request.yml
-!question.md
-
-!.gitignore
diff --git a/.github/actions/.gitignore b/.github/actions/.gitignore
deleted file mode 100644
index 4769b9d..0000000
--- a/.github/actions/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!build_regex_toolkit/
-!build_regex_toolkit/*
-!run-tests/
-!run-tests/*
-!setup-conda/
-!setup-conda/*
-
-!.gitignore
diff --git a/.github/actions/build_regex_toolkit/.gitignore b/.github/actions/build_regex_toolkit/.gitignore
deleted file mode 100644
index 34b5ce3..0000000
--- a/.github/actions/build_regex_toolkit/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!action.yml
-
-!.gitignore
diff --git a/.github/actions/run-tests/.gitignore b/.github/actions/run-tests/.gitignore
deleted file mode 100644
index 34b5ce3..0000000
--- a/.github/actions/run-tests/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!action.yml
-
-!.gitignore
diff --git a/.github/actions/setup-conda/.gitignore b/.github/actions/setup-conda/.gitignore
deleted file mode 100644
index 34b5ce3..0000000
--- a/.github/actions/setup-conda/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!action.yml
-
-!.gitignore
diff --git a/.github/workflows/.gitignore b/.github/workflows/.gitignore
deleted file mode 100644
index dcba760..0000000
--- a/.github/workflows/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!stale-pr.yml
-!ubuntu.yml
-windows-macos.yml
-
-!.gitignore
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index 31b8edd..271e53c 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -4,7 +4,7 @@ on:
push:
branches: ["main"]
pull_request:
- branches: ["main"]
+ branches: ["main", "*.*.*-release"]
paths-ignore: ["docs/**"]
env:
@@ -15,22 +15,24 @@ permissions:
jobs:
run-tests:
- runs-on: ubuntu-22.04
+ runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash -el {0}
timeout-minutes: 60
strategy:
matrix:
+ os: ["ubuntu-latest"]
python_version: ["310", "311", "312"]
+ # python_version: ["310", "311", "312", "313"]
fail-fast: false
- name: Python ${{ matrix.python_version }}
+ name: ${{ format('{0} Python {1}', matrix.os, matrix.python_version) }}
env:
ENV_FILE: ci/deps/actions-${{ matrix.python_version }}.yml
IS_PYPY: ${{ contains(matrix.python_version, 'pypy') }}
concurrency:
# https://github.community/t/concurrecy-not-work-for-push/183068/7
- group: ${{ github.event_name == 'push' && github.run_number || github.ref }}-${{ matrix.python_version }}
+ group: ${{ github.event_name == 'push' && github.run_number || github.ref }}-${{ matrix.os }}-${{ matrix.python_version }}
cancel-in-progress: true
steps:
- name: Checkout
@@ -39,7 +41,7 @@ jobs:
- name: Set up Conda
uses: ./.github/actions/setup-conda
with:
- environment-name: ${{ matrix.python_version }}-env
+ environment-name: ${{ matrix.os }}-${{ matrix.python_version }}-env
environment-file: ${{ env.ENV_FILE }}
- name: Build Regex-Toolkit
diff --git a/.gitignore b/.gitignore
index b04526a..d9c96b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,30 +1,165 @@
-# Ignore everything
-*
-
-# Except
-!setup.py
-!pyproject.toml
-!Makefile
-!environment.yml
-!codecov.yml
-!requirements-doc.txt
-!requirements-test.txt
-
-!src/
-!src/*
-!tests/
-!tests/*
-!ci/
-!ci/*
-!docs/
-!docs/*
-
-!LICENSE
-!README.md
-!.gitignore
-
-!.git/
-!.git/*
-
-!.github/
-!.github/*
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
+.pdm.toml
+.pdm-python
+.pdm-build/
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+.idea/
+
+# Common user directories
+old/
+todo/
+
+# Pytest test data
+test-data.xml
diff --git a/Makefile b/Makefile
index 9115bef..d08d717 100644
--- a/Makefile
+++ b/Makefile
@@ -19,8 +19,8 @@ lint:
format:
@echo 'Formatting code'
- ${PYTHON} -m isort src tests docs/render_readme.py
- ${PYTHON} -m black src tests docs/render_readme.py
+ ${PYTHON} -m isort --sp pyproject.toml src tests docs/render_readme.py
+ ${PYTHON} -m black --config pyproject.toml src tests docs/render_readme.py
@echo 'Done'
build:
diff --git a/README.md b/README.md
index d4ab9c9..1380d83 100644
--- a/README.md
+++ b/README.md
@@ -22,10 +22,10 @@ You should have received a copy of the GNU General Public License along with thi
---
-[Requirements](#requirements)
-[Installing](#installing)
-[Usage](#usage)
-[Library](#library)
+- [Requirements](#requirements)
+- [Installing](#installing)
+- [Usage](#usage)
+- [Library](#library)
## Installing
@@ -425,12 +425,12 @@ rtk.escape("/", flavor=2)
- `ValueError` - Invalid regex flavor.
- `TypeError` - Invalid type for `char`.
-
+
-#### `string_as_exp`
+#### `string_as_expr`
```python
-def string_as_exp(text: str, flavor: int | None = None) -> str
+def string_as_expr(text: str, flavor: int | None = None) -> str
```
Create a regex expression that exactly matches a string.
@@ -440,10 +440,10 @@ Create a regex expression that exactly matches a string.
```python
import regex_toolkit as rtk
-rtk.string_as_exp("http://www.example.com")
+rtk.string_as_expr("http://www.example.com")
# Output: 'https\:\/\/example\.com'
-rtk.string_as_exp("http://www.example.com", flavor=2)
+rtk.string_as_expr("http://www.example.com", flavor=2)
# Output: 'https\x{003a}\x{002f}\x{002f}example\.com'
```
@@ -460,12 +460,12 @@ rtk.string_as_exp("http://www.example.com", flavor=2)
- `ValueError` - Invalid regex flavor.
-
+
-#### `strings_as_exp`
+#### `strings_as_expr`
```python
-def strings_as_exp(texts: Iterable[str], flavor: int | None = None) -> str
+def strings_as_expr(texts: Iterable[str], flavor: int | None = None) -> str
```
Create a regex expression that exactly matches any one string.
@@ -475,10 +475,10 @@ Create a regex expression that exactly matches any one string.
```python
import regex_toolkit as rtk
-rtk.strings_as_exp(["apple", "banana", "cherry"])
+rtk.strings_as_expr(["apple", "banana", "cherry"])
# Output: 'banana|cherry|apple'
-rtk.strings_as_exp(["apple", "banana", "cherry"], flavor=2)
+rtk.strings_as_expr(["apple", "banana", "cherry"], flavor=2)
# Output: 'banana|cherry|apple'
```
@@ -495,12 +495,12 @@ rtk.strings_as_exp(["apple", "banana", "cherry"], flavor=2)
- `ValueError` - Invalid regex flavor.
-
+
-#### `make_exp`
+#### `make_expr`
```python
-def make_exp(chars: Iterable[str], flavor: int | None = None) -> str
+def make_expr(chars: Iterable[str], flavor: int | None = None) -> str
```
Create a regex expression that exactly matches a list of characters.
@@ -513,10 +513,10 @@ The expression is not anchored, so it can be used as part of a larger expression
```python
import regex_toolkit as rtk
-"[" + rtk.make_exp(["a", "b", "c", "z", "y", "x"]) + "]"
+"[" + rtk.make_expr(["a", "b", "c", "z", "y", "x"]) + "]"
# Output: '[a-cx-z]'
-"[" + rtk.make_exp(["a", "b", "c", "z", "y", "x"], flavor=2) + "]"
+"[" + rtk.make_expr(["a", "b", "c", "z", "y", "x"], flavor=2) + "]"
# Output: '[a-cx-z]'
```
diff --git a/ci/.gitignore b/ci/.gitignore
deleted file mode 100644
index 10b884c..0000000
--- a/ci/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!run_tests.sh
-!pre_commit.sh
-!condarc.yml
-
-!deps/
-!deps/*
-
-!.gitignore
diff --git a/ci/condarc.yml b/ci/condarc.yml
index 051ed76..9d750b7 100644
--- a/ci/condarc.yml
+++ b/ci/condarc.yml
@@ -1,8 +1,5 @@
# https://docs.conda.io/projects/conda/en/latest/configuration.html
-channels:
- - conda-forge
-
# always_yes (NoneType, bool)
# aliases: yes
# Automatically choose the 'yes' option whenever asked to proceed with a
diff --git a/ci/deps/.gitignore b/ci/deps/.gitignore
deleted file mode 100644
index 5ec9a8f..0000000
--- a/ci/deps/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!actions-310.yml
-!actions-311.yml
-!actions-312.yml
-!actions-313.yml
-
-!.gitignore
diff --git a/ci/deps/actions-310.yml b/ci/deps/actions-310.yml
index 6c933fb..894f672 100644
--- a/ci/deps/actions-310.yml
+++ b/ci/deps/actions-310.yml
@@ -6,7 +6,6 @@ dependencies:
# Test dependencies
- pytest>=7.0.0
- - pytest-cov
- - pytest-xdist>=2.2.0
+ - pytest-cov>=6.0.0
- pip:
- google-re2>=1.0
diff --git a/ci/deps/actions-311.yml b/ci/deps/actions-311.yml
index e663081..0046a2f 100644
--- a/ci/deps/actions-311.yml
+++ b/ci/deps/actions-311.yml
@@ -6,7 +6,6 @@ dependencies:
# Test dependencies
- pytest>=7.0.0
- - pytest-cov
- - pytest-xdist>=2.2.0
+ - pytest-cov>=6.0.0
- pip:
- google-re2>=1.0
diff --git a/ci/deps/actions-312.yml b/ci/deps/actions-312.yml
index c67a9d6..0e4eea7 100644
--- a/ci/deps/actions-312.yml
+++ b/ci/deps/actions-312.yml
@@ -6,7 +6,6 @@ dependencies:
# Test dependencies
- pytest>=7.0.0
- - pytest-cov
- - pytest-xdist>=2.2.0
+ - pytest-cov>=6.0.0
- pip:
- google-re2>=1.0
diff --git a/ci/deps/actions-313.yml b/ci/deps/actions-313.yml
new file mode 100644
index 0000000..08ca9ae
--- /dev/null
+++ b/ci/deps/actions-313.yml
@@ -0,0 +1,11 @@
+name: regex_toolkit
+channels:
+ - conda-forge
+dependencies:
+ - python=3.13
+
+ # Test dependencies
+ - pytest>=7.0.0
+ - pytest-cov>=6.0.0
+ - pip:
+ - google-re2>=1.0
diff --git a/ci/run_tests.sh b/ci/run_tests.sh
index bb97064..61e9614 100755
--- a/ci/run_tests.sh
+++ b/ci/run_tests.sh
@@ -1,12 +1,8 @@
#!/bin/bash -e
-# Workaround for pytest-xdist (it collects different tests in the workers if PYTHONHASHSEED is not set)
-# https://github.com/pytest-dev/pytest/issues/920
-# https://github.com/pytest-dev/pytest/issues/1075
-export PYTHONHASHSEED=$(python -c 'import random; print(random.randint(1, 4294967295))')
-
-# May help reproduce flaky CI builds if set in subsequent runs
-echo PYTHONHASHSEED=$PYTHONHASHSEED
+PYTHONHASHSEED=$(python -c 'import random; print(random.randint(1, 4294967295))')
+export PYTHONHASHSEED
+echo "PYTHONHASHSEED=$PYTHONHASHSEED"
# If no X server is found, we use xvfb to emulate it
if [[ $(uname) == "Linux" && -z $DISPLAY ]]; then
@@ -14,9 +10,8 @@ if [[ $(uname) == "Linux" && -z $DISPLAY ]]; then
XVFB="xvfb-run "
fi
-# TODO: Consider adding as an input parameter
PYTEST_TARGET=tests
PYTEST_CMD="${XVFB}pytest -r fEs -s --cov=src --cov-report=xml --cov-append $PYTEST_TARGET"
-echo $PYTEST_CMD
+echo "$PYTEST_CMD"
sh -c "$PYTEST_CMD"
diff --git a/docs/.gitignore b/docs/.gitignore
deleted file mode 100644
index 95f63f7..0000000
--- a/docs/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!render_readme.py
-!config.json
-
-!templates/
-!templates/*
-
-!.gitignore
diff --git a/docs/templates/.gitignore b/docs/templates/.gitignore
index 2e53636..bd5355b 100644
--- a/docs/templates/.gitignore
+++ b/docs/templates/.gitignore
@@ -1,14 +1 @@
-# Ignore everything
-*
-
-# Except
-!body.md.jinja
-!header.md.jinja
-!footer.md.jinja
-!install.md.jinja
-!library.md.jinja
-!requirements.md.jinja
-!usage.md.jinja
-!main.md.jinja
-
-!.gitignore
+rendered_libs.md
diff --git a/docs/templates/body.md.jinja b/docs/templates/body.md.jinja
index 10b23bc..41da2e8 100644
--- a/docs/templates/body.md.jinja
+++ b/docs/templates/body.md.jinja
@@ -4,10 +4,10 @@
---
-[Requirements](#requirements)
-[Installing](#installing)
-[Usage](#usage)
-[Library](#library)
+- [Requirements](#requirements)
+- [Installing](#installing)
+- [Usage](#usage)
+- [Library](#library)
## Installing
diff --git a/environment.yml b/environment.yml
index 09760df..17a5119 100644
--- a/environment.yml
+++ b/environment.yml
@@ -1,21 +1,20 @@
# Local development dependencies including docs building, website upload, ASV benchmark
-name: regex_toolkit
+name: regex-toolkit
channels:
- conda-forge
dependencies:
- python=3.10
- pip
- # Test dependencies
- - pytest>=7.0.0
- - pytest-cov
- - pytest-xdist>=2.2.0
- - coverage
- - pip:
- - google-re2>=1.0
-
# Code checks
- black=22.10.0
- - flake8=6.0.0
+ - pylint>=3.0.0
- isort>=5.2.1
- mypy=1.0
+ - codespell>=2.0.0
+
+ # Test dependencies
+ - pytest>=7.0.0
+ - pytest-cov>=6.0.0
+ - pip:
+ - google-re2>=1.0
diff --git a/pyproject.toml b/pyproject.toml
index bce4035..cc48fca 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -22,6 +22,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
"Topic :: Utilities",
"Topic :: Software Development",
"Topic :: Software Development :: Libraries",
@@ -47,10 +48,7 @@ branch = true
source = ["src"]
[tool.coverage.paths]
-source = [
- "src",
- # "*/site-packages"
-]
+source = ["src"]
[tool.coverage.report]
ignore_errors = false
@@ -78,7 +76,7 @@ max-line-length = 88
disable = []
[tool.black]
-target-version = ['py310', 'py311']
+target-version = ["py310", "py311", "py312"]
exclude = '''
(
asv_bench/env
@@ -135,7 +133,6 @@ sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
[tool.pytest.ini_options]
-# NOTE: Have not decided on a minimum version yet
minversion = "7.0"
addopts = "--strict-config --strict-markers --capture=no --junitxml=test-data.xml"
empty_parameter_set_mark = "fail_at_collect"
@@ -153,7 +150,6 @@ doctest_optionflags = [
filterwarnings = []
junit_family = "xunit2"
markers = []
-# asyncio_mode = "strict"
[tool.codespell]
ignore-words-list = "" # "foo, bar, baz"
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 0000000..763b08a
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1,5 @@
+black>=22.10.0
+pylint>=3.0.0
+isort>=5.2.1
+mypy>=1.0
+codespell>=2.0.0
diff --git a/requirements-doc.txt b/requirements-doc.txt
index 8a39850..396fb5a 100644
--- a/requirements-doc.txt
+++ b/requirements-doc.txt
@@ -1,2 +1,2 @@
novella==0.2.3
-pydoc-markdown==4.6.4
\ No newline at end of file
+pydoc-markdown==4.6.4
diff --git a/requirements-test.txt b/requirements-test.txt
index bed0b62..46e405d 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -1,4 +1,3 @@
pytest>=7.0.0
-pytest-cov
-pytest-xdist>=2.2.0
+pytest-cov>=6.0.0
google-re2>=1.0
diff --git a/src/.gitignore b/src/.gitignore
deleted file mode 100644
index a17f0c1..0000000
--- a/src/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!regex_toolkit/
-!regex_toolkit/*
-
-!.gitignore
diff --git a/src/regex_toolkit/.gitignore b/src/regex_toolkit/.gitignore
deleted file mode 100644
index 69400b7..0000000
--- a/src/regex_toolkit/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!__init__.py
-!base.py
-!constants.py
-!enums.py
-!utils.py
-
-!.gitignore
diff --git a/src/regex_toolkit/__init__.py b/src/regex_toolkit/__init__.py
index f62e972..4c509fb 100644
--- a/src/regex_toolkit/__init__.py
+++ b/src/regex_toolkit/__init__.py
@@ -1,8 +1,8 @@
from .base import (
escape,
- make_exp,
- string_as_exp,
- strings_as_exp,
+ make_expr,
+ string_as_expr,
+ strings_as_expr,
)
from .utils import (
char_range,
@@ -16,7 +16,7 @@
to_utf8,
)
-__version__ = "0.1.0"
+__version__ = "0.1.1"
__all__ = [
"char_range",
@@ -24,12 +24,12 @@
"cpoint_to_ord",
"escape",
"iter_char_range",
- "make_exp",
+ "make_expr",
"mask_span",
"mask_spans",
"ord_to_cpoint",
- "string_as_exp",
- "strings_as_exp",
+ "string_as_expr",
+ "strings_as_expr",
"to_nfc",
"to_utf8",
]
diff --git a/src/regex_toolkit/base.py b/src/regex_toolkit/base.py
index 0da577e..97ca90b 100644
--- a/src/regex_toolkit/base.py
+++ b/src/regex_toolkit/base.py
@@ -8,9 +8,9 @@
__all__ = [
"default_flavor",
"escape",
- "make_exp",
- "string_as_exp",
- "strings_as_exp",
+ "make_expr",
+ "string_as_expr",
+ "strings_as_expr",
"resolve_flavor",
]
@@ -108,15 +108,15 @@ def escape(char: str, flavor: int | None = None) -> str:
return _escape2(char)
-def _string_as_exp(text: str) -> str:
+def _string_as_expr(text: str) -> str:
return r"".join(map(_escape, text))
-def _string_as_exp2(text: str) -> str:
+def _string_as_expr2(text: str) -> str:
return r"".join(map(_escape2, text))
-def string_as_exp(text: str, flavor: int | None = None) -> str:
+def string_as_expr(text: str, flavor: int | None = None) -> str:
"""Create a regex expression that exactly matches a string.
Example:
@@ -124,10 +124,10 @@ def string_as_exp(text: str, flavor: int | None = None) -> str:
```python
import regex_toolkit as rtk
- rtk.string_as_exp("http://www.example.com")
+ rtk.string_as_expr("http://www.example.com")
# Output: 'https\\:\\/\\/example\\.com'
- rtk.string_as_exp("http://www.example.com", flavor=2)
+ rtk.string_as_expr("http://www.example.com", flavor=2)
# Output: 'https\\x{003a}\\x{002f}\\x{002f}example\\.com'
```
@@ -142,20 +142,20 @@ def string_as_exp(text: str, flavor: int | None = None) -> str:
ValueError: Invalid regex flavor.
"""
if resolve_flavor(flavor) == RegexFlavor.RE:
- return _string_as_exp(text)
+ return _string_as_expr(text)
else:
- return _string_as_exp2(text)
+ return _string_as_expr2(text)
-def _strings_as_exp(texts: Iterable[str]) -> str:
- return r"|".join(map(_string_as_exp, iter_sort_by_len_and_alpha(texts)))
+def _strings_as_expr(texts: Iterable[str]) -> str:
+ return r"|".join(map(_string_as_expr, iter_sort_by_len_and_alpha(texts)))
-def _strings_as_exp2(texts: Iterable[str]) -> str:
- return r"|".join(map(_string_as_exp2, iter_sort_by_len_and_alpha(texts)))
+def _strings_as_expr2(texts: Iterable[str]) -> str:
+ return r"|".join(map(_string_as_expr2, iter_sort_by_len_and_alpha(texts)))
-def strings_as_exp(texts: Iterable[str], flavor: int | None = None) -> str:
+def strings_as_expr(texts: Iterable[str], flavor: int | None = None) -> str:
"""Create a regex expression that exactly matches any one string.
Example:
@@ -163,10 +163,10 @@ def strings_as_exp(texts: Iterable[str], flavor: int | None = None) -> str:
```python
import regex_toolkit as rtk
- rtk.strings_as_exp(["apple", "banana", "cherry"])
+ rtk.strings_as_expr(["apple", "banana", "cherry"])
# Output: 'banana|cherry|apple'
- rtk.strings_as_exp(["apple", "banana", "cherry"], flavor=2)
+ rtk.strings_as_expr(["apple", "banana", "cherry"], flavor=2)
# Output: 'banana|cherry|apple'
```
@@ -184,15 +184,15 @@ def strings_as_exp(texts: Iterable[str], flavor: int | None = None) -> str:
unique_texts = set(texts)
# if all(map(lambda text: len(text) == 1, unique_texts)):
# logger.warning(
- # "All strings are of length 1. Consider using make_exp() instead."
+ # "All strings are of length 1. Consider using make_expr() instead."
# )
if flavor == RegexFlavor.RE:
- return _strings_as_exp(unique_texts)
+ return _strings_as_expr(unique_texts)
else:
- return _strings_as_exp2(unique_texts)
+ return _strings_as_expr2(unique_texts)
-def _make_group_exp(group: list[int]) -> str:
+def _make_group_expr(group: list[int]) -> str:
if len(group) > 2:
# Represent as a character range
return _escape(chr(group[0])) + "-" + _escape(chr(group[-1]))
@@ -201,7 +201,7 @@ def _make_group_exp(group: list[int]) -> str:
return "".join((_escape(chr(char_ord)) for char_ord in group))
-def _make_group_exp2(group: list[int]) -> str:
+def _make_group_expr2(group: list[int]) -> str:
if len(group) > 2:
# Represent as a character range
return _escape2(chr(group[0])) + "-" + _escape2(chr(group[-1]))
@@ -210,7 +210,7 @@ def _make_group_exp2(group: list[int]) -> str:
return "".join((_escape2(chr(char_ord)) for char_ord in group))
-def make_exp(chars: Iterable[str], flavor: int | None = None) -> str:
+def make_expr(chars: Iterable[str], flavor: int | None = None) -> str:
"""Create a regex expression that exactly matches a list of characters.
The characters are sorted and grouped into ranges where possible.
@@ -221,10 +221,10 @@ def make_exp(chars: Iterable[str], flavor: int | None = None) -> str:
```python
import regex_toolkit as rtk
- "[" + rtk.make_exp(["a", "b", "c", "z", "y", "x"]) + "]"
+ "[" + rtk.make_expr(["a", "b", "c", "z", "y", "x"]) + "]"
# Output: '[a-cx-z]'
- "[" + rtk.make_exp(["a", "b", "c", "z", "y", "x"], flavor=2) + "]"
+ "[" + rtk.make_expr(["a", "b", "c", "z", "y", "x"], flavor=2) + "]"
# Output: '[a-cx-z]'
```
@@ -239,12 +239,12 @@ def make_exp(chars: Iterable[str], flavor: int | None = None) -> str:
ValueError: Invalid regex flavor.
"""
func = (
- _make_group_exp
+ _make_group_expr
if resolve_flavor(flavor) == RegexFlavor.RE
- else _make_group_exp2
+ else _make_group_expr2
)
- exp = ""
+ expr = ""
group = []
for char_ord in sorted(set(map(ord, chars))):
if not group:
@@ -255,10 +255,10 @@ def make_exp(chars: Iterable[str], flavor: int | None = None) -> str:
group.append(char_ord)
else:
# Make the group and start a new one
- exp += func(group)
+ expr += func(group)
group.clear()
group.append(char_ord)
if group:
# Make any remaining group
- exp += func(group)
- return exp
+ expr += func(group)
+ return expr
diff --git a/tests/.gitignore b/tests/.gitignore
deleted file mode 100644
index 9d40e1f..0000000
--- a/tests/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-# Ignore everything
-*
-
-# Except
-!test_base.py
-!test_enums.py
-!test_utils.py
-
-!.gitignore
diff --git a/tests/test_base.py b/tests/test_base.py
index f79461e..7ce360d 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -1,4 +1,3 @@
-# import random
import re
from collections.abc import Iterable
from itertools import product
@@ -63,43 +62,23 @@
# Test helpers
-def _check_exp_match(exp: str, text: str, flavor: int, *, should_match: bool) -> bool:
- if flavor == 1:
- found = bool(re.fullmatch(exp, text))
- return found if should_match else not found
- if flavor == 2:
- found = bool(re2.fullmatch(exp, text))
- return found if should_match else not found
+def _check_expr_match(expr: str, text: str, flavor: int) -> bool:
+ if flavor == RegexFlavor.RE:
+ return bool(re.fullmatch(expr, text))
+ if flavor == RegexFlavor.RE2:
+ return bool(re2.fullmatch(expr, text))
raise ValueError(f"Invalid regex flavor: {flavor!r}")
-def assert_exp_match(
- exp: str, text: str, flavor: int, *, should_match: bool = True
-) -> bool:
- assert _check_exp_match(exp, text, flavor, should_match=should_match), (
- f"RE{flavor} Pattern: {exp!r} should match {text!r}"
- if should_match
- else f"RE{flavor} Pattern: {exp!r} should not match {text!r}"
- )
-
-
-def assert_exp_not_match(exp: str, text: str, flavor: int) -> bool:
- assert_exp_match(exp, text, flavor, should_match=False)
+def assert_expr_match(expr: str, text: str, flavor: int) -> bool:
+ assert _check_expr_match(
+ expr, text, flavor
+ ), f"RE{flavor} Pattern: {expr!r} should match {text!r}"
-def assert_exp_match_all(
- exp: str,
- texts: Iterable[str],
- flavor: int,
- *,
- should_match: bool = True,
-) -> bool:
+def assert_expr_match_all(expr: str, texts: Iterable[str], flavor: int) -> bool:
for text in texts:
- assert_exp_match(exp, text, flavor, should_match=should_match)
-
-
-def assert_exp_not_match_any(exp: str, texts: Iterable[str], flavor: int) -> bool:
- assert_exp_match_all(exp, texts, flavor, should_match=False)
+ assert_expr_match(expr, text, flavor)
# Resolve flavor
@@ -185,31 +164,23 @@ def test_resolve_flavor_None_without_default_raises():
def test_escape_and_escape2_safe(char, expected, flavor):
actual = regex_toolkit.escape(char, flavor)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, char, flavor)
-
- exp_to_test = r"^[" + actual + r"]$"
- assert_exp_match(exp_to_test, char, flavor)
+ assert_expr_match(rf"^{actual}$", char, flavor)
+ assert_expr_match(rf"^[{actual}]$", char, flavor)
@pytest.mark.parametrize(
- "char, expected_exp",
+ "char, expected",
[(char, f"\\{char}") for char in ALWAYS_ESCAPE],
)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_escape_and_escape2_escapable(char, expected_exp, flavor):
+def test_escape_and_escape2_always_safe(char, expected, flavor):
actual = regex_toolkit.escape(char, flavor)
- assert actual == expected_exp
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, char, flavor)
-
- exp_to_test = r"^[" + actual + r"]$"
- assert_exp_match(exp_to_test, char, flavor)
+ assert actual == expected
+ assert_expr_match(rf"^{actual}$", char, flavor)
+ assert_expr_match(rf"^[{actual}]$", char, flavor)
-def test_escape_and_escape2_calls_expected_inner_func():
+def test_escape_and_escape2_calls_expected_internal_func():
char = "a"
flavor = RegexFlavor.RE
@@ -266,18 +237,14 @@ def test_escape_and_escape2_non_str(non_str_char, flavor):
@pytest.mark.parametrize(
- "char, expected_exp",
+ "char, expected",
[(char, f"\\{char}") for char in NON_ASCII_CHARS],
)
-def test_escape_unknown(char, expected_exp):
+def test_escape_unknown(char, expected):
actual = regex_toolkit.escape(char, RegexFlavor.RE)
- assert actual == expected_exp
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, char, RegexFlavor.RE)
-
- exp_to_test = r"^[" + actual + r"]$"
- assert_exp_match(exp_to_test, char, RegexFlavor.RE)
+ assert actual == expected
+ assert_expr_match(rf"^{actual}$", char, RegexFlavor.RE)
+ assert_expr_match(rf"^[{actual}]$", char, RegexFlavor.RE)
# RE2 - Escape
@@ -296,35 +263,26 @@ def test_escape_unknown(char, expected_exp):
def test_escape2_unknown(char, expected):
actual = regex_toolkit.escape(char, RegexFlavor.RE2)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, char, RegexFlavor.RE2)
-
- exp_to_test = r"^[" + actual + r"]$"
- assert_exp_match(exp_to_test, char, RegexFlavor.RE2)
+ assert_expr_match(rf"^{actual}$", char, RegexFlavor.RE2)
+ assert_expr_match(rf"^[{actual}]$", char, RegexFlavor.RE2)
def test_escape2_trimmed():
- text = "°"
+ char = "°"
expected = "\\x{00B0}"
- actual = regex_toolkit.escape(text, RegexFlavor.RE2)
+ actual = regex_toolkit.escape(char, RegexFlavor.RE2)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, text, RegexFlavor.RE2)
+ assert_expr_match(rf"^{actual}$", char, RegexFlavor.RE2)
+ assert_expr_match(rf"^[{actual}]$", char, RegexFlavor.RE2)
def test_escape2_untrimmed():
- text = "🅰"
+ char = "🅰"
expected = "\\x{0001F170}"
- actual = regex_toolkit.escape(text, RegexFlavor.RE2)
+ actual = regex_toolkit.escape(char, RegexFlavor.RE2)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, text, RegexFlavor.RE2)
-
- exp_to_test = r"^[" + actual + r"]$"
- assert_exp_match(exp_to_test, text, RegexFlavor.RE2)
+ assert_expr_match(rf"^{actual}$", char, RegexFlavor.RE2)
+ assert_expr_match(rf"^[{actual}]$", char, RegexFlavor.RE2)
# RE and RE2 - String as expression
@@ -332,23 +290,21 @@ def test_escape2_untrimmed():
@pytest.mark.parametrize("text, expected", [(text, text) for text in ALWAYS_SAFE])
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_string_as_exp_and_exp2_and_exp2_safe_individual_char(text, expected, flavor):
- actual = regex_toolkit.string_as_exp(text, flavor)
+def test_string_as_expr_and_expr2_and_expr2_safe_individual_char(
+ text, expected, flavor
+):
+ actual = regex_toolkit.string_as_expr(text, flavor)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, text, flavor)
+ assert_expr_match(rf"^{actual}$", text, flavor)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_string_as_exp_and_exp2_and_exp2_safe_joined_as_one(flavor):
+def test_string_as_expr_and_expr2_and_expr2_safe_joined_as_one(flavor):
text = "".join(ALWAYS_SAFE)
- expected = "".join(ALWAYS_SAFE)
- actual = regex_toolkit.string_as_exp(text, flavor)
+ expected = text
+ actual = regex_toolkit.string_as_expr(text, flavor)
assert actual == expected
-
- exp_to_test = actual
- assert_exp_match(exp_to_test, text, flavor)
+ assert_expr_match(rf"^{actual}$", text, flavor)
@pytest.mark.parametrize(
@@ -356,57 +312,51 @@ def test_string_as_exp_and_exp2_and_exp2_safe_joined_as_one(flavor):
[(char, f"\\{char}") for char in ALWAYS_ESCAPE],
)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_string_as_exp_and_exp2_escapable_individual_char(text, expected, flavor):
- actual = regex_toolkit.string_as_exp(text, flavor)
+def test_string_as_expr_and_expr2_always_safe_individual_char(text, expected, flavor):
+ actual = regex_toolkit.string_as_expr(text, flavor)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, text, flavor)
+ assert_expr_match(rf"^{actual}$", text, flavor)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_string_as_exp_and_exp2_escapable_joined_as_one(flavor):
+def test_string_as_expr_and_expr2_always_safe_joined_as_one(flavor):
text = "".join(ALWAYS_ESCAPE)
expected = "".join(f"\\{char}" for char in ALWAYS_ESCAPE)
- actual = regex_toolkit.string_as_exp(text, flavor)
+ actual = regex_toolkit.string_as_expr(text, flavor)
assert actual == expected
-
- exp_to_test = actual
- assert_exp_match(exp_to_test, text, flavor)
+ assert_expr_match(rf"^{actual}$", text, flavor)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_string_as_exp_and_exp2_matches_unicode_chars(flavor):
+def test_string_as_expr_and_expr2_matches_unicode_chars(flavor):
high_surrogate_pair_ords = set(range(0xD800, 0xDBFF + 1))
low_surrogate_pair_ords = set(range(0xDC00, 0xDFFF + 1))
- for i in (
+ for ord in (
set(range(0x0000, 0x10FFFF + 1))
- high_surrogate_pair_ords
- low_surrogate_pair_ords
):
- char = chr(i)
- actual = regex_toolkit.string_as_exp(char, flavor)
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, char, flavor)
+ char = chr(ord)
+ actual = regex_toolkit.string_as_expr(char, flavor)
+ assert_expr_match(rf"^{actual}$", char, flavor)
-def test_string_as_exp_and_exp2_calls_expected_inner_func():
+def test_string_as_expr_and_expr2_calls_expected_internal_func():
text = "foo"
flavor = RegexFlavor.RE
- with mock.patch("regex_toolkit.base._string_as_exp") as mock__string_as_exp:
- with mock.patch("regex_toolkit.base._string_as_exp2") as mock__string_as_exp2:
- regex_toolkit.string_as_exp(text, flavor)
- mock__string_as_exp.assert_called_once_with(text)
- mock__string_as_exp2.assert_not_called()
+ with mock.patch("regex_toolkit.base._string_as_expr") as mock__string_as_expr:
+ with mock.patch("regex_toolkit.base._string_as_expr2") as mock__string_as_expr2:
+ regex_toolkit.string_as_expr(text, flavor)
+ mock__string_as_expr.assert_called_once_with(text)
+ mock__string_as_expr2.assert_not_called()
flavor = RegexFlavor.RE2
- with mock.patch("regex_toolkit.base._string_as_exp") as mock__string_as_exp:
- with mock.patch("regex_toolkit.base._string_as_exp2") as mock__string_as_exp2:
- regex_toolkit.string_as_exp(text, flavor)
- mock__string_as_exp.assert_not_called()
- mock__string_as_exp2.assert_called_once_with(text)
+ with mock.patch("regex_toolkit.base._string_as_expr") as mock__string_as_expr:
+ with mock.patch("regex_toolkit.base._string_as_expr2") as mock__string_as_expr2:
+ regex_toolkit.string_as_expr(text, flavor)
+ mock__string_as_expr.assert_not_called()
+ mock__string_as_expr2.assert_called_once_with(text)
# RE - String as expression
@@ -416,22 +366,18 @@ def test_string_as_exp_and_exp2_calls_expected_inner_func():
"text, expected",
[(text, f"\\{text}") for text in NON_ASCII_CHARS],
)
-def test_string_as_exp_unsafe_individual_char(text, expected):
- actual = regex_toolkit.string_as_exp(text, RegexFlavor.RE)
+def test_string_as_expr_unsafe_individual_char(text, expected):
+ actual = regex_toolkit.string_as_expr(text, RegexFlavor.RE)
assert actual == expected
+ assert_expr_match(rf"^{actual}$", text, RegexFlavor.RE)
- exp_to_test = actual
- assert_exp_match(exp_to_test, text, RegexFlavor.RE)
-
-def test_string_as_exp_unsafe_joined_as_one():
+def test_string_as_expr_unsafe_joined_as_one():
text = "".join(NON_ASCII_CHARS)
expected = "".join(f"\\{char}" for char in text)
- actual = regex_toolkit.string_as_exp(text, RegexFlavor.RE)
+ actual = regex_toolkit.string_as_expr(text, RegexFlavor.RE)
assert actual == expected
-
- exp_to_test = actual
- assert_exp_match(exp_to_test, text, RegexFlavor.RE)
+ assert_expr_match(rf"^{actual}$", text, RegexFlavor.RE)
# RE2 - String as expression
@@ -447,25 +393,21 @@ def test_string_as_exp_unsafe_joined_as_one():
for char in NON_ASCII_CHARS
],
)
-def test_string_as_exp2_unknown_individual_char(text, expected):
- actual = regex_toolkit.string_as_exp(text, RegexFlavor.RE2)
+def test_string_as_expr2_unknown_individual_char(text, expected):
+ actual = regex_toolkit.string_as_expr(text, RegexFlavor.RE2)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match(exp_to_test, text, RegexFlavor.RE2)
+ assert_expr_match(rf"^{actual}$", text, RegexFlavor.RE2)
-def test_string_as_exp2_unknown_joined_as_one():
+def test_string_as_expr2_unknown_joined_as_one():
text = "".join(NON_ASCII_CHARS)
expected = "".join(
"\\x{" + format(ord(char), "x").zfill(8).removeprefix("0000").upper() + "}"
for char in text
)
- actual = regex_toolkit.string_as_exp(text, RegexFlavor.RE2)
+ actual = regex_toolkit.string_as_expr(text, RegexFlavor.RE2)
assert actual == expected
-
- exp_to_test = actual
- assert_exp_match(exp_to_test, text, RegexFlavor.RE2)
+ assert_expr_match(rf"^{actual}$", text, RegexFlavor.RE2)
# RE and RE2 - Strings as expression
@@ -487,12 +429,10 @@ def test_string_as_exp2_unknown_joined_as_one():
],
)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_strings_as_exp_and_exp2_safe_of_various_lengths(texts, expected, flavor):
- actual = regex_toolkit.strings_as_exp(texts, flavor)
+def test_strings_as_expr_and_expr2_safe_of_various_lengths(texts, expected, flavor):
+ actual = regex_toolkit.strings_as_expr(texts, flavor)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match_all(exp_to_test, texts, flavor)
+ assert_expr_match_all(rf"^{actual}$", texts, flavor)
@pytest.mark.parametrize(
@@ -512,12 +452,12 @@ def test_strings_as_exp_and_exp2_safe_of_various_lengths(texts, expected, flavor
],
)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_strings_as_exp_and_exp2_escapable_of_various_lengths(texts, expected, flavor):
- actual = regex_toolkit.strings_as_exp(texts, flavor)
+def test_strings_as_expr_and_expr2_always_safe_of_various_lengths(
+ texts, expected, flavor
+):
+ actual = regex_toolkit.strings_as_expr(texts, flavor)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match_all(exp_to_test, texts, flavor)
+ assert_expr_match_all(rf"^{actual}$", texts, flavor)
@pytest.mark.parametrize(
@@ -537,12 +477,10 @@ def test_strings_as_exp_and_exp2_escapable_of_various_lengths(texts, expected, f
],
)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_strings_as_exp_and_exp2_reserved_of_various_lengths(texts, expected, flavor):
- actual = regex_toolkit.strings_as_exp(texts, flavor)
+def test_strings_as_expr_and_expr2_reserved_of_various_lengths(texts, expected, flavor):
+ actual = regex_toolkit.strings_as_expr(texts, flavor)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match_all(exp_to_test, texts, flavor)
+ assert_expr_match_all(rf"^{actual}$", texts, flavor)
@pytest.mark.parametrize(
@@ -562,53 +500,57 @@ def test_strings_as_exp_and_exp2_reserved_of_various_lengths(texts, expected, fl
],
)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_strings_as_exp_and_exp2_safe_and_escapable_of_various_lengths(
+def test_strings_as_expr_and_expr2_safe_and_always_safe_of_various_lengths(
texts, expected, flavor
):
- actual = regex_toolkit.strings_as_exp(texts, flavor)
+ actual = regex_toolkit.strings_as_expr(texts, flavor)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match_all(exp_to_test, texts, flavor)
+ assert_expr_match_all(rf"^{actual}$", texts, flavor)
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_strings_as_exp_and_exp2_with_duplicates(flavor):
+def test_strings_as_expr_and_expr2_with_duplicates(flavor):
texts = ["a", "A", "abc", "ABC", "ABC", "abc", "A", "a"]
-
expected = r"ABC|abc|A|a"
- actual = regex_toolkit.strings_as_exp(texts, flavor)
+ actual = regex_toolkit.strings_as_expr(texts, flavor)
assert actual == expected
+ assert_expr_match_all(rf"^{actual}$", texts, flavor)
@pytest.mark.parametrize("seq", ["abc", tuple("abc"), list("abc")])
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_strings_as_exp_and_exp2_various_sequence_types(seq, flavor):
- assert regex_toolkit.strings_as_exp(seq, flavor) == "a|b|c"
+def test_strings_as_expr_and_expr2_various_sequence_types(seq, flavor):
+ assert regex_toolkit.strings_as_expr(seq, flavor) == "a|b|c"
-@pytest.mark.parametrize("seq", ["", tuple(), list()])
+@pytest.mark.parametrize("texts", ["", tuple(), list()])
@pytest.mark.parametrize("flavor", ALL_REGEX_FLAVORS)
-def test_strings_as_exp_and_exp2_empty_of_various_sequence_types(seq, flavor):
- assert regex_toolkit.strings_as_exp(seq, flavor) == ""
+def test_strings_as_expr_and_expr2_empty_of_various_sequence_types(texts, flavor):
+ expected = ""
+ actual = regex_toolkit.strings_as_expr(texts, flavor)
+ assert actual == expected
-def test_strings_as_exp_calls_expected_inner_func():
+def test_strings_as_expr_calls_expected_internal_func():
texts = ["foo", "bar"]
flavor = RegexFlavor.RE
- with mock.patch("regex_toolkit.base._strings_as_exp") as mock__strings_as_exp:
- with mock.patch("regex_toolkit.base._strings_as_exp2") as mock__strings_as_exp2:
- regex_toolkit.base.strings_as_exp(texts, flavor)
- mock__strings_as_exp.assert_called_once_with(set(texts))
- mock__strings_as_exp2.assert_not_called()
+ with mock.patch("regex_toolkit.base._strings_as_expr") as mock__strings_as_expr:
+ with mock.patch(
+ "regex_toolkit.base._strings_as_expr2"
+ ) as mock__strings_as_expr2:
+ regex_toolkit.base.strings_as_expr(texts, flavor)
+ mock__strings_as_expr.assert_called_once_with(set(texts))
+ mock__strings_as_expr2.assert_not_called()
flavor = RegexFlavor.RE2
- with mock.patch("regex_toolkit.base._strings_as_exp") as mock__strings_as_exp:
- with mock.patch("regex_toolkit.base._strings_as_exp2") as mock__strings_as_exp2:
- regex_toolkit.base.strings_as_exp(texts, flavor)
- mock__strings_as_exp.assert_not_called()
- mock__strings_as_exp2.assert_called_once_with(set(texts))
+ with mock.patch("regex_toolkit.base._strings_as_expr") as mock__strings_as_expr:
+ with mock.patch(
+ "regex_toolkit.base._strings_as_expr2"
+ ) as mock__strings_as_expr2:
+ regex_toolkit.base.strings_as_expr(texts, flavor)
+ mock__strings_as_expr.assert_not_called()
+ mock__strings_as_expr2.assert_called_once_with(set(texts))
# RE - Strings as expression
@@ -630,12 +572,10 @@ def test_strings_as_exp_calls_expected_inner_func():
for texts in product(NON_ASCII_CHARS, repeat=2)
],
)
-def test_strings_as_exp_unsafe_of_various_lengths(texts, expected):
- actual = regex_toolkit.strings_as_exp(texts, RegexFlavor.RE)
+def test_strings_as_expr_unsafe_of_various_lengths(texts, expected):
+ actual = regex_toolkit.strings_as_expr(texts, RegexFlavor.RE)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match_all(exp_to_test, texts, RegexFlavor.RE)
+ assert_expr_match_all(rf"^{actual}$", texts, RegexFlavor.RE)
# RE2 - Strings as expression
@@ -659,12 +599,10 @@ def test_strings_as_exp_unsafe_of_various_lengths(texts, expected):
for texts in product(NON_ASCII_CHARS, repeat=2)
],
)
-def test_strings_as_exp2_unsafe_of_various_lengths(texts, expected):
- actual = regex_toolkit.strings_as_exp(texts, RegexFlavor.RE2)
+def test_strings_as_expr2_unsafe_of_various_lengths(texts, expected):
+ actual = regex_toolkit.strings_as_expr(texts, RegexFlavor.RE2)
assert actual == expected
-
- exp_to_test = r"^" + actual + r"$"
- assert_exp_match_all(exp_to_test, texts, RegexFlavor.RE2)
+ assert_expr_match_all(rf"^{actual}$", texts, RegexFlavor.RE2)
# RE - Make expression
@@ -693,5 +631,7 @@ def test_strings_as_exp2_unsafe_of_various_lengths(texts, expected):
(["d", "a", "b", "c", "a"], "a-d"),
),
)
-def test_make_exp(chars, expected):
- assert regex_toolkit.make_exp(chars, RegexFlavor.RE) == expected
+def test_make_expr(chars, expected):
+ actual = regex_toolkit.make_expr(chars, RegexFlavor.RE)
+ assert actual == expected
+ assert_expr_match_all(rf"^[{actual}]$", chars, RegexFlavor.RE)