projects
/
python_utils.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fix a newly introduced bug in run_tests.sh.
[python_utils.git]
/
string_utils.py
diff --git
a/string_utils.py
b/string_utils.py
index b93dc93aaa78e9b1b901499169c3b902f3445a59..244c450b5ac4b1ec89d8388de6d32eb592b40225 100644
(file)
--- a/
string_utils.py
+++ b/
string_utils.py
@@
-11,7
+11,16
@@
import numbers
import random
import re
import string
import random
import re
import string
-from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Sequence,
+ Tuple,
+)
import unicodedata
from uuid import uuid4
import warnings
import unicodedata
from uuid import uuid4
import warnings
@@
-32,7
+41,7
@@
URLS_RAW_STRING = (
r"([a-z-]+://)" # scheme
r"([a-z_\d-]+:[a-z_\d-]+@)?" # user:password
r"(www\.)?" # www.
r"([a-z-]+://)" # scheme
r"([a-z_\d-]+:[a-z_\d-]+@)?" # user:password
r"(www\.)?" # www.
- r"((?<!\.)[a-z\d]+[a-z\d.-]+\.[a-z]{2,6}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|localhost)" # domain
+ r"((?<!\.)[a-z\d]+[a-z\d.-]+\.[a-z]{2,6}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|localhost)"
# domain
r"(:\d{2,})?" # port number
r"(/[a-z\d_%+-]*)*" # folders
r"(\.[a-z\d_%+-]+)*" # file extension
r"(:\d{2,})?" # port number
r"(/[a-z\d_%+-]*)*" # folders
r"(\.[a-z\d_%+-]+)*" # file extension
@@
-254,10
+263,10
@@
def is_integer_number(in_str: str) -> bool:
False
"""
return (
False
"""
return (
- (is_number(in_str) and "." not in in_str)
or
- is_hexidecimal_integer_number(in_str) or
- is_octal_integer_number(in_str) or
- is_binary_integer_number(in_str)
+ (is_number(in_str) and "." not in in_str)
+ or is_hexidecimal_integer_number(in_str)
+ or is_octal_integer_number(in_str)
+
or
is_binary_integer_number(in_str)
)
)
@@
-382,10
+391,7
@@
def strip_escape_sequences(in_str: str) -> str:
def add_thousands_separator(
def add_thousands_separator(
- in_str: str,
- *,
- separator_char = ',',
- places = 3
+ in_str: str, *, separator_char=',', places=3
) -> str:
"""
Add thousands separator to a numeric string. Also handles numbers.
) -> str:
"""
Add thousands separator to a numeric string. Also handles numbers.
@@
-406,20
+412,21
@@
def add_thousands_separator(
in_str = f'{in_str}'
if is_number(in_str):
return _add_thousands_separator(
in_str = f'{in_str}'
if is_number(in_str):
return _add_thousands_separator(
- in_str,
- separator_char = separator_char,
- places = places
+ in_str, separator_char=separator_char, places=places
)
raise ValueError(in_str)
)
raise ValueError(in_str)
-def _add_thousands_separator(in_str: str, *, separator_char = ',', places = 3) -> str:
+def _add_thousands_separator(
+ in_str: str, *, separator_char=',', places=3
+) -> str:
decimal_part = ""
if '.' in in_str:
(in_str, decimal_part) = in_str.split('.')
tmp = [iter(in_str[::-1])] * places
ret = separator_char.join(
decimal_part = ""
if '.' in in_str:
(in_str, decimal_part) = in_str.split('.')
tmp = [iter(in_str[::-1])] * places
ret = separator_char.join(
- "".join(x) for x in zip_longest(*tmp, fillvalue=""))[::-1]
+ "".join(x) for x in zip_longest(*tmp, fillvalue="")
+ )[::-1]
if len(decimal_part) > 0:
ret += '.'
ret += decimal_part
if len(decimal_part) > 0:
ret += '.'
ret += decimal_part
@@
-507,6
+514,7
@@
def suffix_string_to_number(in_str: str) -> Optional[int]:
>>> suffix_string_to_number('13.1Gb')
14066017894
"""
>>> suffix_string_to_number('13.1Gb')
14066017894
"""
+
def suffix_capitalize(s: str) -> str:
if len(s) == 1:
return s.upper()
def suffix_capitalize(s: str) -> str:
if len(s) == 1:
return s.upper()
@@
-1093,6
+1101,7
@@
def to_date(in_str: str) -> Optional[datetime.date]:
Parses a date string. See DateParser docs for details.
"""
import dateparse.dateparse_utils as dp
Parses a date string. See DateParser docs for details.
"""
import dateparse.dateparse_utils as dp
+
try:
d = dp.DateParser()
d.parse(in_str)
try:
d = dp.DateParser()
d.parse(in_str)
@@
-1100,7
+1109,6
@@
def to_date(in_str: str) -> Optional[datetime.date]:
except dp.ParseException:
msg = f'Unable to parse date {in_str}.'
logger.warning(msg)
except dp.ParseException:
msg = f'Unable to parse date {in_str}.'
logger.warning(msg)
- warnings.warn(msg)
return None
return None
@@
-1109,6
+1117,7
@@
def valid_date(in_str: str) -> bool:
True if the string represents a valid date.
"""
import dateparse.dateparse_utils as dp
True if the string represents a valid date.
"""
import dateparse.dateparse_utils as dp
+
try:
d = dp.DateParser()
_ = d.parse(in_str)
try:
d = dp.DateParser()
_ = d.parse(in_str)
@@
-1116,7
+1125,6
@@
def valid_date(in_str: str) -> bool:
except dp.ParseException:
msg = f'Unable to parse date {in_str}.'
logger.warning(msg)
except dp.ParseException:
msg = f'Unable to parse date {in_str}.'
logger.warning(msg)
- warnings.warn(msg)
return False
return False
@@
-1125,6
+1133,7
@@
def to_datetime(in_str: str) -> Optional[datetime.datetime]:
Parses a datetime string. See DateParser docs for more info.
"""
import dateparse.dateparse_utils as dp
Parses a datetime string. See DateParser docs for more info.
"""
import dateparse.dateparse_utils as dp
+
try:
d = dp.DateParser()
dt = d.parse(in_str)
try:
d = dp.DateParser()
dt = d.parse(in_str)
@@
-1133,7
+1142,6
@@
def to_datetime(in_str: str) -> Optional[datetime.datetime]:
except ValueError:
msg = f'Unable to parse datetime {in_str}.'
logger.warning(msg)
except ValueError:
msg = f'Unable to parse datetime {in_str}.'
logger.warning(msg)
- warnings.warn(msg)
return None
return None
@@
-1146,7
+1154,6
@@
def valid_datetime(in_str: str) -> bool:
return True
msg = f'Unable to parse datetime {in_str}.'
logger.warning(msg)
return True
msg = f'Unable to parse datetime {in_str}.'
logger.warning(msg)
- warnings.warn(msg)
return False
return False
@@
-1164,7
+1171,7
@@
def squeeze(in_str: str, character_to_squeeze: str = ' ') -> str:
return re.sub(
r'(' + re.escape(character_to_squeeze) + r')+',
character_to_squeeze,
return re.sub(
r'(' + re.escape(character_to_squeeze) + r')+',
character_to_squeeze,
- in_str
+ in_str
,
)
)
@@
-1236,6
+1243,7
@@
class SprintfStdout(object):
'test\n'
"""
'test\n'
"""
+
def __init__(self) -> None:
self.destination = io.StringIO()
self.recorder = None
def __init__(self) -> None:
self.destination = io.StringIO()
self.recorder = None
@@
-1335,9
+1343,7
@@
def trigrams(txt: str):
def shuffle_columns_into_list(
def shuffle_columns_into_list(
- input_lines: Iterable[str],
- column_specs: Iterable[Iterable[int]],
- delim=''
+ input_lines: Iterable[str], column_specs: Iterable[Iterable[int]], delim=''
) -> Iterable[str]:
"""Helper to shuffle / parse columnar data and return the results as a
list. The column_specs argument is an iterable collection of
) -> Iterable[str]:
"""Helper to shuffle / parse columnar data and return the results as a
list. The column_specs argument is an iterable collection of
@@
-1367,9
+1373,9
@@
def shuffle_columns_into_list(
def shuffle_columns_into_dict(
def shuffle_columns_into_dict(
-
input_lines: Iterable[str],
-
column_specs: Iterable[Tuple[str, Iterable[int]]],
- delim=''
+ input_lines: Iterable[str],
+ column_specs: Iterable[Tuple[str, Iterable[int]]],
+ delim='',
) -> Dict[str, str]:
"""Helper to shuffle / parse columnar data and return the results
as a dict.
) -> Dict[str, str]:
"""Helper to shuffle / parse columnar data and return the results
as a dict.
@@
-1477,12
+1483,14
@@
def chunk(txt: str, chunk_size):
if len(txt) % chunk_size != 0:
msg = f'String to chunk\'s length ({len(txt)} is not an even multiple of chunk_size ({chunk_size})'
logger.warning(msg)
if len(txt) % chunk_size != 0:
msg = f'String to chunk\'s length ({len(txt)} is not an even multiple of chunk_size ({chunk_size})'
logger.warning(msg)
- warnings.warn(msg)
+ warnings.warn(msg
, stacklevel=2
)
for x in range(0, len(txt), chunk_size):
for x in range(0, len(txt), chunk_size):
- yield txt[x
:x+
chunk_size]
+ yield txt[x
: x +
chunk_size]
-def to_bitstring(txt: str, *, delimiter='', encoding='utf-8', errors='surrogatepass') -> str:
+def to_bitstring(
+ txt: str, *, delimiter='', encoding='utf-8', errors='surrogatepass'
+) -> str:
"""Encode txt and then chop it into bytes. Note: only bitstrings
with delimiter='' are interpretable by from_bitstring.
"""Encode txt and then chop it into bytes. Note: only bitstrings
with delimiter='' are interpretable by from_bitstring.
@@
-1497,12
+1505,7
@@
def to_bitstring(txt: str, *, delimiter='', encoding='utf-8', errors='surrogatep
"""
etxt = to_ascii(txt)
"""
etxt = to_ascii(txt)
- bits = bin(
- int.from_bytes(
- etxt,
- 'big'
- )
- )
+ bits = bin(int.from_bytes(etxt, 'big'))
bits = bits[2:]
return delimiter.join(chunk(bits.zfill(8 * ((len(bits) + 7) // 8)), 8))
bits = bits[2:]
return delimiter.join(chunk(bits.zfill(8 * ((len(bits) + 7) // 8)), 8))
@@
-1528,7
+1531,10
@@
def from_bitstring(bits: str, encoding='utf-8', errors='surrogatepass') -> str:
"""
n = int(bits, 2)
"""
n = int(bits, 2)
- return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'
+ return (
+ n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors)
+ or '\0'
+ )
def ip_v4_sort_key(txt: str) -> Tuple[int]:
def ip_v4_sort_key(txt: str) -> Tuple[int]:
@@
-1578,4
+1584,5
@@
def replace_all(in_str: str, replace_set: str, replacement: str) -> str:
if __name__ == '__main__':
import doctest
if __name__ == '__main__':
import doctest
+
doctest.testmod()
doctest.testmod()