Mousse
Collections of my most used functions, classes and patterns. I was craving for a delicious mousse as I was comming up with the name.
Installation
pip install -U mousse
Components
Dataclass
This is a self-implement, minimal version of pydantic, with some minor changes.
from typing import *
from mousse import Dataclass, asdict, asclass, Field
class Foo(Dataclass):
name: str
number: float
items: List[str] = []
class Bar(Dataclass):
foo: Foo
index: int = Field(..., alias="id")
foo = Foo(
name="foo",
number=42.0,
items=["banana", "egg"]
)
bar = Bar(id=1, foo=foo)
print(bar.foo)
bar_dict = asdict(bar)
print(bar_dict)
bar = asclass(Bar, bar_dict)
print(bar)
bar = asclass(Bar, path="bar.json")
print(bar)
Some helper functions are:
validate
: Check data type of variable
from typing import *
from mousse import validate, Dataclass
class Foo(Dataclass):
name: str
number: float
items: List[str] = []
Number = Union[int, float]
validate(int, 1)
validate(int, 1.0)
validate(Number, 1)
validate(Number, 1.0)
validate(Dict[str, Any], {
"a": 1,
"b": "a"
})
validate(Dict[str, int], {
"a": 1,
"b": "a"
})
validate(Tuple[int, float], (1, 1.2))
validate(Tuple[int, float], (1.0, 1.2))
validate(Tuple[Number, Number], (1, 1.2))
foo = Foo(
name="foo",
number=42.0,
items=["banana", "egg"]
)
validate(Foo, foo)
validate(List[Foo], [foo])
validate(List[Foo], (foo,))
validate(Sequence[Foo], (foo,))
parse
: Attempt to parse data
from typing import *
from mousse import parse, Dataclass
class Foo(Dataclass):
name: str
number: float
items: List[str] = []
parse(float, 1)
parse(Union[int, float], 1)
parse(Union[float, int], 1)
parse(Dict[str, Any], {
1: 2,
2: 3
})
parse(Dict[str, float], {
1: 2,
2: 3
})
parse(Foo, {
"name": "foo",
"number": 42.2,
"items": [1, 2, 3]
})
Config
This is how I manage the configuration of my application. By creating a Config object that can be loaded once and refered everywhere. Of course, by default, the Config object cannot be changed by convention means. A changing config during runtime is evil.
from mousse import load_config
load_config(
"foo",
path="config.yaml"
)
from typing import *
from mousse import get_config, asdict, asclass, Dataclass
config = get_config("foo")
print(config)
print(config)
print(config.foo)
print(config.foo.items[0].price)
config.foo = "bar"
config_data = asdict(config)
print(config_data)
class Item(Dataclass):
name: str
price: int
class Foo(Dataclass):
name: str
number: float
items: List[Item]
class Bar(Dataclass):
foo: Foo
id: int
bar = asclass(Bar, config)
print(bar)
Logger
This module is for managing logging process, with pre-defined logging format and both file logging and stdout logging.
from mousse import get_logger
logger = get_logger(
"foo",
)
logger.add_handler("RotatingFileHandler", path="logs/foo.out")
from mousse import get_logger
logger = get_logger("foo")
logger.info("This is", "my", "logger number:", 1)
The format of the log is:
[{date} {time}] [{process_id} {thread_id}] [{level}] [{file}:{caller}:{lineno}] {msg}
Pattern
A collection of my most used design patterns
Registry pattern
from mousse import Registry
pokedex = Registry()
class Pokemon:
def __init__(self, name:str):
self.name = name
from .registry import pokedex, Pokemon
@pokedex.register
class Pikachu(Pokemon):
def sound(self):
return "pika pika chu"
@pokedex.register
class Charmander(Pokemon):
def sound(self):
return "charman charman der"
from .registry import pokedex, Pokemon
@pokedex.register
class Chikorita(Pokemon):
def sound(self):
return "chiko chiko"
from . import kanto, johto
from .registry import pokedex
pikachu = pokedex("Pikachu", "1st")
print(pikachu.name, pikachu.sound())
charmander = pokedex("Charmander", "2nd")
print(charmander.name, charmander.sound())
chikorita = pokedex("Chikorita", "3rd")
print(chikorita.name, chikorita.sound())