UMT Python Package
UMT Python Package is a Python port of the TypeScript umt utility library. package/main is the source of truth; this package mirrors those modules (array, date, math, string, validate, …) with snake_case names.
Install
pip install umt-python
# or using uv
uv add umt-python
# or using poetry
poetry add umt-python
Quick Start
from umt_python import (
add_business_days,
format_string,
is_between,
random_string,
to_base64,
)
random_string(10) # e.g. "aBcD3fGh1j"
format_string("Hello, {0}! Today is {1}.", "World", "Monday")
to_base64("Hello World") # "SGVsbG8gV29ybGQ="
from datetime import datetime
is_between(datetime(2025, 4, 15), datetime(2025, 4, 10), datetime(2025, 4, 20))
add_business_days(datetime(2025, 4, 18, 9, 30), 1) # 2025-04-21 09:30
Import the published package as umt_python. Unit tests in this repo import from src (for example from src.date import is_between).
Modules
Public names are re-exported from src/__init__.py. Grouped the same way as TypeScript:
| Module | Examples |
|---|---|
advance |
range_advance |
array |
chunk, unique, ultra_number_sort, zip_arrays |
async_util |
sleep, parallel, timeout, debounce_async |
color |
hexa_to_rgba, rgba_to_hsla (see below) |
consts |
ONE_DAY_MS, HttpStatus |
crypto |
encode_base32, decode_base32, decode_base58 (see below) |
data_structure |
LRUCache, TTLCache, PriorityQueue |
date |
is_between, add_business_days, from_unix (see below) |
error |
safe_execute, match_result |
function |
debounce, memoize, throttle |
ip |
ip_to_long, cidr_to_long, is_in_range, is_private_ip (see below) |
iterator |
lazy_map, lazy_filter, lazy_take |
map |
group_by_to_map, zip_to_map |
math |
gcd, n_cr, sum_precise, calculator, math_converter, to_base_n (see below) |
number |
format_number, to_ordinal, to_percentage |
object |
object_get, deep_clone, flatten_object |
predicate |
every, some, is_nullish |
random |
random_choice, seeded_random |
simple |
birthday_simple, now_simple |
string |
format_string, slugify, strip_ansi, strip_tags, words, normalize_whitespace, unescape_html, escape_html, camel_case, kebab_case, sanitize_string, delete_spaces, to_full_width, to_half_width (see below) |
time |
convert_time |
tool |
pipe, unwrap, parse_json, escape_regexp (see below) |
ua |
parse_user_agent, extract_browser_from_user_agent, extract_device_from_user_agent, extract_os_from_user_agent (see below) |
unit |
to_celsius, to_kelvin |
url |
build_url, parse_query_string, is_absolute_url, join_path (see below) |
validate |
is_number, array_of, parse_email (see below) |
Not every TypeScript helper is ported yet. There is no is_same (use is_same_day or compare truncated values with start_of). There is no date format (TypeScript format / Rust umt_format / Go FormatDate). There is also no count_by, partition, sliding, map_series, or safe_execute_async.
Date helpers
Local-time calendar helpers aligned with TypeScript package/main/src/Date. Week boundaries are Sunday-start (JavaScript Date#getDay() 0, not Python weekday() Monday=0). There are no UTC variants.
| Function | Type | Description | Example |
|---|---|---|---|
is_between |
(date, start, end, unit=None, inclusivity="()") -> bool |
Range check. Default inclusivity is exclusive on both ends. Ranges are not swapped. Omit unit for exact timestamps; with a unit, all three dates are truncated with start_of first. |
is_between(datetime(2025, 4, 15), datetime(2025, 4, 10), datetime(2025, 4, 20)) # True / is_between(datetime(2025, 4, 10), datetime(2025, 4, 10), datetime(2025, 4, 20)) # False / is_between(datetime(2025, 4, 10), datetime(2025, 4, 10), datetime(2025, 4, 20), None, "[]") # True |
add_business_days |
(date, amount, holidays=None) -> datetime |
Walk calendar days until amount weekdays (minus optional holidays compared with is_same_day) have been counted. Start date is not counted: Friday + 1 is Monday. 0 returns a clone and does not snap to a business day. |
add_business_days(datetime(2025, 4, 18, 9, 30), 1) # datetime(2025, 4, 21, 9, 30) |
sub_business_days |
(date, amount, holidays=None) -> datetime |
add_business_days(date, -amount, holidays) |
sub_business_days(datetime(2025, 4, 21, 9, 30), 1) # datetime(2025, 4, 18, 9, 30) |
is_business_day |
(date, holidays=None) -> bool |
Weekday and not in holidays |
is_business_day(datetime(2025, 4, 21)) # True |
get_quarter |
(date) -> int |
Local month → 1–4 (Jan–Mar = 1) | get_quarter(datetime(2025, 4, 15)) # 2 |
week_of_year |
(date) -> int |
Sunday-start week index. Week 1 contains January 1 of that year. Not ISO-8601. | week_of_year(datetime(2025, 1, 1)) # 1 / week_of_year(datetime(2025, 1, 5)) # 2 |
from_unix |
(value, unit="s") -> datetime |
Epoch to naive local datetime whose timestamp matches JavaScript Date.getTime() |
from_unix(0).timestamp() # 0.0 |
to_unix |
(date, unit="s") -> float |
Default seconds, floored | to_unix(datetime(1970, 1, 1, tzinfo=timezone.utc)) # 0.0 |
start_of / end_of |
(date, unit) -> datetime |
Boundary truncation. unit is second | minute | hour | day | week | month | quarter | year |
start_of(datetime(2025, 4, 15, 10, 30), "day") # datetime(2025, 4, 15, 0, 0) |
DateInclusivity is "()" | "[]" | "[)" | "(]". UnixTimeUnit is "s" | "ms".
String helpers
Unicode-aware helpers aligned with TypeScript package/main/src/String.
| Function | Type | Description | Example |
|---|---|---|---|
strip_ansi |
(string_: str) -> str |
Removes CSI (colors, cursor, including C1 U+009B) and OSC sequences. Incomplete CSI is left unchanged. Unlike sanitize_string, other non-printables stay. |
strip_ansi("\x1b[31mred\x1b[0m") # "red" |
strip_tags |
(string_: str) -> str |
Deletes HTML/XML tags, repeating until stable so "<sc<script>ript>" becomes "". Self-closing tags leave no separator. |
strip_tags("<p>Hello <b>World</b></p>") # "Hello World" |
words |
(string_: str, pattern: re.Pattern[str] | None = None) -> list[str] |
Default: camelCase / acronym split, then non-letter/number separators. Pass a compiled pattern to return findall matches ([] if none). |
words("XMLHttpRequest") # ["XML", "Http", "Request"] |
normalize_whitespace |
(string_: str) -> str |
Collapses Unicode \s+ to a single space and trims. Unlike delete_spaces, words stay separated. |
normalize_whitespace("hello world") # "hello world" |
delete_spaces |
(string_: str) -> str |
Removes every Unicode \s character (spaces, tabs, newlines, em space, ideographic space). |
delete_spaces("Hello World") # "HelloWorld" / delete_spaces(" tab\t space ") # "tabspace" |
sanitize_string |
(string_: str) -> str |
Keeps printable ASCII (space to tilde) plus TAB / LF / CR. Drops NULL, other C0, DEL, ANSI ESC, and all non-ASCII (CJK, emoji, "é"). Unlike strip_ansi, CSI leftovers remain. |
sanitize_string("\x1b[31mred\x1b[0m") # "[31mred[0m" / sanitize_string("héllo") # "hllo" / sanitize_string("日本語") # "" |
unescape_html |
(string_: str) -> str |
Named entities plus decimal / hex numeric references. A (uppercase X) is left unchanged. Decodes via chr() — it does not apply TypeScript's extra rejection of NULL / C0 / DEL / C1 / surrogates. |
unescape_html("Tom & Jerry") # "Tom & Jerry" / unescape_html("A") # "A" |
escape_html |
(string_: str) -> str |
Encodes & < > " '. Does not encode backtick or /. TypeScript escapeHtml also maps backtick → ` and / → /. Cached re.compile(r"[&<>\"']"). |
escape_html("<script></script>") # "<script></script>" / escape_html("Tom & Jerry") # "Tom & Jerry" |
to_full_width |
(string_: str) -> str |
ASCII digits and letters only (0-9A-Za-z), each code point + 0xFEE0. Punctuation and space stay. str.maketrans / translate, not regex. |
to_full_width("Abc123") # "Abc123" / to_full_width("a-b!") # "a-b!" |
to_half_width |
(string_: str) -> str |
Broader than TypeScript / Rust / Go: U+FF01–U+FF5E (full-width ! through ~, including digits and letters) plus ideographic space U+3000 → " ". Those ports convert only 0-9A-Za-z. str.maketrans / translate, not regex. |
to_half_width("ABC123") # "ABC123" / to_half_width("! ") # "! " |
camel_case |
(string_: str) -> str |
Replaces non-alphanumeric runs, then lowercases only the first character. Does not split acronyms. | camel_case("hello-world") # "helloWorld" / camel_case("HELLO") # "hELLO" |
kebab_case |
(string_: str) -> str |
Inserts dashes on case boundaries and replaces separators. Splits acronyms. | kebab_case("XMLHttpRequest") # "xml-http-request" |
slugify |
(string_: str) -> str |
NFD, strip combining marks, lowercase, hyphenate. Python \w is Unicode, so CJK stays: "Japanese: こんにちは" → "japanese-こんにちは". TypeScript / Go drop those letters ("japanese"). |
slugify("Hello World!") # "hello-world" / slugify("Café") # "cafe" |
IP helpers
IPv4 dotted-decimal only, aligned with TypeScript package/main/src/IP. Unlike TypeScript, these functions validate input and raise ValueError (or TypeError from get_network_address) on malformed values.
| Function | Type | Description | Example |
|---|---|---|---|
ip_to_long / long_to_ip |
(ip: str) -> int / (long: int | float) -> str |
Pack or unpack four octets. Rejects leading zeros ("192.168.01.1"). |
ip_to_long("192.168.1.1") # 3232235777 / long_to_ip(3232235777) # "192.168.1.1" |
cidr_to_long / cidr_to_subnet_mask |
(cidr: int) -> int / (cidr: int) -> str |
Prefix 0–32. Outside that range raises ValueError. |
cidr_to_long(24) # 4294967040 / cidr_to_subnet_mask(24) # "255.255.255.0" |
subnet_mask_to_cidr |
(subnet_mask: str) -> int |
Requires contiguous 1 bits then 0 bits. "255.0.255.0" raises. TypeScript subnetMaskToCidr only counts bits. |
subnet_mask_to_cidr("255.255.255.0") # 24 |
is_in_range |
(remote_ip, network_ip, cidr) -> bool |
(ip & mask) == (network & mask). CIDR 0 matches every IPv4 address. |
is_in_range("192.168.1.2", "192.168.1.0", 24) # True |
is_private_ip |
(ip: str) -> bool |
RFC 1918 only: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16. Loopback and link-local are not private. The three (network, mask) pairs are computed once at module load (TypeScript / Rust / Go do the same). Invalid input raises ValueError. |
is_private_ip("10.0.0.1") # True / is_private_ip("127.0.0.1") # False |
get_ip_class |
(ip: str) -> str |
Classful first-octet lookup (A–E). 0.0.0.0 and malformed input return "". |
get_ip_class("10.0.0.1") # "A" |
get_network_address |
(ip: str, subnet_mask: str) -> int |
Returns an unsigned 32-bit int, not a dotted string. | get_network_address("192.168.1.1", "255.255.255.0") # 3232235776 |
ip_to_binary_string |
(ip: str) -> str |
32-character 0/1 string, eight bits per octet. |
ip_to_binary_string("192.168.0.1") # "11000000101010000000000000000001" |
Color and URL helpers
| Function | Type | Description | Example |
|---|---|---|---|
hexa_to_rgba |
(hex_code: str) -> dict[str, float] |
# plus 3, 6, or 8 hex digits → {r, g, b, a}. a is 0–1 rounded to 2 decimals. Invalid input raises ValueError. TypeScript hexaToRgba does not validate. |
hexa_to_rgba("#FF0000") # {'r': 255, 'g': 0, 'b': 0, 'a': 1.0} / hexa_to_rgba("#fff") # {'r': 255, 'g': 255, 'b': 255, 'a': 1.0} |
is_absolute_url |
(url: str) -> bool |
RFC 3986 scheme check (letter, then letters / digits / + / . / -, then :). Protocol-relative URLs are not absolute. |
is_absolute_url("https://example.com") # True / is_absolute_url("//example.com") # False |
join_path |
(*segments: str) -> str |
Slash-normalizing string join, not os.path.join. Keeps the first segment's leading / and the last segment's trailing /. Empty pieces are dropped. No . / .. resolution. No segments → "". A single "///" stays "///". |
join_path("https://example.com/", "/api/", "/users") # "https://example.com/api/users" / join_path("a", "", "b") # "a/b" |
escape_regexp(string) (in tool) prefixes $ ( ) * + . ? [ \ ] ^ { | } with a backslash. Hyphen and / are not escaped. calculator builds its currency-symbol regex with this helper at call time.
from umt_python import escape_regexp, join_path
escape_regexp("a.b") # "a\\.b"
escape_regexp("foo-bar") # "foo-bar"
escape_regexp("path/to/file.txt") # "path/to/file\\.txt"
join_path("https://example.com/", "/api/", "/users") # "https://example.com/api/users"
Crypto helpers
RFC 4648 Base32 (A-Z + 2-7, = padding), aligned with TypeScript package/main/src/Crypto. Encoding, not encryption.
| Function | Type | Description | Example |
|---|---|---|---|
encode_base32 |
(input_data: str | bytes) -> str |
UTF-8 encode a string first. Empty input → "". Pads to a multiple of 8 with =. |
encode_base32("Hello") # "JBSWY3DP" / encode_base32("f") # "MY======" |
decode_base32 |
(input_data: str) -> bytes |
Skips = anywhere. Raises ValueError on invalid / lowercase characters ("1A", "jbswy3dp"). TypeScript decodeBase32 maps those to value 0 and does not throw. |
decode_base32("JBSWY3DP") # b"Hello" / decode_base32("JB=SWY3DP") # b"Hello" |
decode_base32_to_string |
(input_data: str) -> str |
UTF-8 decode of decode_base32. |
decode_base32_to_string("JBSWY3DP") # "Hello" |
parse_email
parse_email(email, ParseEmailOptions(level=...)) returns ParseEmailResult(valid, parts). level is required: "basic" | "rfc822" | "rfc2822" | "rfc5321" | "rfc5322". There is no TypeScript 320-character pre-check.
from umt_python import ParseEmailOptions, parse_email
parse_email("user@example.com", ParseEmailOptions(level="basic")).valid # True
parse_email("user@localhost", ParseEmailOptions(level="basic")).valid # True
parse_email("user@localhost", ParseEmailOptions(level="rfc5321")).valid # False
rfc822 allows single-label domains and comments. rfc2822 requires a TLD and rejects ... rfc5321 is the SMTP path (max 256 / local 64, domain literals allowed). rfc5322 adds comments and quoted strings.
Math helpers
| Function | Type | Description | Example |
|---|---|---|---|
calculator |
(expression: str, exchange=None) -> str |
Strips whitespace. = solves a single-variable equation ("x=5" → "5"). Otherwise evaluates + - * / ^ and parentheses. Incomplete input is returned as-is. ^ reduces the last pair first ("2^2^2" → "16"). |
calculator("1+2") # "3" / calculator("$10*2", {"$": 100}) # "2000" |
math_converter |
(equation: str) -> str |
Rewrites n*n or n^2 as a sum of simpler products. Uses float in the rewritten terms, so the string is "1500.0*1000+…" rather than TypeScript / Go "1500*1000+…". |
math_converter("1250*1250") # "1500.0*1000+400.0*100+200.0*100+50*50" |
to_base_n |
(value: int, radix: int = 2) -> str |
Default radix is 2 (to_base_n(10) → "1010"). Hex digits are lowercase. Radix 2 / 8 / 10 / 16 use format strings (f"{value:d}" for 10). bool is accepted as int (True → "1"). Rust returns "Invalid radix" and Go panics on a base outside 2–36; this function does not check that range. |
to_base_n(15, 16) # "f" / to_base_n(255, 16) # "ff" / to_base_n(-10, 10) # "-10" |
UA helpers
Coarse User-Agent labels aligned with TypeScript package/main/src/UA. Matching is case-insensitive. parse_user_agent lowercases the input, then calls the three extractors. Not a full UA parser (no versions).
| Function | Type | Description | Example |
|---|---|---|---|
extract_browser_from_user_agent |
(ua: str) -> BrowserType |
Order: Edge → IE → Firefox → Opera (opr/, returned as "other") → Chrome (chrome / crios) → Safari → "other". |
extract_browser_from_user_agent("… Chrome/91 … OPR/77") # "other" |
extract_device_from_user_agent |
(ua: str) -> DeviceType |
Bots first, then iPhone / iPod / webOS / BlackBerry / Opera Mini as "mobile". Android with mobile → "mobile"; Android without mobile → "tablet". iPad is "tablet". |
extract_device_from_user_agent("Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X)") # "tablet" |
extract_os_from_user_agent |
(ua: str) -> OsType |
iPhone / iPad / iPod → "ios" even when the string contains like Mac OS X. Android wins over the Linux token. |
extract_os_from_user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)") # "macos" |
parse_user_agent |
(user_agent: str) -> UserAgentInfo |
TypedDict {browser, device, os}. |
parse_user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/91.0") # {'browser': 'chrome', 'device': 'desktop', 'os': 'macos'} |
Fixed regexes in this package are compiled once at module level (re.compile): UA extractors, hexa_to_rgba, is_absolute_url, join_path, math_converter, parse_email, strip_ansi / strip_tags, unescape_html, escape_html, camel_case, kebab_case, slugify, normalize_whitespace, sanitize_string, delete_spaces, escape_regexp, calculator / calculator_core (except the currency-symbol pattern), literal_expression, apply_formatter, get_value. Caller-built patterns (format_string, regex_match, optional words pattern, template_literal, calculator currency symbol) stay inline. to_full_width / to_half_width use module-level str.maketrans tables, not regex.
Function List
String Manipulation Functions
| Function | Type | Description | Example |
|---|---|---|---|
delete_spaces |
(string_: str) -> str |
Remove all whitespace characters from a string | delete_spaces("Hello World") # "HelloWorld" |
format_string |
(template: str, *values: object) -> str |
Replace placeholders {0}, {1}, etc. in a template string | format_string("Sum of {0} and {1} is {2}", 1, 2, 3) # "Sum of 1 and 2 is 3" |
reverse_string |
(char: str) -> str |
Reverse a string | reverse_string("Hello") # "olleH" |
escape_html |
(string_: str) -> str |
Encode & < > " ' (not backtick or /) |
escape_html("<b>") # "<b>" |
to_full_width |
(string_: str) -> str |
Convert ASCII digits and letters to full-width | to_full_width("Abc123") # "Abc123" |
to_half_width |
(string_: str) -> str |
Convert U+FF01–U+FF5E and ideographic space to half-width |
to_half_width("Hello 123") # "Hello 123" |
Base64 Encoding Functions
| Function | Type | Description | Example |
|---|---|---|---|
to_base64 |
(char: str) -> str |
Encode a string to Base64 | to_base64("Hello") # "SGVsbG8=" |
from_base64 |
(base64_string: str) -> str |
Decode a Base64 string | from_base64("SGVsbG8=") # "Hello" |
String Padding Functions
| Function | Type | Description | Example |
|---|---|---|---|
pad_start |
(string_: str, target_length: int, pad_string: str) -> str |
Pad string from the start to reach target length | pad_start("123", 5, "0") # "00123" |
pad_end |
(string_: str, target_length: int, pad_string: str) -> str |
Pad string from the end to reach target length | pad_end("abc", 5, "0") # "abc00" |
String Trimming Functions
| Function | Type | Description | Example |
|---|---|---|---|
trim_characters |
(string_: str, chars: str) -> str |
Remove specified characters from both ends | trim_characters("-.-hello-.-", "-.") # "hello" |
trim_start_characters |
(string_: str, chars: str) -> str |
Remove specified characters from the start | trim_start_characters("!!!hello", "!") # "hello" |
trim_end_characters |
(string_: str, chars: str) -> str |
Remove specified characters from the end | trim_end_characters("hello!!!", "!") # "hello" |
Random String Generation
| Function | Type | Description | Example |
|---|---|---|---|
random_string |
(size: int = 8, char_pool: str = DEFAULT_RANDOM_STRING_CHARS) -> str |
Generate a random string of specified length | random_string(10) # "aBcD3fGh1j" |
random_string_initialization |
(char_pool: str = DEFAULT_RANDOM_STRING_CHARS) -> Callable[[int], str] |
Create a custom random string generator with specific character pool | custom_random = random_string_initialization("xyz") → custom_random(3) # "xyx" |
String Validation Functions
| Function | Type | Description | Example |
|---|---|---|---|
has_no_letters |
(text: str) -> bool |
Check if string contains no letters (only numbers, emojis, special chars) | has_no_letters("123!@#") # True / has_no_letters("abc123") # False |
Number Functions
| Function | Type | Description | Example |
|---|---|---|---|
format_number |
(value: float | int, *, locale: str | None = None, minimum_fraction_digits: int | None = None, maximum_fraction_digits: int | None = None, style: Literal["decimal", "currency", "percent"] = "decimal", currency: str | None = None) -> str |
Format a number with locale-aware separators, fraction-digit controls, and decimal/percent/currency styles. Mirrors Intl.NumberFormat from the TypeScript source. |
format_number(1234567.89) # "1,234,567.89" / format_number(1234567.89, locale="de-DE") # "1.234.567,89" / format_number(0.75, style="percent") # "75%" / format_number(1234.5, style="currency", currency="USD") # "$1,234.50" |
to_ordinal |
(value: int | float) -> str |
Convert a number to its English ordinal string (handles 11th/12th/13th specially) | to_ordinal(1) # "1st" / to_ordinal(11) # "11th" / to_ordinal(21) # "21st" |
to_percentage |
(value: float | int, total: float | int, decimals: int = 2) -> float |
Calculate the percentage of a value relative to a total (returns 0 when total is 0) | to_percentage(1, 3) # 33.33 / to_percentage(25, 100) # 25.0 |
Constants
DEFAULT_RANDOM_STRING_CHARS: Default character pool for random string generation (ASCII letters + digits)
Constraints
- Python 3.10+ (
requires-python = ">=3.10"). CI currently runs 3.10–3.15. boolis a subclass ofintin Python. Numeric validators must rejectTrue/Falseexplicitly so they do not treat them as1/0.- Exact arithmetic in math helpers uses
decimal.Decimalconstructed from strings, to match JavaScript number-string behavior. - Date week math uses Sunday-start weeks. Do not assume ISO weeks (
datetime.isocalendar()). - IP helpers are IPv4 only. They validate input (TypeScript does not).
subnet_mask_to_cidrrequires a contiguous mask; TypeScriptsubnetMaskToCidronly counts set bits.is_private_ipis RFC 1918 only (not loopback or link-local). The three RFC 1918(network, mask)pairs are hoisted at module load, matching TypeScript / Rust / Go. decode_base32raisesValueErroron invalid / lowercase characters. TypeScriptdecodeBase32maps those to0.to_base_ndefaults to radix 2.True/Falseare1/0becauseboolis anint.hexa_to_rgbarequires#plus 3, 6, or 8 hex digits. TypeScripthexaToRgbadoes not validate.unescape_htmldecodes numeric entities withchr(). TypeScriptunescapeHtmladditionally rejects NULL, most C0 controls, DEL, C1, surrogates, and out-of-range values.escape_htmlencodes& < > " 'only. TypeScriptescapeHtmlalso encodes backtick (`) and/(/).to_full_widthconverts ASCII alnum only.to_half_widthalso converts full-width punctuation (U+FF01–U+FF5E) and ideographic space; TypeScript / Rust / GotoHalfWidthconvert digits and letters only.slugifykeeps Unicode letters (Python\w). TypeScript / Goslugifyuse ASCII\wand drop CJK.parse_emailrequiresParseEmailOptions. It does not apply TypeScript's 320-character ReDoS cap.math_converterformats split terms withfloat("1500.0*1000+…"). TypeScript / Rust / Go emit integers ("1500*1000+…").- UA helpers are coarse labels. Opera (
OPR/) is"other". Android without amobiletoken is"tablet". iPhone UAs that containlike Mac OS Xare"ios". sanitize_stringis ASCII-only. CJK, emoji, and accented letters are dropped. It is notstrip_ansi:"\x1b[31mred\x1b[0m"becomes"[31mred[0m".join_pathdoes not resolve./..and does not use OS separators.escape_regexpdoes not escape-or/.
Development
This project uses uv. Prefer the Makefile targets (same commands as CI):
make install # uv sync
make test # uv run pytest
make lint # ruff format --check && ruff check
make format # uv run ruff format
make typecheck # uv run pyright
make all # format, lint, typecheck, test
Tests live under tests/unit/ (mirroring src/) and import from src:
from src.date import is_between
License
MIT License
Metadata
Release files for umt_python 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| umt_python-0.4.0.tar.gz | 24.5 kB | Without provenance | Details for umt_python-0.4.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| umt_python-0.4.0-py3-none-any.whl | Python 3 | none | any | Details for umt_python-0.4.0-py3-none-any.whl |
Total release size: 39.9 kB
Release files / umt_python-0.4.0.tar.gz
| Download URL | umt_python-0.4.0.tar.gz |
|---|---|
| Size | 24.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
391289ad9cf4e2ed60ab7b8aaff69c1ebf72a4e7a20129a8883da3c41425891e
|
|
BLAKE2b-256 checksum How to use checksums |
413f2e6a5db38f27342c945d72b3225facfffe429cf14299efa05c78ed817791
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / umt_python-0.4.0-py3-none-any.whl
| Download URL | umt_python-0.4.0-py3-none-any.whl |
|---|---|
| Size | 15.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f807ec1a8943ee4512ecfa4b04b247be2c4a0e11f7ab261ff001a19ce8950c7f
|
|
BLAKE2b-256 checksum How to use checksums |
4f869db296b50ea75f7734ee9ef15594fb91f42325476ec8c3d47097b7926bb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for umt_python 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.