Collection of lower-level utilities that enhance code compatibility and validation.
Project description
Motivation
While developing Python software for Visual Effects pipelines, I found myself having to write the same boiler-plate code over and over again, as well as struggling with compatibility issues and feature gaps between Python 2.7 and Python 3.7+.
So I decided to implement solutions for those issues at the base, and basicco was born.
Overview
Basicco provides a collection of lower-level Utilities that enhance code readability and validation.
Utilities
caller_module
Retrieve the caller’s module name.
>>> from basicco.caller_module import caller_module
>>> def do_something():
... return "I was called by {}".format(caller_module())
...
>>> do_something()
'I was called by __main__'
custom_repr
Custom representation functions.
>>> from basicco.custom_repr import mapping_repr
>>> dct = {"a": 1, "b": 2}
>>> mapping_repr(dct, prefix="<", suffix=">", template="{key}={value}", sorting=True)
"<'a'=1, 'b'=2>"
>>> from basicco.custom_repr import iterable_repr
>>> tup = ("a", "b", "c", 1, 2, 3)
>>> iterable_repr(tup, prefix="<", suffix=">", value_repr=str)
'<a, b, c, 1, 2, 3>'
explicit_hash
Metaclass that forces __hash__ to be declared when __eq__ is declared.
>>> import six
>>> from basicco.explicit_hash import ExplicitHashMeta
>>> class Asset(six.with_metaclass(ExplicitHashMeta, object)):
... def __eq__(self, other):
... pass
...
Traceback (most recent call last):
TypeError: declared '__eq__' in 'Asset' but didn't declare '__hash__'
fabricate_value
Run a value through a callable factory (or None).
>>> from basicco.fabricate_value import fabricate_value
>>> fabricate_value(None, 3)
3
>>> fabricate_value(str, 3)
'3'
>>> fabricate_value("str", 3) # use an import path
'3'
import_path
Generate importable dot paths and import from them.
>>> import itertools
>>> from basicco.import_path import get_path, import_path
>>> get_path(itertools.chain)
'itertools.chain'
>>> import_path("itertools.chain")
<... 'itertools.chain'>
>>> from basicco.import_path import extract_generic_paths
>>> extract_generic_paths("Tuple[int, str]")
('Tuple', ('int', 'str'))
mangling
Functions to mangle/unmangle/extract private names.
>>> from basicco.mangling import mangle, unmangle, extract
>>> mangle("__member", "Foo")
'_Foo__member'
>>> unmangle("_Foo__member", "Foo")
'__member'
>>> extract("_Foo__member")
('__member', 'Foo')
mapping_proxy
Mapping Proxy type (read-only) for older Python versions.
>>> from basicco.mapping_proxy import MappingProxyType
>>> internal_dict = {"foo": "bar"}
>>> proxy_dict = MappingProxyType(internal_dict)
>>> proxy_dict["foo"]
'bar'
namespace
Wraps a dictionary/mapping and provides attribute-style access to it.
>>> from basicco.namespace import Namespace
>>> ns = Namespace({"bar": "foo"})
>>> ns.bar
'foo'
>>> from basicco.namespace import MutableNamespace
>>> ns = MutableNamespace({"bar": "foo"})
>>> ns.foo = "bar"
>>> ns.foo
'bar'
>>> ns.bar
'foo'
Also provides a NamespacedMeta metaclass for adding a __namespace__ private property that is unique to each class.
>>> from six import with_metaclass
>>> from basicco.namespace import NamespacedMeta
>>> class Asset(with_metaclass(NamespacedMeta, object)):
... pass
...
>>> Asset.__namespace__.foo = "bar"
qualname
Python 2.7 compatible way of getting the qualified name. Inspired by wbolster/qualname.
recursive_repr
Decorator that prevents infinite recursion for __repr__ methods.
>>> from basicco.recursive_repr import recursive_repr
>>> class MyClass(object):
...
... @recursive_repr
... def __repr__(self):
... return "MyClass<{!r}>".format(self)
...
>>> my_obj = MyClass()
>>> repr(my_obj)
'MyClass<...>'
runtime_final
Runtime-checked version of the typing.final decorator.
Can be used on methods, properties, classmethods, staticmethods, and classes that have FinalizedMeta as a metaclass. It is also recognized by static type checkers and prevents subclassing and/or member overriding during runtime:
>>> import six
>>> from basicco.runtime_final import FinalizedMeta, final
>>> @final
... class Asset(six.with_metaclass(FinalizedMeta, object)):
... pass
...
>>> class SubAsset(Asset):
... pass
...
Traceback (most recent call last):
TypeError: can't subclass final class 'Asset'
>>> import six
>>> from basicco.runtime_final import FinalizedMeta, final
>>> class Asset(six.with_metaclass(FinalizedMeta, object)):
... @final
... def method(self):
... pass
...
>>> class SubAsset(Asset):
... def method(self):
... pass
Traceback (most recent call last):
TypeError: can't override final member 'method'
>>> import six
>>> from basicco.runtime_final import FinalizedMeta, final
>>> class Asset(six.with_metaclass(FinalizedMeta, object)):
... @property
... @final
... def prop(self):
... pass
...
>>> class SubAsset(Asset):
... @property
... def prop(self):
... pass
Traceback (most recent call last):
TypeError: can't override final member 'prop'
scrape_class
Scrape a class and get a dictionary with filtered named members. This will respect the MRO (supports multiple inheritance).
>>> from basicco.scrape_class import scrape_class
>>> class Field(object):
... pass
...
>>> class Asset(object):
... name = Field()
... version = Field()
...
>>> class SubAsset(Asset):
... sub_name = Field()
...
>>> def field_filter(base, member_name, member):
... return isinstance(member, Field)
>>> sorted(scrape_class(SubAsset, field_filter))
['name', 'sub_name', 'version']
type_checking
Runtime type checking with support for import paths and type hints.
>>> from typing import Mapping
>>> from itertools import chain
>>> from basicco.type_checking import is_instance
>>> class SubChain(chain):
... pass
...
>>> is_instance(3, int)
True
>>> is_instance(3, (chain, int))
True
>>> is_instance(3, ())
False
>>> is_instance(SubChain(), "itertools.chain")
True
>>> is_instance(chain(), "itertools.chain", subtypes=False)
True
>>> is_instance(SubChain(), "itertools.chain", subtypes=False)
False
>>> is_instance({"a": 1, "b": 2}, Mapping[str, int])
True
unique_iterator
Iterator that yields unique values.
>>> from basicco.unique_iterator import unique_iterator
>>> list(unique_iterator([1, 2, 3, 3, 4, 4, 5]))
[1, 2, 3, 4, 5]
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
Hashes for basicco-6.1.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2d3b526e7d19ae6731996b4812beb439dfae203240a77bf4894e8b4625f76491 |
|
MD5 | 3615b966520ae13adb4d3495aeec719a |
|
BLAKE2b-256 | e74d812afe73f75f88924409b1cebe0ecbd1a2b2436430a852e7d4cfe704039f |