python_arango_ogm.utils.str_util
1from copy import copy 2import re 3import textwrap 4 5from enum import StrEnum, auto 6from typing import Iterable 7 8CR = '\n' 9LF = '\n' 10EMPTY = '' 11INDENT = ' ' 12QUOTE = '"' 13SPACE = ' ' 14SCORE = '_' 15 16RE_COMBINE_WHITESPACE = re.compile(r"\s+") 17RE_ENCLOSE_WS_BEFORE = re.compile(r"(\s+)([\{\[\(])") 18RE_ENCLOSE_NO_WS_BEFORE = re.compile(r"(\S)([\}\]\)])") 19RE_ENCLOSE_NO_WS_AFTER = re.compile(r"([\{\[\(\}\]\)])(\S)") 20RE_ENCLOSEEMPTY = re.compile(r"([\{\[\(])(\s+)([\}\]\)])") 21RE_TOSNAKECASE = re.compile(r"(?:(?<=[a-z])(?=[A-Z]))|[^a-zA-Z]") 22RE_CAPITALIZED = re.compile(r"(\s+)([A-Z])") 23RE_CAPITAL = re.compile(r"([A-Z]+)") 24RE_NOT_ALPHNUM_SCORE = re.compile(r"[^\w+]") 25 26RE_NOT_ALPHNUM = re.compile(r"[^\w]+") 27RE_NOT_ALPHNUM_SPACE = re.compile(r"[^a-zA-Z0-9\s]+") 28RE_NOT_ALPHNUM_STRICT = re.compile(r"[^a-zA-Z0-9]+") 29 30 31class QuoteEnum(StrEnum): 32 """ Quote Enum """ 33 SINGLE = auto() 34 DOUBLE = auto() 35 TRIPLE = auto() 36 37 38QUOTE_TYPES = { 39 QuoteEnum.SINGLE: "'", 40 QuoteEnum.DOUBLE: '"', 41 QuoteEnum.TRIPLE: '"""', 42} 43 44 45class SurroundEnum(StrEnum): 46 QUOTE_SINGLE = auto() 47 QUOTE_DOUBLE = auto() 48 QUOTE_TRIPLE = auto() 49 BRACE = auto() 50 BRACKET = auto() 51 PARENS = auto() 52 53 54SURROUND_TYPES = { 55 SurroundEnum.QUOTE_SINGLE: ("'", "'"), 56 SurroundEnum.QUOTE_DOUBLE: ('"', '"'), 57 SurroundEnum.QUOTE_TRIPLE: ('"""', '"""'), 58 SurroundEnum.BRACE: ('{', '}'), 59 SurroundEnum.BRACKET: ('[', ']'), 60 SurroundEnum.PARENS: ('(', ')'), 61} 62 63 64def indent(text, amount=4, pre=''): 65 txt = f"{pre} {text}" if pre else str(text) 66 return textwrap.indent(txt, INDENT * amount) 67 68 69def prefix(text, pre): 70 return f"{pre}{text}" if text else copy(EMPTY) 71 72 73def pluralize(val): 74 s = str(val).strip() 75 76 if s: 77 last_char = s[-1] 78 if last_char == 'y': 79 p = s[:-1] + 'ies' 80 elif last_char == 's': 81 p = s + 'es' 82 else: 83 p = s + 's' 84 else: 85 p = copy(EMPTY) 86 87 return p 88 89 90def collapse(ary, join_char=LF): 91 return join_char.join(ary) 92 93 94def surround(text: str, surround_with: SurroundEnum = SurroundEnum.PARENS): 95 if not text: 96 return copy(EMPTY) 97 98 stype = SURROUND_TYPES[surround_with] 99 return "{o}{text}{c}".format(o=stype[0], c=stype[1], text=text) 100 101 102def surround_all(iterable: Iterable, surround_with: SurroundEnum = SurroundEnum.PARENS) -> Iterable: 103 return [surround(t, surround_with=surround_with) for t in iterable] 104 105 106def squish_text(text, format_braces=True): 107 squished = RE_COMBINE_WHITESPACE.sub(SPACE, text).strip() 108 if format_braces: 109 squished = RE_ENCLOSE_WS_BEFORE.sub(r'\g<2>', squished) 110 squished = RE_ENCLOSE_NO_WS_BEFORE.sub(r'\g<1> \g<2>', squished) 111 squished = RE_ENCLOSE_NO_WS_AFTER.sub(r'\g<1> \g<2>', squished) 112 squished = RE_ENCLOSEEMPTY.sub(r'\g<1>\g<3>', squished) 113 squished = RE_COMBINE_WHITESPACE.sub(SPACE, squished).strip() 114 115 return squished 116 117 118def score_text(text): 119 return RE_COMBINE_WHITESPACE.sub('_', text.strip()).lower() 120 121 122def combine_space(text): 123 return RE_COMBINE_WHITESPACE.sub(SPACE, text.strip()) 124 125 126def snake_text(text, lower: bool = True): 127 def score_cap(txt: str, position:int): 128 return txt if not (txt.isupper() and position) else f"_{txt}" 129 # Separate capitalized words: 130 terms = RE_CAPITAL.split(text) 131 terms.remove('') 132 133 snaked = [score_cap(t, i) for i, t in enumerate(terms) if t] 134 txt = "".join(snaked) 135 return txt.lower() if lower else txt 136 137 138def capitalize_text(text): 139 txt = str(text).strip() 140 return txt if txt.isupper() else txt.capitalize() 141 142 143def title_text(text): 144 txt = RE_CAPITAL.sub(r" \1", text) 145 terms = RE_NOT_ALPHNUM_STRICT.split(txt) 146 clean_terms = filter(None, terms) 147 148 words = [capitalize_text(t) for t in clean_terms] 149 return SPACE.join(words)
CR =
'\n'
LF =
'\n'
EMPTY =
''
INDENT =
' '
QUOTE =
'"'
SPACE =
' '
SCORE =
'_'
RE_COMBINE_WHITESPACE =
re.compile('\\s+')
RE_ENCLOSE_WS_BEFORE =
re.compile('(\\s+)([\\{\\[\\(])')
RE_ENCLOSE_NO_WS_BEFORE =
re.compile('(\\S)([\\}\\]\\)])')
RE_ENCLOSE_NO_WS_AFTER =
re.compile('([\\{\\[\\(\\}\\]\\)])(\\S)')
RE_ENCLOSEEMPTY =
re.compile('([\\{\\[\\(])(\\s+)([\\}\\]\\)])')
RE_TOSNAKECASE =
re.compile('(?:(?<=[a-z])(?=[A-Z]))|[^a-zA-Z]')
RE_CAPITALIZED =
re.compile('(\\s+)([A-Z])')
RE_CAPITAL =
re.compile('([A-Z]+)')
RE_NOT_ALPHNUM_SCORE =
re.compile('[^\\w+]')
RE_NOT_ALPHNUM =
re.compile('[^\\w]+')
RE_NOT_ALPHNUM_SPACE =
re.compile('[^a-zA-Z0-9\\s]+')
RE_NOT_ALPHNUM_STRICT =
re.compile('[^a-zA-Z0-9]+')
class
QuoteEnum(enum.StrEnum):
32class QuoteEnum(StrEnum): 33 """ Quote Enum """ 34 SINGLE = auto() 35 DOUBLE = auto() 36 TRIPLE = auto()
Quote Enum
SINGLE =
<QuoteEnum.SINGLE: 'single'>
DOUBLE =
<QuoteEnum.DOUBLE: 'double'>
TRIPLE =
<QuoteEnum.TRIPLE: 'triple'>
Inherited Members
- enum.Enum
- name
- value
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
QUOTE_TYPES =
{<QuoteEnum.SINGLE: 'single'>: "'", <QuoteEnum.DOUBLE: 'double'>: '"', <QuoteEnum.TRIPLE: 'triple'>: '"""'}
class
SurroundEnum(enum.StrEnum):
46class SurroundEnum(StrEnum): 47 QUOTE_SINGLE = auto() 48 QUOTE_DOUBLE = auto() 49 QUOTE_TRIPLE = auto() 50 BRACE = auto() 51 BRACKET = auto() 52 PARENS = auto()
Enum where members are also (and must be) strings
QUOTE_SINGLE =
<SurroundEnum.QUOTE_SINGLE: 'quote_single'>
QUOTE_DOUBLE =
<SurroundEnum.QUOTE_DOUBLE: 'quote_double'>
QUOTE_TRIPLE =
<SurroundEnum.QUOTE_TRIPLE: 'quote_triple'>
BRACE =
<SurroundEnum.BRACE: 'brace'>
BRACKET =
<SurroundEnum.BRACKET: 'bracket'>
PARENS =
<SurroundEnum.PARENS: 'parens'>
Inherited Members
- enum.Enum
- name
- value
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
SURROUND_TYPES =
{<SurroundEnum.QUOTE_SINGLE: 'quote_single'>: ("'", "'"), <SurroundEnum.QUOTE_DOUBLE: 'quote_double'>: ('"', '"'), <SurroundEnum.QUOTE_TRIPLE: 'quote_triple'>: ('"""', '"""'), <SurroundEnum.BRACE: 'brace'>: ('{', '}'), <SurroundEnum.BRACKET: 'bracket'>: ('[', ']'), <SurroundEnum.PARENS: 'parens'>: ('(', ')')}
def
indent(text, amount=4, pre=''):
def
prefix(text, pre):
def
pluralize(val):
def
collapse(ary, join_char='\n'):
def
surround_all( iterable: Iterable, surround_with: SurroundEnum = <SurroundEnum.PARENS: 'parens'>) -> Iterable:
def
squish_text(text, format_braces=True):
107def squish_text(text, format_braces=True): 108 squished = RE_COMBINE_WHITESPACE.sub(SPACE, text).strip() 109 if format_braces: 110 squished = RE_ENCLOSE_WS_BEFORE.sub(r'\g<2>', squished) 111 squished = RE_ENCLOSE_NO_WS_BEFORE.sub(r'\g<1> \g<2>', squished) 112 squished = RE_ENCLOSE_NO_WS_AFTER.sub(r'\g<1> \g<2>', squished) 113 squished = RE_ENCLOSEEMPTY.sub(r'\g<1>\g<3>', squished) 114 squished = RE_COMBINE_WHITESPACE.sub(SPACE, squished).strip() 115 116 return squished
def
score_text(text):
def
combine_space(text):
def
snake_text(text, lower: bool = True):
127def snake_text(text, lower: bool = True): 128 def score_cap(txt: str, position:int): 129 return txt if not (txt.isupper() and position) else f"_{txt}" 130 # Separate capitalized words: 131 terms = RE_CAPITAL.split(text) 132 terms.remove('') 133 134 snaked = [score_cap(t, i) for i, t in enumerate(terms) if t] 135 txt = "".join(snaked) 136 return txt.lower() if lower else txt
def
capitalize_text(text):
def
title_text(text):