Library that extends the Python base class library with utility functions.
Project description
universal-common
A library that extends the Python base class library with utility functions and types, inspired by the .NET base class library and language features - without needing full feature parity, just enough to make everyday Python a little saner.
Features
- Null-coalescing (
coalesce) and null/whitespace string checks (is_null_or_empty,is_null_or_white_space) - LINQ-style iteration helpers (
first,first_or_default,last,last_or_default), available both as free functions and as methods onList Dictionary: adictsubclass that also supports attribute accessevent/BoundEvent: a C#-style event pattern with+=/-=subscriptionStopwatch: a simple elapsed-time measurer, usable as a context managerMediaType: parsing and building MIME media type strings (e.g."application/json; charset=utf-8")SemanticVersion: dependency-free Semantic Versioning 2.0.0 parsing and comparisonSqlConnectionStringBuilder: a minimal SQL connection string builder/parser
Installation
Install the package from PyPI using pip:
pip install universal-common
Usage
Null coalescing and string checks
from universal_common import coalesce, is_null_or_empty, is_null_or_white_space
coalesce(None, None, 3) # 3 - first non-None value
is_null_or_empty(None) # True
is_null_or_empty("") # True
is_null_or_white_space(" ") # True - unlike `if not s:`, this catches whitespace-only strings
LINQ-style iteration helpers
from universal_common import first, first_or_default, last, last_or_default, List
numbers = [1, 2, 5, 4]
first(numbers) # 1
first(numbers, lambda x: x > 3) # 5
last(numbers) # 4
last_or_default(numbers, lambda x: x > 10) # None, instead of raising
# The same methods are available directly on List:
items = List([1, 2, 5, 4])
items.first_or_default(lambda x: x > 3) # 5
items.last() # 4
first/last raise ValueError when nothing matches; first_or_default/last_or_default return None instead.
Attribute-accessible dictionaries
from universal_common import Dictionary
settings = Dictionary({"name": "Ada"})
settings.name # "Ada"
settings["name"] # "Ada"
settings.age = 30 # same as settings["age"] = 30
settings.missing # None, does not raise
C#-style events
from universal_common import event
class Button:
@event
def clicked(self):
"""Raised when the button is clicked."""
button = Button()
button.clicked += lambda: print("clicked!")
button.clicked() # invokes every subscribed handler
If more than one handler raises, every handler still runs; the first exception is raised, and any additional ones are attached to it as .other_exceptions rather than silently discarded.
Timing
from universal_common import Stopwatch
with Stopwatch() as stopwatch:
do_work()
print(stopwatch.elapsed, "seconds")
# Or standalone:
stopwatch = Stopwatch.start_new()
do_work()
stopwatch.stop()
print(stopwatch.elapsed_milliseconds, "ms")
Media types
from universal_common import MediaType
media_type = MediaType.parse("application/json; charset=utf-8")
media_type.full_type # "application/json"
media_type.charset # "utf-8"
str(media_type) # "application/json; charset=utf-8"
Semantic versioning
from universal_common import SemanticVersion
version = SemanticVersion.parse("1.2.3-beta.1+build.5")
version.major, version.minor, version.patch # (1, 2, 3)
SemanticVersion.parse("1.0.0-alpha") < SemanticVersion.parse("1.0.0") # True
sorted([SemanticVersion.parse(v) for v in ["2.0.0", "1.0.0", "1.5.0"]])
Comparison follows the semver 2.0.0 precedence rules exactly: numeric identifiers sort before alphanumeric ones, a version without a prerelease outranks one with a prerelease at the same major.minor.patch, and build metadata (+...) is ignored for comparison.
SQL connection strings
from universal_common import SqlConnectionStringBuilder
builder = SqlConnectionStringBuilder()
builder.server = "localhost"
builder.database = "app"
builder.user_id = "admin"
builder.password = "hunter2"
str(builder) # "Server=localhost;Database=app;Uid=admin;Pwd=hunter2"
parsed = SqlConnectionStringBuilder.parse("Server=localhost;Database=app")
parsed.server # "localhost"
License
CC0 1.0 Universal (Public Domain Dedication).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file universal_common-1.3.0.tar.gz.
File metadata
- Download URL: universal_common-1.3.0.tar.gz
- Upload date:
- Size: 10.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
711c9297df2dd399a16dc31e3c050f2f6f0acf865f6c7916175e8260651b1fb8
|
|
| MD5 |
bdbdf20c6b933023c2d97275c477259f
|
|
| BLAKE2b-256 |
7d6872d0a3ab2fa2a3de2d2c6bc9dcb72a40f5a70027e2e5b89dc92d4f385801
|
File details
Details for the file universal_common-1.3.0-py3-none-any.whl.
File metadata
- Download URL: universal_common-1.3.0-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a152ba0cabd125e6b0be057fa191a49e8079c7db92d5aab5f46dfe02dfee5dab
|
|
| MD5 |
436b8c2cd2106106af893a04d06fabd7
|
|
| BLAKE2b-256 |
ef4fddd62831fd92db960c908d43ed2bd80fd482c4dc3c28aa106607c570d131
|