Utilities
The openviper.utils package provides lightweight helper modules used
throughout the framework: timezone-aware datetime helpers, high-performance
data structures for HTTP primitives, a cached import utility, i18n
translation, logging configuration, and CLI module resolution.
Overview
These utilities are building blocks for the rest of the framework. Application code can import them freely; they have no side effects on import.
Key Modules
openviper.utils.timezone
Timezone-aware datetime helpers that respect settings.USE_TZ and
settings.TIME_ZONE.
- now() datetime.datetime
Return the current datetime. If
USE_TZ=Truereturns a UTC-aware datetime; otherwise returns a naive local datetime.
- get_current_timezone() zoneinfo.ZoneInfo
Return a
ZoneInfoinstance forsettings.TIME_ZONE.
- get_settings() object
Return the active settings proxy. Used internally for backwards-compatible patching in tests.
- make_aware(value, timezone=None) datetime.datetime
Attach timezone (defaults to
get_current_timezone()) to a naive value. RaisesValueErrorif value is already aware.
- make_naive(value, timezone=None) datetime.datetime
Remove timezone info from an aware value after converting to timezone. Raises
ValueErrorif value is already naive.
- localtime(value=None, timezone=None) datetime.datetime
Convert an aware datetime to the configured timezone. If value is
None, returns the current time in the configured timezone. If value is naive, it is assumed to be in the configured timezone.
- utc
The UTC
datetime.timezonesingleton (datetime.UTC).
openviper.utils.datastructures
HTTP-oriented data structures backed by multidict C extensions for O(1)
lookups.
- check_no_crlf(value, label='Header value') None
Raise
ValueErrorif value contains CR or LF characters. Guards against HTTP response splitting.
- unique_keys(iterable) Iterator[str]
Yield each key from iterable only once, preserving first-occurrence order.
- unique_items(iterable) Iterator[tuple[str, str]]
Yield each
(key, value)pair from iterable only once per key, preserving first-occurrence order.
- class Headers(raw)
Immutable, case-insensitive HTTP header map.
raw- list of[name_bytes, value_bytes]pairs (ASGI format)..get(key, default=None)- case-insensitive lookup..getlist(key)- return all values for a header..raw- original bytes list aslist[tuple[bytes, bytes]].
- class MutableHeaders(raw=None)
Mutable header map; used internally when constructing responses.
.set(key, value)- replace all values for key..append(key, value)- add a new header (allows duplicates)..delete(key)- remove all entries for key.
- class QueryParams(query_string)
Immutable parsed query string. Supports
getlist(key)for repeated parameters.
- class ImmutableMultiDict(data)
Immutable multi-value dict for form data and file fields.
openviper.utils.importlib
- import_string(dotted_path) Callable[..., object]
Import and return an object by its dotted Python path. Results are cached to avoid repeated imports. Failed imports are not cached so that transient
sys.pathissues do not permanently poison the cache.Raises
ImportErrorif the module cannot be found or dotted_path has no dot separator.
- import_string_uncached(dotted_path) Callable[..., object]
Import and return an object by its dotted Python path without caching.
- IMPORT_CACHE
The
dict[str, Callable[..., object]]used byimport_stringfor caching. Accessible for test introspection.
openviper.utils.translation
Context-variable-based internationalization using Python’s gettext
module. Language is scoped per async task via contextvars.
- gettext_lazy(message) LazyString
Return a
LazyStringthat defers translation until it is evaluated (e.g. at template render time).
- get_translation_object(language) gettext.NullTranslations
Retrieve or load a translation object for language. Falls back to
NullTranslationsonOSErrororValueError.
- translations_cache
The
dict[str, gettext.NullTranslations]mapping language codes to loaded translation objects.
- LOCALE_DIR
Absolute path to the
locale/directory.
- DEFAULT_DOMAIN
gettext domain name (default:
"messages").
- class LazyString(message)
A string-like object that defers its translation until it is actually used. Supports
str(),len(),bool(),==,+, and%formatting.
openviper.utils.logging
Uvicorn logging configuration with timestamps.
openviper.utils.module_resolver
Resolves viperctl target arguments to concrete module locations for
flexible project layouts.
- class ResolvedModule
Frozen dataclass result of resolving a target argument.
app_label: str- importable app label.app_path: Path- absolute filesystem path to the app directory.is_root: bool-Truewhen the target was".".models_module: str- dotted import path for the models file.
- resolve_target(target, cwd=None) ResolvedModule
Resolve a
viperctltarget string to a concrete module location. target is"."for CWD-as-app, or a module name like"todo".Raises
click.ClickExceptionif the target cannot be resolved.
- resolve_root(cwd) ResolvedModule
Treat the CWD itself as the application module.
- resolve_module(target, cwd) ResolvedModule
Resolve a named module directory inside cwd.
openviper.utils.settings_discovery
Auto-discovers settings.py for flexible project layouts so that
viperctl can set OPENVIPER_SETTINGS_MODULE without a
pre-generated project scaffold.
- discover_settings_module(target, cwd=None, explicit=None) str | None
Resolve a dotted settings module path. Resolution priority:
explicit - value from the
--settingsflag (returned as-is).Module settings -
<target>/settingsexists inside cwd.Root settings -
settingsdirectly in cwd.
Returns a dotted Python module path, or
Noneif no settings file was found.
Example Usage
Timezone Helpers
from openviper.utils import timezone
# Current time (UTC-aware when USE_TZ=True)
ts = timezone.now()
# Convert a naive timestamp to the configured timezone
import datetime
naive = datetime.datetime(2024, 6, 1, 12, 0, 0)
aware = timezone.make_aware(naive)
# Check awareness
print(timezone.is_aware(aware)) # True
Headers Usage
from openviper.utils.datastructures import Headers
raw = [(b"content-type", b"application/json"), (b"x-request-id", b"abc123")]
headers = Headers(raw)
print(headers.get("content-type")) # "application/json"
print(headers.get("X-Request-ID")) # "abc123" (case-insensitive)
Dynamic Import
from openviper.utils.importlib import import_string
StorageClass = import_string("myproject.storage.S3Storage")
storage = StorageClass(bucket="my-bucket")
Translation
from openviper.utils.translation import gettext, set_language
set_language("fr")
msg = gettext("Welcome")
Module Resolution
from openviper.utils.module_resolver import resolve_target
resolved = resolve_target("todo")
print(resolved.app_label) # "todo"
print(resolved.models_module) # "todo.models"