# Advanced Python Utilities Module
This module provides a comprehensive set of utilities for advanced Python programming, including HTTP communication, string handling, logging enhancements, introspection, dynamic importing, property descriptors, data class extensions, and serialization. It is designed to facilitate complex application development by offering robust tools that extend Python's standard capabilities.
## Table of Contents
- [HTTP Communication Utilities](#http-communication-utilities)
- [String Handling Enhancements](#string-handling-enhancements)
- [Advanced Logging System](#advanced-logging-system)
- [Introspection and Reflection Utilities](#introspection-and-reflection-utilities)
- [Dynamic Importing Tools](#dynamic-importing-tools)
- [Advanced Property Descriptors](#advanced-property-descriptors)
- [Data Class Extensions and Configuration Handling](#data-class-extensions-and-configuration-handling)
- [Serialization and Deserialization Utilities](#serialization-and-deserialization-utilities)
## HTTP Communication Utilities
### Overview
This component provides a robust toolkit for handling HTTP communication. It includes advanced features for error handling, response parsing, cookie management, and URL processing. The utilities streamline building HTTP clients and services by abstracting common patterns and offering flexible, extensible components.
### Key Features
- **HTTPException Hierarchy**: A comprehensive set of exception classes for handling HTTP errors, based on status codes and error types.
- **Response Handling**: Utilities for parsing and processing HTTP responses, including automatic JSON decoding and error checking.
- **Cookie Management**: Tools for managing HTTP cookies, including parsing and formatting.
- **URL Processing**: Classes and functions for manipulating URLs, including query parameters and path components.
- **Serialization Decorators**: Decorators to facilitate serialization and deserialization of complex objects within the HTTP context.
- **Namespace Augmentation**: Enhancements to the HTTP namespace for convenient access to common utilities like `HTTP.URL`, `HTTP.Agent`, and `HTTP.Exception`.
## String Handling Enhancements
### Overview
Provides advanced string handling utilities focused on character encoding detection, conversion, and manipulation. It defines the `Str` class, acting as a wrapper around string or bytes objects, offering methods to handle various encoding scenarios and to facilitate text processing.
### Key Features
- **Encoding and Decoding**: Convert between bytes and string representations, handling different character encodings.
- **Charset Detection**: Automatically detects the character encoding of input data using custom logic and libraries.
- **Lazy Proxying**: Proxies common string methods to the underlying string representation, allowing `Str` instances to behave like regular strings.
- **Tokenization**: Methods to split strings into tokens based on regular expression patterns.
## Advanced Logging System
### Overview
Enhances the standard Python logging system by introducing custom log levels, additional logging utilities, and a more flexible logger configuration. It provides advanced logging capabilities suitable for complex applications that require detailed logging and traceability.
### Key Features
- **Custom Log Levels**: Defines additional log levels like `NOTICE`, `DEPRECATE`, and `VERBOSE` for finer-grained logging.
- **Logger Configuration**: Supports configuration from files (e.g., `logging.toml`), environment variables, or default settings.
- **Logger Extensions**: Provides a `Logger` class with enhanced methods for logging, including context-aware logging and deduplication of messages.
- **Integration with Modules**: Automatically injects the custom logger into modules, ensuring consistent logging behavior across the application.
## Introspection and Reflection Utilities
### Overview
Offers a collection of utility functions and classes for introspection, type checking, and reflection. It includes functions to analyze objects, their types, inheritance hierarchies, and modules.
### Key Features
- **Type Checking Functions**: Utilities like `is_callable`, `is_collection`, and `is_iterable` for checking object types.
- **Inheritance Utilities**: Functions to iterate over an object's MRO, get attributes from superclasses, and analyze class hierarchies.
- **Module and Object Inspection**: Tools to get the module of an object, its fully qualified name, source file, and other metadata.
- **Stack Inspection**: Functions to analyze the call stack, filter stack traces, and determine stack frame offsets.
## Dynamic Importing Tools
### Overview
Provides utilities for dynamic importing of modules and objects, with support for caching, handling optional dependencies, and enhanced error reporting.
### Key Features
- **Dynamic Importing**: Functions like `import_object` to import modules or objects by name at runtime.
- **Caching Imports**: `cached_import` function to memoize imports and improve performance.
- **Optional Dependencies**: `optional` function to handle optional imports gracefully, returning `None` or a default value if the module is not available.
- **Error Handling**: Detailed logging and error messages to aid in debugging import issues, including suggestions for missing packages.
## Advanced Property Descriptors
### Overview
Provides advanced property descriptors for Python classes, allowing the creation of instance, class, and mixed properties with optional caching capabilities. It includes decorators and base classes to facilitate the definition of properties that can behave differently depending on access context.
### Key Features
- **Custom Property Decorators**: Decorators like `@Class.Property` and `@Property.Cached` to define properties with custom behaviors.
- **Caching Support**: Ability to cache property results, optimizing performance for expensive computations.
- **Context-Aware Properties**: Properties that can differentiate between being accessed from an instance or a class.
- **Async Support**: Supports both synchronous and asynchronous property methods.
## Data Class Extensions and Configuration Handling
### Overview
Extends the standard `dataclass` module with additional features such as validation, serialization, dynamic class creation, and integration with custom logging mechanisms.
### Key Features
- **Custom Data Classes**: Enhanced `dataclass` decorator that supports extra parameters, memoization, and custom initialization.
- **Validation**: Automatic validation of field types and default values against the defined schema.
- **Serialization Methods**: Methods like `as_dict`, `as_json`, and `as_sql` for converting instances to different formats.
- **Dynamic Class Creation**: Utilities like `autoclass` and `simple` to generate classes dynamically based on configuration schemas.
- **Operator Overloading**: Overloaded operators (`&`, `|`, `^`, `-`, `+`) for combining and comparing data class instances.
## Serialization and Deserialization Utilities
### Overview
Provides advanced serialization and deserialization utilities, supporting multiple serialization backends, compression algorithms, and encoding schemes. It allows custom serialization of complex objects, automatic detection of serialization formats, and flexible data encoding and decoding options.
### Key Features
- **Multiple Backends**: Supports serialization backends like `orjson` and standard `json`, with automatic selection.
- **Custom Serialization**: Ability to register custom serialization functions for specific classes.
- **Compression Support**: Utilizes compression libraries like `zstd` or `gzip` to compress serialized data.
- **Flexible Encoding**: Supports multiple encoding schemes such as Base16, Base32, Base64, Base85, and Base2048.
- **Automatic Backend Detection**: Deserialization functions automatically detect the serialization backend used.
- **Error Handling**: Robust exception handling and context-aware suppression of errors.
# Tasks
## lint
Requires: venv, update
Runs all defined pre-commit hooks.
```bash
uvx pre-commit run --config ci/.pre-commit-config.yaml --color always --all
```
## force-update
Run: once
Requires: venv
Update all pre-commit hook versions to latest releases.
```bash
uvx pre-commit autoupdate --config ci/.pre-commit-config.yaml --color always
uncommited="$(git diff --cached --name-only | sort -u | tr '\n' ' ' | xargs)"
changes="$(git ls-files --deleted --modified --exclude-standard)"
changes="$(printf "$changes" | sort -u | tr '\n' ' ' | xargs)"
if [[ "$uncommited" =~ "\bci/\.pre-commit-config\.yaml\b" ]] || [[ "$changes" =~ "\bci/\.pre-commit-config\.yaml\b" ]]; then
xc add-precommit
fi
```
## publish
Run: once
Requires: venv, update
Input: mode
Environment: mode=patch
Bumps project new version, build and publish the package to repository.
```bash
xc bump "$mode"
rm -rf dist/ || true
uv build
uvx uv-publish --repo kalib
rm -rf dist/ || true
uv sync --all-extras
```
## clean
Run: once
Clean up the project working directory: remove build/, .venv/, and .ruff_cache/ directories, as well as all .pyc files and __pycache__ directories.
```bash
rm -rf dist/ 2>/dev/null || true
rm -rf build/ 2>/dev/null || true
rm -rf src/*.egg-info/ 2>/dev/null || true
rm -rf .mypy_cache/ 2>/dev/null || true
rm -rf .ruff_cache/ 2>/dev/null || true
rm -rf .pytest_cache/ 2>/dev/null || true
rm -rf ci/.ruff_cache/ 2>/dev/null || true
find . -name "*.pyc" -delete || true
find . -name "__pycache__" -type d -exec rm -rf {} + || true
```
## clean-all
Run: once
Clean up the project working directory: remove build/, .venv/, and .ruff_cache/ directories, as well as all .pyc files and __pycache__ directories.
```bash
xc stop || true
xc clean
rm -rf .venv/ || true
```
## venv
Run: once
Make virtualenv for project build & test tools, install pre-push hook.
```bash
if [ ! -d ".venv" ]; then
uv venv
uv sync --all-extras
uvx pre-commit install \
--config ci/.pre-commit-config.yaml \
--color always \
--hook-type pre-push \
--install-hooks \
--overwrite
else
[ -f ".venv/bin/activate" ]
fi
```
## update
Run: once
Autoupdate pre-commit hooks if the last update was more than 7 days ago.
```bash
ctime="$(date +%s)"
mtime="$(git log -1 --format=%ct ci/.pre-commit-config.yaml)"
result=$(((7*86400) - (ctime - mtime)))
if [ "$result" -le 0 ]; then
xc force-update
fi
```
## bump
Run: once
Requires: venv
Inputs: mode
Environment: mode=patch
Prepare and commit a version update in a Git repository. Checks for uncommitted changes, ensures the current branch is master, verifies if there are any changes since the last tag, and bumps the version number.
After validating the readiness for an update, it prompts to proceed. Once confirmed, the script updates the pyproject.toml and .pre-commit-config.yaml files if necessary, commits the changes, tags the new version, and pushes the updates to the remote repository.
```bash
#!/bin/zsh
uncommited="$(git diff --cached --name-only | sort -u | tr '\n' ' ' | xargs)"
if [ -n "$uncommited" ]; then
echo "uncommited changes found"
exit 1
fi
#
branch="$(git rev-parse --quiet --abbrev-ref HEAD 2>/dev/null)"
if [ -z "$branch" ]; then
exit 1
elif [ "$branch" == "master" ]; then
echo "using main master mode"
else
exit 1
fi
#
changes="$(git ls-files --deleted --modified --exclude-standard)"
changes="$(printf "$changes" | sort -u | tr '\n' ' ' | xargs)"
if [ "$changes" == "README.md" ]; then
echo "pipeline development mode"
elif [ -n "$changes" ]; then
echo "uncommited changes found"
exit 1
fi
git fetch --tags --force
current="$(git tag --list | sort -rV | head -n 1)" || retval="$?"
if [ "$retval" -eq 128 ]; then
current="0.0.0"
elif [ "$retval" -gt 0 ]; then
echo "something goes wrong on last used git tag fetch"
exit "$retval"
fi
[ -z "$current" ] && exit 1
if [ "$current" = '0.0.0' ]; then
amount="1"
else
amount="$(git rev-list --count $current..HEAD)"
fi
uncommited="$(git diff --cached --name-only | sort -u | tr '\n' ' ' | xargs)"
if [ "$amount" -eq 0 ] && [ -z "$uncommited" ]; then
echo "no changes since $current"
exit 1
fi
version="$(bump "$mode" "$current")"
[ -z "$version" ] && exit 1
revision="$(git rev-parse "$version" 2>/dev/null)" || retval="$?"
if [ "$retval" -eq 128 ]; then
echo "future tag $revision not found, continue"
elif [ -z "$retval" ] && [ -n "$revision" ]; then
echo "future tag $version already set to commit $revision, sync with remote branch!"
exit 1
else
echo "something went wrong, version: '$version' revision: '$revision', retval: '$retval'"
exit 2
fi
# non destructive stop here
if [ -d "tests/" ]; then
xc test
fi
xc lint
git-restore-mtime --skip-missing || echo "datetime restoration failed, return: $?, skip"
ls -la
echo "we ready for bump $current -> $version, press ENTER twice to proceed or ESC+ENTER to exit"
counter=0
while : ; do
read -r key
if [[ $key == $'\e' ]]; then
exit 1
elif [ -z "$key" ]; then
counter=$((counter + 1))
if [ "$counter" -eq 2 ]; then
break
fi
fi
done
# actions starts here
xc add-precommit
xc update-pyproject "$current" "$version"
xc add-pyproject
uncommited="$(git diff --cached --name-only | sort -u | tr '\n' ' ' | xargs)"
if [ -n "$uncommited" ]; then
git commit -m "$branch: $version"
fi
git tag -a "$version" -m "$version"
git push --tags
git push origin "$branch"
echo "version updated to $version"
```
## add-precommit
Requires: venv
Check and format ci/.pre-commit-config.yaml. If any changes are made, it stages the file for the next commit.
```bash
file="ci/.pre-commit-config.yaml"
uvx pre-commit run check-yaml --config "$file" --color always --file "$file" || value="$?"
while true; do
value="0"
uvx pre-commit run yamlfix --config "$file" --color always --file "$file" || value="$?"
if [ "$value" -eq 0 ]; then
break
elif [ "$value" -eq 1 ]; then
continue
else
exit "$value"
fi
done
uncommited="$(git diff --cached --name-only | sort -u | tr '\n' ' ' | xargs)"
changes="$(git ls-files --deleted --modified --exclude-standard)"
changes="$(printf "$changes" | sort -u | tr '\n' ' ' | xargs)"
if [[ "$uncommited" =~ "\bci/\.pre-commit-config\.yaml\b" ]] || [[ "$changes" =~ "\bci/\.pre-commit-config\.yaml\b" ]]; then
git add "$file"
git commit -m "(ci/cd): autoupdate pre-commit"
fi
```
## add-pyproject
Requires: venv
Check and format pyproject.toml. If any changes are made, it stages the file for the next commit.
```bash
file="pyproject.toml"
uvx pre-commit run check-toml --config ci/.pre-commit-config.yaml --color always --file "$file" || value="$?"
while true; do
value="0"
uvx pre-commit run pretty-format-toml --config ci/.pre-commit-config.yaml --color always --file "$file" || value="$?"
if [ "$value" -eq 0 ]; then
break
elif [ "$value" -eq 1 ]; then
continue
else
exit "$value"
fi
done
changes="$(git diff "$file")" || exit "$?"
changes="$(printf "$changes" | wc -l)"
if [ "$changes" -ne 0 ]; then
git add "$file"
fi
```
## update-pyproject
Run: once
Requires: venv
Update version in pyproject.toml file based on provided old and new version tags. It validates the version format and ensures the current tag matches the project's version before writing the new version.
```python
#!.venv/bin/python
from os import environ
from sys import argv, exit
from re import match
from pathlib import Path
import tomli_w
try:
import tomllib as reader
except ImportError:
import tomli as reader
ROOT = Path(environ['PWD'])
def get_version(string):
try:
return match(r'^(\d+\.\d+\.\d+)$', string).group(1)
except Exception:
print(f'could not parse version from {string}')
exit(3)
if __name__ == '__main__':
try:
current_tag = get_version(argv[1])
version_tag = get_version(argv[2])
except IndexError:
print('usage: xc update-pyproject <old_tag> <new_tag>')
exit(1)
path = ROOT / 'pyproject.toml'
try:
with open(path, 'rb') as fd:
data = reader.load(fd)
except Exception:
print(f'could not load {path}')
exit(2)
try:
current_ver = get_version(data['project']['version'])
print(f'project version: {current_ver}')
except KeyError:
print(f'could not find version in {data}')
exit(2)
if current_tag != current_ver:
if current_ver == version_tag:
print(f'current version {current_ver} == {version_tag}, no update needed')
exit(0)
print(f'current tag {current_tag} != {current_ver} current version')
exit(4)
data['project']['version'] = version_tag
try:
with open(path, 'wb') as fd:
tomli_w.dump(data, fd)
print(f'project version -> {version_tag}')
except Exception:
print(f'could not write {path} with {data=}')
exit(5)
```
## test
Run: once
Requires: venv
```bash
uvx pytest -svx
```
Raw data
{
"_id": null,
"home_page": null,
"name": "kalib",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "dataclass, decorators, descriptors, http, import, introspection, logging, python, serialization, string, utilities",
"author": null,
"author_email": "Alex Kalaverin <alex@kalaver.in>",
"download_url": "https://files.pythonhosted.org/packages/ca/eb/e43e82da015b4a52864cc3ac4d2a90323dd4ad8735d978614c738cc9fb84/kalib-0.21.1.tar.gz",
"platform": null,
"description": "# Advanced Python Utilities Module\n\nThis module provides a comprehensive set of utilities for advanced Python programming, including HTTP communication, string handling, logging enhancements, introspection, dynamic importing, property descriptors, data class extensions, and serialization. It is designed to facilitate complex application development by offering robust tools that extend Python's standard capabilities.\n\n## Table of Contents\n\n- [HTTP Communication Utilities](#http-communication-utilities)\n- [String Handling Enhancements](#string-handling-enhancements)\n- [Advanced Logging System](#advanced-logging-system)\n- [Introspection and Reflection Utilities](#introspection-and-reflection-utilities)\n- [Dynamic Importing Tools](#dynamic-importing-tools)\n- [Advanced Property Descriptors](#advanced-property-descriptors)\n- [Data Class Extensions and Configuration Handling](#data-class-extensions-and-configuration-handling)\n- [Serialization and Deserialization Utilities](#serialization-and-deserialization-utilities)\n\n## HTTP Communication Utilities\n\n### Overview\n\nThis component provides a robust toolkit for handling HTTP communication. It includes advanced features for error handling, response parsing, cookie management, and URL processing. The utilities streamline building HTTP clients and services by abstracting common patterns and offering flexible, extensible components.\n\n### Key Features\n\n- **HTTPException Hierarchy**: A comprehensive set of exception classes for handling HTTP errors, based on status codes and error types.\n- **Response Handling**: Utilities for parsing and processing HTTP responses, including automatic JSON decoding and error checking.\n- **Cookie Management**: Tools for managing HTTP cookies, including parsing and formatting.\n- **URL Processing**: Classes and functions for manipulating URLs, including query parameters and path components.\n- **Serialization Decorators**: Decorators to facilitate serialization and deserialization of complex objects within the HTTP context.\n- **Namespace Augmentation**: Enhancements to the HTTP namespace for convenient access to common utilities like `HTTP.URL`, `HTTP.Agent`, and `HTTP.Exception`.\n\n## String Handling Enhancements\n\n### Overview\n\nProvides advanced string handling utilities focused on character encoding detection, conversion, and manipulation. It defines the `Str` class, acting as a wrapper around string or bytes objects, offering methods to handle various encoding scenarios and to facilitate text processing.\n\n### Key Features\n\n- **Encoding and Decoding**: Convert between bytes and string representations, handling different character encodings.\n- **Charset Detection**: Automatically detects the character encoding of input data using custom logic and libraries.\n- **Lazy Proxying**: Proxies common string methods to the underlying string representation, allowing `Str` instances to behave like regular strings.\n- **Tokenization**: Methods to split strings into tokens based on regular expression patterns.\n\n## Advanced Logging System\n\n### Overview\n\nEnhances the standard Python logging system by introducing custom log levels, additional logging utilities, and a more flexible logger configuration. It provides advanced logging capabilities suitable for complex applications that require detailed logging and traceability.\n\n### Key Features\n\n- **Custom Log Levels**: Defines additional log levels like `NOTICE`, `DEPRECATE`, and `VERBOSE` for finer-grained logging.\n- **Logger Configuration**: Supports configuration from files (e.g., `logging.toml`), environment variables, or default settings.\n- **Logger Extensions**: Provides a `Logger` class with enhanced methods for logging, including context-aware logging and deduplication of messages.\n- **Integration with Modules**: Automatically injects the custom logger into modules, ensuring consistent logging behavior across the application.\n\n## Introspection and Reflection Utilities\n\n### Overview\n\nOffers a collection of utility functions and classes for introspection, type checking, and reflection. It includes functions to analyze objects, their types, inheritance hierarchies, and modules.\n\n### Key Features\n\n- **Type Checking Functions**: Utilities like `is_callable`, `is_collection`, and `is_iterable` for checking object types.\n- **Inheritance Utilities**: Functions to iterate over an object's MRO, get attributes from superclasses, and analyze class hierarchies.\n- **Module and Object Inspection**: Tools to get the module of an object, its fully qualified name, source file, and other metadata.\n- **Stack Inspection**: Functions to analyze the call stack, filter stack traces, and determine stack frame offsets.\n\n## Dynamic Importing Tools\n\n### Overview\n\nProvides utilities for dynamic importing of modules and objects, with support for caching, handling optional dependencies, and enhanced error reporting.\n\n### Key Features\n\n- **Dynamic Importing**: Functions like `import_object` to import modules or objects by name at runtime.\n- **Caching Imports**: `cached_import` function to memoize imports and improve performance.\n- **Optional Dependencies**: `optional` function to handle optional imports gracefully, returning `None` or a default value if the module is not available.\n- **Error Handling**: Detailed logging and error messages to aid in debugging import issues, including suggestions for missing packages.\n\n## Advanced Property Descriptors\n\n### Overview\n\nProvides advanced property descriptors for Python classes, allowing the creation of instance, class, and mixed properties with optional caching capabilities. It includes decorators and base classes to facilitate the definition of properties that can behave differently depending on access context.\n\n### Key Features\n\n- **Custom Property Decorators**: Decorators like `@Class.Property` and `@Property.Cached` to define properties with custom behaviors.\n- **Caching Support**: Ability to cache property results, optimizing performance for expensive computations.\n- **Context-Aware Properties**: Properties that can differentiate between being accessed from an instance or a class.\n- **Async Support**: Supports both synchronous and asynchronous property methods.\n\n## Data Class Extensions and Configuration Handling\n\n### Overview\n\nExtends the standard `dataclass` module with additional features such as validation, serialization, dynamic class creation, and integration with custom logging mechanisms.\n\n### Key Features\n\n- **Custom Data Classes**: Enhanced `dataclass` decorator that supports extra parameters, memoization, and custom initialization.\n- **Validation**: Automatic validation of field types and default values against the defined schema.\n- **Serialization Methods**: Methods like `as_dict`, `as_json`, and `as_sql` for converting instances to different formats.\n- **Dynamic Class Creation**: Utilities like `autoclass` and `simple` to generate classes dynamically based on configuration schemas.\n- **Operator Overloading**: Overloaded operators (`&`, `|`, `^`, `-`, `+`) for combining and comparing data class instances.\n\n## Serialization and Deserialization Utilities\n\n### Overview\n\nProvides advanced serialization and deserialization utilities, supporting multiple serialization backends, compression algorithms, and encoding schemes. It allows custom serialization of complex objects, automatic detection of serialization formats, and flexible data encoding and decoding options.\n\n### Key Features\n\n- **Multiple Backends**: Supports serialization backends like `orjson` and standard `json`, with automatic selection.\n- **Custom Serialization**: Ability to register custom serialization functions for specific classes.\n- **Compression Support**: Utilizes compression libraries like `zstd` or `gzip` to compress serialized data.\n- **Flexible Encoding**: Supports multiple encoding schemes such as Base16, Base32, Base64, Base85, and Base2048.\n- **Automatic Backend Detection**: Deserialization functions automatically detect the serialization backend used.\n- **Error Handling**: Robust exception handling and context-aware suppression of errors.\n\n# Tasks\n\n## lint\n\nRequires: venv, update\n\nRuns all defined pre-commit hooks.\n\n```bash\nuvx pre-commit run --config ci/.pre-commit-config.yaml --color always --all\n```\n\n## force-update\n\nRun: once\nRequires: venv\n\nUpdate all pre-commit hook versions to latest releases.\n\n```bash\n\n uvx pre-commit autoupdate --config ci/.pre-commit-config.yaml --color always\n\n uncommited=\"$(git diff --cached --name-only | sort -u | tr '\\n' ' ' | xargs)\"\n changes=\"$(git ls-files --deleted --modified --exclude-standard)\"\n changes=\"$(printf \"$changes\" | sort -u | tr '\\n' ' ' | xargs)\"\n\n if [[ \"$uncommited\" =~ \"\\bci/\\.pre-commit-config\\.yaml\\b\" ]] || [[ \"$changes\" =~ \"\\bci/\\.pre-commit-config\\.yaml\\b\" ]]; then\n xc add-precommit\n fi\n```\n\n## publish\n\nRun: once\nRequires: venv, update\n\nInput: mode\nEnvironment: mode=patch\n\nBumps project new version, build and publish the package to repository.\n\n```bash\n\nxc bump \"$mode\"\n\nrm -rf dist/ || true\nuv build\nuvx uv-publish --repo kalib\nrm -rf dist/ || true\nuv sync --all-extras\n\n```\n\n## clean\n\nRun: once\n\nClean up the project working directory: remove build/, .venv/, and .ruff_cache/ directories, as well as all .pyc files and __pycache__ directories.\n\n```bash\n\n rm -rf dist/ 2>/dev/null || true\n rm -rf build/ 2>/dev/null || true\n rm -rf src/*.egg-info/ 2>/dev/null || true\n\n rm -rf .mypy_cache/ 2>/dev/null || true\n rm -rf .ruff_cache/ 2>/dev/null || true\n rm -rf .pytest_cache/ 2>/dev/null || true\n rm -rf ci/.ruff_cache/ 2>/dev/null || true\n\n find . -name \"*.pyc\" -delete || true\n find . -name \"__pycache__\" -type d -exec rm -rf {} + || true\n```\n\n## clean-all\n\nRun: once\n\nClean up the project working directory: remove build/, .venv/, and .ruff_cache/ directories, as well as all .pyc files and __pycache__ directories.\n\n```bash\n\n xc stop || true\n xc clean\n rm -rf .venv/ || true\n```\n\n## venv\n\nRun: once\n\nMake virtualenv for project build & test tools, install pre-push hook.\n\n```bash\n if [ ! -d \".venv\" ]; then\n uv venv\n uv sync --all-extras\n\n uvx pre-commit install \\\n --config ci/.pre-commit-config.yaml \\\n --color always \\\n --hook-type pre-push \\\n --install-hooks \\\n --overwrite\n else\n [ -f \".venv/bin/activate\" ]\n\n fi\n```\n\n## update\n\nRun: once\n\nAutoupdate pre-commit hooks if the last update was more than 7 days ago.\n\n```bash\n\n ctime=\"$(date +%s)\"\n mtime=\"$(git log -1 --format=%ct ci/.pre-commit-config.yaml)\"\n\n result=$(((7*86400) - (ctime - mtime)))\n\n if [ \"$result\" -le 0 ]; then\n xc force-update\n fi\n```\n\n## bump\n\nRun: once\nRequires: venv\n\nInputs: mode\nEnvironment: mode=patch\n\nPrepare and commit a version update in a Git repository. Checks for uncommitted changes, ensures the current branch is master, verifies if there are any changes since the last tag, and bumps the version number.\n\nAfter validating the readiness for an update, it prompts to proceed. Once confirmed, the script updates the pyproject.toml and .pre-commit-config.yaml files if necessary, commits the changes, tags the new version, and pushes the updates to the remote repository.\n\n```bash\n#!/bin/zsh\n\n uncommited=\"$(git diff --cached --name-only | sort -u | tr '\\n' ' ' | xargs)\"\n if [ -n \"$uncommited\" ]; then\n echo \"uncommited changes found\"\n exit 1\n fi\n\n #\n\n branch=\"$(git rev-parse --quiet --abbrev-ref HEAD 2>/dev/null)\"\n if [ -z \"$branch\" ]; then\n exit 1\n elif [ \"$branch\" == \"master\" ]; then\n echo \"using main master mode\"\n else\n exit 1\n fi\n\n #\n\n changes=\"$(git ls-files --deleted --modified --exclude-standard)\"\n changes=\"$(printf \"$changes\" | sort -u | tr '\\n' ' ' | xargs)\"\n\n if [ \"$changes\" == \"README.md\" ]; then\n echo \"pipeline development mode\"\n elif [ -n \"$changes\" ]; then\n echo \"uncommited changes found\"\n exit 1\n fi\n\n git fetch --tags --force\n current=\"$(git tag --list | sort -rV | head -n 1)\" || retval=\"$?\"\n if [ \"$retval\" -eq 128 ]; then\n current=\"0.0.0\"\n elif [ \"$retval\" -gt 0 ]; then\n echo \"something goes wrong on last used git tag fetch\"\n exit \"$retval\"\n fi\n [ -z \"$current\" ] && exit 1\n\n if [ \"$current\" = '0.0.0' ]; then\n amount=\"1\"\n else\n amount=\"$(git rev-list --count $current..HEAD)\"\n fi\n\n uncommited=\"$(git diff --cached --name-only | sort -u | tr '\\n' ' ' | xargs)\"\n\n if [ \"$amount\" -eq 0 ] && [ -z \"$uncommited\" ]; then\n echo \"no changes since $current\"\n exit 1\n fi\n\n version=\"$(bump \"$mode\" \"$current\")\"\n [ -z \"$version\" ] && exit 1\n\n revision=\"$(git rev-parse \"$version\" 2>/dev/null)\" || retval=\"$?\"\n\n if [ \"$retval\" -eq 128 ]; then\n echo \"future tag $revision not found, continue\"\n\n elif [ -z \"$retval\" ] && [ -n \"$revision\" ]; then\n\n echo \"future tag $version already set to commit $revision, sync with remote branch!\"\n exit 1\n\n else\n echo \"something went wrong, version: '$version' revision: '$revision', retval: '$retval'\"\n exit 2\n fi\n\n # non destructive stop here\n\n if [ -d \"tests/\" ]; then\n xc test\n fi\n\n xc lint\n\n git-restore-mtime --skip-missing || echo \"datetime restoration failed, return: $?, skip\"\n ls -la\n echo \"we ready for bump $current -> $version, press ENTER twice to proceed or ESC+ENTER to exit\"\n\n counter=0\n while : ; do\n read -r key\n\n if [[ $key == $'\\e' ]]; then\n exit 1\n\n elif [ -z \"$key\" ]; then\n counter=$((counter + 1))\n if [ \"$counter\" -eq 2 ]; then\n break\n fi\n fi\n done\n\n # actions starts here\n\n xc add-precommit\n\n xc update-pyproject \"$current\" \"$version\"\n xc add-pyproject\n\n uncommited=\"$(git diff --cached --name-only | sort -u | tr '\\n' ' ' | xargs)\"\n if [ -n \"$uncommited\" ]; then\n git commit -m \"$branch: $version\"\n fi\n\n git tag -a \"$version\" -m \"$version\"\n git push --tags\n git push origin \"$branch\"\n\n echo \"version updated to $version\"\n```\n\n## add-precommit\n\nRequires: venv\n\nCheck and format ci/.pre-commit-config.yaml. If any changes are made, it stages the file for the next commit.\n\n```bash\n\n file=\"ci/.pre-commit-config.yaml\"\n\n uvx pre-commit run check-yaml --config \"$file\" --color always --file \"$file\" || value=\"$?\"\n\n while true; do\n value=\"0\"\n uvx pre-commit run yamlfix --config \"$file\" --color always --file \"$file\" || value=\"$?\"\n\n if [ \"$value\" -eq 0 ]; then\n break\n\n elif [ \"$value\" -eq 1 ]; then\n continue\n\n else\n exit \"$value\"\n\n fi\n done\n\n uncommited=\"$(git diff --cached --name-only | sort -u | tr '\\n' ' ' | xargs)\"\n changes=\"$(git ls-files --deleted --modified --exclude-standard)\"\n changes=\"$(printf \"$changes\" | sort -u | tr '\\n' ' ' | xargs)\"\n\n if [[ \"$uncommited\" =~ \"\\bci/\\.pre-commit-config\\.yaml\\b\" ]] || [[ \"$changes\" =~ \"\\bci/\\.pre-commit-config\\.yaml\\b\" ]]; then\n git add \"$file\"\n git commit -m \"(ci/cd): autoupdate pre-commit\"\n fi\n```\n\n## add-pyproject\n\nRequires: venv\n\nCheck and format pyproject.toml. If any changes are made, it stages the file for the next commit.\n\n```bash\n\n file=\"pyproject.toml\"\n\n uvx pre-commit run check-toml --config ci/.pre-commit-config.yaml --color always --file \"$file\" || value=\"$?\"\n\n while true; do\n value=\"0\"\n uvx pre-commit run pretty-format-toml --config ci/.pre-commit-config.yaml --color always --file \"$file\" || value=\"$?\"\n\n if [ \"$value\" -eq 0 ]; then\n break\n\n elif [ \"$value\" -eq 1 ]; then\n continue\n\n else\n exit \"$value\"\n\n fi\n done\n\n changes=\"$(git diff \"$file\")\" || exit \"$?\"\n changes=\"$(printf \"$changes\" | wc -l)\"\n if [ \"$changes\" -ne 0 ]; then\n git add \"$file\"\n fi\n```\n\n## update-pyproject\n\nRun: once\nRequires: venv\n\nUpdate version in pyproject.toml file based on provided old and new version tags. It validates the version format and ensures the current tag matches the project's version before writing the new version.\n\n```python\n#!.venv/bin/python\nfrom os import environ\nfrom sys import argv, exit\nfrom re import match\nfrom pathlib import Path\n\nimport tomli_w\n\ntry:\n import tomllib as reader\nexcept ImportError:\n import tomli as reader\n\n\nROOT = Path(environ['PWD'])\n\ndef get_version(string):\n try:\n return match(r'^(\\d+\\.\\d+\\.\\d+)$', string).group(1)\n except Exception:\n print(f'could not parse version from {string}')\n exit(3)\n\nif __name__ == '__main__':\n try:\n current_tag = get_version(argv[1])\n version_tag = get_version(argv[2])\n except IndexError:\n print('usage: xc update-pyproject <old_tag> <new_tag>')\n exit(1)\n\n path = ROOT / 'pyproject.toml'\n try:\n with open(path, 'rb') as fd:\n data = reader.load(fd)\n\n except Exception:\n print(f'could not load {path}')\n exit(2)\n\n try:\n current_ver = get_version(data['project']['version'])\n print(f'project version: {current_ver}')\n\n except KeyError:\n print(f'could not find version in {data}')\n exit(2)\n\n if current_tag != current_ver:\n if current_ver == version_tag:\n print(f'current version {current_ver} == {version_tag}, no update needed')\n exit(0)\n\n print(f'current tag {current_tag} != {current_ver} current version')\n exit(4)\n\n data['project']['version'] = version_tag\n\n try:\n with open(path, 'wb') as fd:\n tomli_w.dump(data, fd)\n\n print(f'project version -> {version_tag}')\n\n except Exception:\n print(f'could not write {path} with {data=}')\n exit(5)\n```\n\n## test\n\nRun: once\nRequires: venv\n\n```bash\n\n uvx pytest -svx\n```\n",
"bugtrack_url": null,
"license": "BSD License",
"summary": "A comprehensive set of advanced utilities for Python programming, e.g. HTTP communication, string handling, logging enhancements, introspection, dynamic importing, property caching descriptors, data class extensions, serialization, etc.",
"version": "0.21.1",
"project_urls": null,
"split_keywords": [
"dataclass",
" decorators",
" descriptors",
" http",
" import",
" introspection",
" logging",
" python",
" serialization",
" string",
" utilities"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9557be2d73aef5099ce9e83c81951db6ac298b00f5498489ac419ac34177d55a",
"md5": "71daff6aa70647a49105f922a05b9c1c",
"sha256": "69e8f341429a4d82bcced04cc4804c960e537fe4d969d200da44c835e8d81f85"
},
"downloads": -1,
"filename": "kalib-0.21.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "71daff6aa70647a49105f922a05b9c1c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 51097,
"upload_time": "2024-12-19T16:22:33",
"upload_time_iso_8601": "2024-12-19T16:22:33.797546Z",
"url": "https://files.pythonhosted.org/packages/95/57/be2d73aef5099ce9e83c81951db6ac298b00f5498489ac419ac34177d55a/kalib-0.21.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "caebe43e82da015b4a52864cc3ac4d2a90323dd4ad8735d978614c738cc9fb84",
"md5": "2bcd95aec02b281a24c0027b7c7db4ff",
"sha256": "3ee5cdd524f5782e6201f349c8d778fe31d6ea0c86d874d00d8e37262c87f4a1"
},
"downloads": -1,
"filename": "kalib-0.21.1.tar.gz",
"has_sig": false,
"md5_digest": "2bcd95aec02b281a24c0027b7c7db4ff",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 51123,
"upload_time": "2024-12-19T16:22:37",
"upload_time_iso_8601": "2024-12-19T16:22:37.719477Z",
"url": "https://files.pythonhosted.org/packages/ca/eb/e43e82da015b4a52864cc3ac4d2a90323dd4ad8735d978614c738cc9fb84/kalib-0.21.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-19 16:22:37",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "kalib"
}