aspect oriented programming helper
Project description
# Concerns
[Python](https://www.python.org/) implementation of the
[Ruby](https://www.ruby-lang.org/)’s
[ActiveSupport::Concern](https://api.rubyonrails.org/v5.1/classes/ActiveSupport/Concern.html)
behavior.
## Use examples
Note: the class context is the fourth argument of the
[metaclass](https://www.python.org/doc/essays/metaclasses/) `__init__` method,
formally “namespace”:
```python
def __init__(cls, name: str, bases: tuple, namespace: dict) -> None:
...
```
It is a dictionary representation of the class body.
### Using a class as mix-in
If the aspect is a class, its context will be merged to the target context on
its factoring.
```python
from typing import NamedTuple
from concerns import concern
class SerialMixin:
def serialize(self) -> str:
return json.dumps(self._asdict(), sort_keys=True)
@classmethod
def deserialize(cls, data: str):
return cls(**json.loads(data))
class PersonBase(NamedTuple):
name: str
surname: str
class Person(PersonBase):
concern(SerialMixin)
```
### Using a mapping as default values map
If the aspect is a mapping (a dictionary, by example), it itself will be merged
to the target context on its factoring.
```python
from concerns import concern
class Animal:
# Too simple use, avoid doing it
concern({voice='grrr'})
def __init__(self, *, voice: str = None):
if voice:
self.voice = voice
def say(self) -> None:
print(self.voice)
```
### Function to change behavior
If the aspect is a callable, the target class context will be passed as
parameter to the aspect for processing before its factoring.
```python
from concerns import concern
from collections.abc import MutableMapping
from datetime import datetime
def make_timed(context: MutableMapping) -> None:
"""
Reusable aspect function to add creating time to objects
"""
def set_created_attr(attr: str) -> None:
context[attr] = None
def new(cls, name: str, bases: tuple, _dict: dict):
self = super().__new__(cls, name, bases, _dict)
setattr(self, attr) = datetime.now()
return self
context['__new__'] = new
context['set_created_attr'] = set_created_attr
class Register:
concern(make_timed)
... # more class attributes
set_created_attr('created_at')
```
[Python](https://www.python.org/) implementation of the
[Ruby](https://www.ruby-lang.org/)’s
[ActiveSupport::Concern](https://api.rubyonrails.org/v5.1/classes/ActiveSupport/Concern.html)
behavior.
## Use examples
Note: the class context is the fourth argument of the
[metaclass](https://www.python.org/doc/essays/metaclasses/) `__init__` method,
formally “namespace”:
```python
def __init__(cls, name: str, bases: tuple, namespace: dict) -> None:
...
```
It is a dictionary representation of the class body.
### Using a class as mix-in
If the aspect is a class, its context will be merged to the target context on
its factoring.
```python
from typing import NamedTuple
from concerns import concern
class SerialMixin:
def serialize(self) -> str:
return json.dumps(self._asdict(), sort_keys=True)
@classmethod
def deserialize(cls, data: str):
return cls(**json.loads(data))
class PersonBase(NamedTuple):
name: str
surname: str
class Person(PersonBase):
concern(SerialMixin)
```
### Using a mapping as default values map
If the aspect is a mapping (a dictionary, by example), it itself will be merged
to the target context on its factoring.
```python
from concerns import concern
class Animal:
# Too simple use, avoid doing it
concern({voice='grrr'})
def __init__(self, *, voice: str = None):
if voice:
self.voice = voice
def say(self) -> None:
print(self.voice)
```
### Function to change behavior
If the aspect is a callable, the target class context will be passed as
parameter to the aspect for processing before its factoring.
```python
from concerns import concern
from collections.abc import MutableMapping
from datetime import datetime
def make_timed(context: MutableMapping) -> None:
"""
Reusable aspect function to add creating time to objects
"""
def set_created_attr(attr: str) -> None:
context[attr] = None
def new(cls, name: str, bases: tuple, _dict: dict):
self = super().__new__(cls, name, bases, _dict)
setattr(self, attr) = datetime.now()
return self
context['__new__'] = new
context['set_created_attr'] = set_created_attr
class Register:
concern(make_timed)
... # more class attributes
set_created_attr('created_at')
```
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.
Built Distribution
concerns-1.0-py3-none-any.whl
(2.1 kB
view hashes)