Skip to content

Commit 7e1513e

Browse files
committed
test(enums): fix doctests (#1267)
1 parent 67f14dc commit 7e1513e

File tree

14 files changed

+1228
-366
lines changed

14 files changed

+1228
-366
lines changed
Lines changed: 94 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,94 @@
1-
# Transitional imports to ensure non-breaking changes.
2-
# Could be deprecated in the next major release.
3-
#
4-
# How imports are being used today:
5-
#
6-
# >>> from openfisca_core.module import symbol
7-
#
8-
# The previous example provokes cyclic dependency problems
9-
# that prevent us from modularizing the different components
10-
# of the library so to make them easier to test and to maintain.
11-
#
12-
# How could them be used after the next major release:
13-
#
14-
# >>> from openfisca_core import module
15-
# >>> module.symbol()
16-
#
17-
# And for classes:
18-
#
19-
# >>> from openfisca_core import module
20-
# >>> module.Symbol()
21-
#
22-
# See: https://www.python.org/dev/peps/pep-0008/#imports
23-
24-
from . import types
25-
from .entity import Entity
26-
from .group_entity import GroupEntity
27-
from .helpers import build_entity, find_role
28-
from .role import Role
29-
30-
SingleEntity = Entity
31-
32-
__all__ = [
33-
"Entity",
34-
"SingleEntity",
35-
"GroupEntity",
36-
"Role",
37-
"build_entity",
38-
"find_role",
39-
"types",
40-
]
1+
"""Provides a way of representing the entities of a rule system.
2+
3+
Each rule system is comprised by legislation and regulations to be applied upon
4+
"someone". In legal and economical terms, "someone" is referred to as people:
5+
individuals, families, tax households, companies, and so on.
6+
7+
People can be either human or non-human, that is a legal entity, also referred
8+
to as a legal person. Human or non-human, a person is an atomic element of a
9+
rule system: for example, in most legislations, a salary is invariably owed
10+
to an indivual, and payroll taxes by a company, as a juridical person. In
11+
OpenFisca, that atomic element is represented as an :class:`.Entity`.
12+
13+
In other cases, legal and regulatory rules are defined for groups or clusters
14+
of people: for example, income tax is usually due by a tax household, that is
15+
a group of individuals. There may also be fiduciary entities where the members,
16+
legal entities, are collectively liable for a property tax. In OpenFisca, those
17+
cluster elements are represented as a :class:`.GroupEntity`.
18+
19+
In the latter case, the atomic members of a given group may have a different
20+
:class:`Role` in the context of a specific rule: for example, income tax
21+
is due, in some legislations, by a tax household, where we find different
22+
roles as the declarant, the spouse, the children, and so on…
23+
24+
What's important is that each rule, or in OpenFisca, a :class:`.Variable`,
25+
is defined either for an :class:`.Entity` or for a :class:`.GroupEntity`,
26+
and in the latter case, the way the rule is going to be applied depends
27+
on the attributes and roles of the members of the group.
28+
29+
Finally, there is a distiction to be made between the "abstract" entities
30+
described by in a rule system, for example an individual, as in "any"
31+
individual, and an actual individual, like Mauko, Andrea, Mehdi, Seiko,
32+
or José.
33+
34+
This module provides tools for modelling the former. For the actual
35+
"simulation" or "application" of any given :class:`.Variable` to a
36+
concrete individual or group of individuals, see :class:`.Population`
37+
and :class:`.GroupPopulation`.
38+
39+
Official Public API:
40+
* :class:`.Entity`
41+
* :class:`.GroupEntity`
42+
* :class:`.Role`
43+
* :func:`.build_entity`
44+
* :func:`.check_role_validity`
45+
46+
Deprecated:
47+
* :meth:`.Entity.set_tax_benefit_system`
48+
* :meth:`.Entity.get_variable`
49+
* :meth:`.Entity.check_variable_defined_for_entity`
50+
* :meth:`.Entity.check_role_validity`
51+
52+
Note:
53+
The ``deprecated`` features are kept so as to give time to users to
54+
migrate, and could be definitely removed from the codebase in a future
55+
major release.
56+
57+
Note:
58+
How imports are being used today::
59+
60+
from openfisca_core.entities import * # Bad
61+
from openfisca_core.entities.helpers import build_entity # Bad
62+
from openfisca_core.entities.role import Role # Bad
63+
64+
The previous examples provoke cyclic dependency problems, that prevents us
65+
from modularizing the different components of the library, so as to make
66+
them easier to test and to maintain.
67+
68+
How could them be used after the next major release::
69+
70+
from openfisca_core import entities
71+
from openfisca_core.entities import Role
72+
73+
Role() # Good: import classes as publicly exposed
74+
entities.build_entity() # Good: use functions as publicly exposed
75+
76+
.. seealso:: `PEP8#Imports`_ and `OpenFisca's Styleguide`_.
77+
78+
.. _PEP8#Imports:
79+
https://www.python.org/dev/peps/pep-0008/#imports
80+
81+
.. _OpenFisca's Styleguide:
82+
https://github.com/openfisca/openfisca-core/blob/master/STYLEGUIDE.md
83+
84+
"""
85+
86+
# Official Public API
87+
88+
from .entity import Entity # noqa: F401
89+
from .group_entity import GroupEntity # noqa: F401
90+
from .helpers import build_entity, check_role_validity # noqa: F401
91+
from .role import Role # noqa: F401
92+
93+
__all__ = ["Entity", "GroupEntity", "Role"]
94+
__all__ = ["build_entity", "check_role_validity", *__all__]
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from __future__ import annotations
2+
3+
from typing import Iterable, Optional, Sequence, Type
4+
5+
from openfisca_core.types import HasPlural, RoleLike, SupportsRole
6+
7+
import dataclasses
8+
9+
10+
@dataclasses.dataclass(frozen=True)
11+
class RoleBuilder:
12+
"""Builds roles & sub-roles from a given input.
13+
14+
Attributes:
15+
builder (:obj:`.Entity` or :obj:`.GroupEntity`):
16+
A builder object.
17+
buildee (:obj:`.Role`):
18+
The objects to be built.
19+
20+
Args:
21+
builder: A builder object.
22+
buildee: The objects to be built.
23+
24+
Examples:
25+
>>> from openfisca_core.entities import GroupEntity, Role
26+
27+
>>> group_entity = GroupEntity(
28+
... "household",
29+
... "households",
30+
... "A household",
31+
... "All the people who live together in the same place.",
32+
... []
33+
... )
34+
35+
>>> items = [{
36+
... "key": "parent",
37+
... "subroles": ["first_parent", "second_parent"],
38+
... }]
39+
40+
>>> builder = RoleBuilder(group_entity, Role)
41+
42+
>>> repr(RoleBuilder)
43+
"<class 'openfisca_core.entities._role_builder.RoleBuilder'>"
44+
45+
>>> repr(builder)
46+
"<RoleBuilder(households, <class '...Role'>)>"
47+
48+
>>> str(builder)
49+
"<RoleBuilder(households, <class '...Role'>)>"
50+
51+
>>> builder(items)
52+
(<Role(parent)>,)
53+
54+
.. versionadded:: 35.7.0
55+
56+
"""
57+
58+
__slots__ = ["builder", "buildee"]
59+
builder: HasPlural
60+
buildee: Type[SupportsRole]
61+
62+
def __repr__(self) -> str:
63+
return f"<{self.__class__.__name__}({self.builder}, {self.buildee})>"
64+
65+
def __call__(self, items: Iterable[RoleLike]) -> Sequence[SupportsRole]:
66+
"""Builds a sub/role for each item in ``items``.
67+
68+
Args:
69+
items: Role-like items, see :class:`.RoleLike`.
70+
71+
Returns:
72+
A :obj:`list` of :obj:`.Role`.
73+
74+
.. versionadded:: 35.7.0
75+
76+
"""
77+
78+
return tuple(self.build(item) for item in items)
79+
80+
def build(self, item: RoleLike) -> SupportsRole:
81+
"""Builds a role from ``item``.
82+
83+
Args:
84+
item: A role-like item, see :class:`.RoleLike`.
85+
86+
Returns:
87+
:obj:`.Role`: A :obj:`.Role`.
88+
89+
.. versionadded:: 35.7.0
90+
91+
"""
92+
93+
role: SupportsRole
94+
subroles: Optional[Iterable[str]]
95+
96+
role = self.buildee(item, self.builder)
97+
subroles = item.get("subroles", [])
98+
99+
if subroles:
100+
role.subroles = [
101+
self.build(RoleLike({"key": key, "max": 1})) for key in subroles
102+
]
103+
role.max = len(role.subroles)
104+
105+
return role

0 commit comments

Comments
 (0)