Skip to content

Commit ef505fe

Browse files
committed
Add new "divide" and "redivide" functions to split strings in two.
1 parent fb1f4dc commit ef505fe

12 files changed

+98
-1
lines changed

domdf_python_tools/utils.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,12 @@
6464
import contextlib
6565
import inspect
6666
import json
67+
import re
6768
import sys
6869
from io import StringIO
6970
from math import log10
7071
from pprint import pformat
71-
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union
72+
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional, Pattern, Tuple, Union
7273

7374
# this package
7475
import domdf_python_tools.words
@@ -101,6 +102,8 @@
101102
"trim_precision",
102103
"double_repr_string",
103104
"redirect_output",
105+
"divide",
106+
"redivide",
104107
]
105108

106109
#: The current major python version.
@@ -427,3 +430,40 @@ def redirect_output(combine: bool = False) -> Iterator[Tuple[StringIO, StringIO]
427430

428431
with contextlib.redirect_stdout(stdout), contextlib.redirect_stderr(stderr):
429432
yield stdout, stderr
433+
434+
435+
def divide(string: str, sep: str) -> Tuple[str, str]:
436+
"""
437+
Divide a string into two parts, about the given string.
438+
439+
.. versionadded:: 2.7.0
440+
441+
:param string:
442+
:param sep:
443+
"""
444+
445+
if sep not in string:
446+
raise ValueError(f"{sep!r} not in {string!r}")
447+
448+
parts = string.split(sep, 1)
449+
return tuple(parts) # type: ignore
450+
451+
452+
def redivide(string: str, pat: Union[str, Pattern]) -> Tuple[str, str]:
453+
"""
454+
Divide a string into two parts, splitting on the given regular expression.
455+
456+
.. versionadded:: 2.7.0
457+
458+
:param string:
459+
:param pat:
460+
"""
461+
462+
if isinstance(pat, str):
463+
pat = re.compile(pat)
464+
465+
if not pat.search(string):
466+
raise ValueError(f"{pat!r} has no matches in {string!r}")
467+
468+
parts = pat.split(string, 1)
469+
return tuple(parts) # type: ignore

tests/test_utils.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
# 3rd party
1818
import click
1919
import pytest
20+
from pytest_regressions.data_regression import DataRegressionFixture
2021

2122
# this package
2223
from domdf_python_tools.testing import testing_boolean_values
2324
from domdf_python_tools.typing import HasHead
2425
from domdf_python_tools.utils import (
2526
cmp,
2627
convert_indents,
28+
divide,
2729
double_repr_string,
2830
enquote_value,
2931
head,
@@ -33,6 +35,7 @@
3335
printt,
3436
pyversion,
3537
redirect_output,
38+
redivide,
3639
stderr_writer,
3740
str2tuple,
3841
strtobool,
@@ -449,3 +452,47 @@ def test_redirect_output_combine():
449452
expected = "I'm going to stdout\nI'm going to stderr\nI'm also going to stdout\nI'm also going to stderr\n"
450453
assert stdout.getvalue() == expected
451454
assert stderr.getvalue() == expected
455+
456+
457+
@pytest.mark.parametrize(
458+
"string, sep",
459+
[
460+
("hello=world", '='),
461+
("hello = world", '='),
462+
("hello = world", " = "),
463+
("hello: world", ':'),
464+
("hello: world", ": "),
465+
]
466+
)
467+
def test_divide(string: str, sep: str, data_regression: DataRegressionFixture):
468+
data = dict(divide(e, sep) for e in [string, string, string])
469+
470+
data_regression.check(data)
471+
472+
473+
def test_divide_errors():
474+
with pytest.raises(ValueError, match="'=' not in 'hello: world'"):
475+
divide("hello: world", '=')
476+
477+
478+
@pytest.mark.parametrize(
479+
"string, sep",
480+
[
481+
("hello=world", r"\s?=\s?"),
482+
("hello = world", r"\s?=\s?"),
483+
("hello = world", '='),
484+
("hello: world", r":\s?"),
485+
("hello: world", r"\s?:\s?"),
486+
]
487+
)
488+
def test_redivide(string: str, sep: str, data_regression: DataRegressionFixture):
489+
data = dict(redivide(e, sep) for e in [string, string, string])
490+
491+
data_regression.check(data)
492+
493+
494+
def test_redivide_errors():
495+
with pytest.raises(ValueError, match=r"re.compile\('='\) has no matches in 'hello: world'"):
496+
redivide("hello: world", '=')
497+
with pytest.raises(ValueError, match=r"re.compile\(.*\) has no matches in 'hello: world'"):
498+
redivide("hello: world", r"\d")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
'hello ': ' world'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello: world
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello: ' world'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello: world
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello: world
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
'hello ': ' world'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello: world
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello: world

0 commit comments

Comments
 (0)