Various bugfixing and improvements for the Python backend

This commit is contained in:
Denis Merigoux 2021-06-25 00:16:21 +02:00
parent 3f5027e5a5
commit e38dc4c728
No known key found for this signature in database
GPG Key ID: EE99DCFA365C3EE3
13 changed files with 404 additions and 129 deletions

View File

@ -186,20 +186,17 @@ FRENCH_LAW_OCAML_LIB_DIR=french_law/ocaml
FRENCH_LAW_JS_LIB_DIR=french_law/js
FRENCH_LAW_PYTHON_LIB_DIR=french_law/python
$(FRENCH_LAW_PYTHON_LIB_DIR)/allocations_familiales.py: .FORCE
$(FRENCH_LAW_PYTHON_LIB_DIR)/src/allocations_familiales.py: .FORCE
CATALA_OPTS="$(CATALA_OPTS) -O -t" $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) allocations_familiales.py
cp -f $(ALLOCATIONS_FAMILIALES_DIR)/allocations_familiales.py \
$(FRENCH_LAW_PYTHON_LIB_DIR)/
cp -f $(ALLOCATIONS_FAMILIALES_DIR)/allocations_familiales.py $@
$(FRENCH_LAW_OCAML_LIB_DIR)/law_source/allocations_familiales.ml: .FORCE
CATALA_OPTS="$(CATALA_OPTS) -O -t" $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) allocations_familiales.ml
cp -f $(ALLOCATIONS_FAMILIALES_DIR)/allocations_familiales.ml \
$(FRENCH_LAW_OCAML_LIB_DIR)/law_source
cp -f $(ALLOCATIONS_FAMILIALES_DIR)/allocations_familiales.ml $@
$(FRENCH_LAW_OCAML_LIB_DIR)/law_source/unit_tests/tests_allocations_familiales.ml: .FORCE
CATALA_OPTS="$(CATALA_OPTS) -O -t" $(MAKE) -s -C $(ALLOCATIONS_FAMILIALES_DIR) tests/tests_allocations_familiales.ml
cp -f $(ALLOCATIONS_FAMILIALES_DIR)/tests/tests_allocations_familiales.ml \
$(FRENCH_LAW_OCAML_LIB_DIR)/law_source/unit_tests/
cp -f $(ALLOCATIONS_FAMILIALES_DIR)/tests/tests_allocations_familiales.ml $@
#> generate_french_law_library_ocaml : Generates the French law library OCaml sources from Catala
generate_french_law_library_ocaml:\
@ -227,7 +224,7 @@ build_french_law_library_js: generate_french_law_library_ocaml format
#> generate_french_law_library_python : Generates the French law library Python sources from Catala
generate_french_law_library_python:\
$(FRENCH_LAW_PYTHON_LIB_DIR)/allocations_familiales.py
$(FRENCH_LAW_PYTHON_LIB_DIR)/src/allocations_familiales.py
. $(FRENCH_LAW_PYTHON_LIB_DIR)/env/bin/activate ;\
$(MAKE) -C $(FRENCH_LAW_PYTHON_LIB_DIR) format

View File

@ -299,11 +299,21 @@ and format_block (ctx : Dcalc.Ast.decl_ctx) (fmt : Format.formatter) (b : block)
let format_ctx (type_ordering : Scopelang.Dependency.TVertex.t list) (fmt : Format.formatter)
(ctx : D.decl_ctx) : unit =
let format_struct_decl fmt (struct_name, struct_fields) =
if List.length struct_fields = 0 then
Format.fprintf fmt "class %a(Unit):@\n\tpass@\n@\n" format_struct_name struct_name
if List.length struct_fields = 0 then failwith "no fields in the struct"
else
Format.fprintf fmt "class %a:@\n\tdef __init__(self, %a) -> None:@\n%a@\n@\n"
format_struct_name struct_name
Format.fprintf fmt
"class %a:@\n\
\tdef __init__(self, %a) -> None:@\n\
%a@\n\
@\n\
\tdef __eq__(self, other: object) -> bool:@\n\
\t\tif isinstance(other, %a):@\n\
\t\t\treturn @[<hov>(%a)@]@\n\
\t\telse:@\n\
\t\t\treturn False@\n\
@\n\
\tdef __ne__(self, other: object) -> bool:@\n\
\t\treturn not (self == other)" format_struct_name struct_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ", ")
(fun _fmt (struct_field, struct_field_type) ->
@ -315,6 +325,12 @@ let format_ctx (type_ordering : Scopelang.Dependency.TVertex.t list) (fmt : Form
(fun _fmt (struct_field, _) ->
Format.fprintf fmt "\t\tself.%a = %a" format_struct_field_name struct_field
format_struct_field_name struct_field))
struct_fields format_struct_name struct_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt " and@ ")
(fun _fmt (struct_field, _) ->
Format.fprintf fmt "self.%a == other.%a" format_struct_field_name struct_field
format_struct_field_name struct_field))
struct_fields
in
let format_enum_decl fmt (enum_name, enum_cons) =
@ -327,13 +343,24 @@ let format_ctx (type_ordering : Scopelang.Dependency.TVertex.t list) (fmt : Form
class %a:@\n\
\tdef __init__(self, code: %a_Code, value: Any) -> None:@\n\
\t\tself.code = code@\n\
\t\tself.value = value" format_enum_name enum_name
\t\tself.value = value@\n\
@\n\
@\n\
\tdef __eq__(self, other: object) -> bool:@\n\
\t\tif isinstance(other, %a):@\n\
\t\t\treturn self.code == other.code and self.value == other.value@\n\
\t\telse:@\n\
\t\t\treturn False@\n\
@\n\
@\n\
\tdef __ne__(self, other: object) -> bool:@\n\
\t\treturn not (self == other)" format_enum_name enum_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
(fun _fmt (i, enum_cons, enum_cons_type) ->
Format.fprintf fmt "%a = %d" format_enum_cons_name enum_cons i))
(List.mapi (fun i (x, y) -> (i, x, y)) enum_cons)
format_enum_name enum_name format_enum_name enum_name
format_enum_name enum_name format_enum_name enum_name format_enum_name enum_name
in
let is_in_type_ordering s =
@ -367,7 +394,7 @@ let format_program (fmt : Format.formatter) (p : Ast.program)
Format.fprintf fmt
"# This file has been generated by the Catala compiler, do not edit!\n\
@\n\
from .catala_runtime import *@\n\
from .catala import *@\n\
from typing import Any, List, Callable, Tuple\n\
from enum import Enum\n\
@\n\

View File

@ -1,6 +1,3 @@
env/
.mypy_cache/
_static/
_templates/
doc/
**/__pycache__

View File

@ -1,4 +1,4 @@
SOURCES=catala_runtime.py allocations_familiales.py
SOURCES=src/catala.py src/allocations_familiales.py main.py
dependencies:
pip install -r dependencies.txt
@ -7,9 +7,4 @@ type:
mypy $(SOURCES)
format:
autopep8 --in-place $(SOURCES)
doc:
mkdir -p doc
sphinx-build ./ doc
ln -sf doc/index.html doc.html
autopep8 --in-place $(SOURCES)

View File

@ -1,7 +0,0 @@
catala\_runtime module
======================
.. automodule:: catala_runtime
:members:
:undoc-members:
:show-inheritance:

View File

@ -1,58 +0,0 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'French law'
copyright = '2021, Denis Merigoux'
author = 'Denis Merigoux'
# The full version, including alpha/beta/rc tags
release = '0.4.0'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc'
]
# Add any paths that contain templates here, relative to this directory.
# templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'doc', 'env']
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ['_static']
autodoc_member_order = 'bysource'

View File

@ -3,5 +3,4 @@ typing
mypy
python-dateutil
types-python-dateutil
sphinx
autopep8

View File

@ -1,26 +0,0 @@
.. French law documentation master file, created by
sphinx-quickstart on Mon Jun 21 16:33:54 2021.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to French law's documentation!
======================================
.. toctree::
:maxdepth: 2
:caption: Contents:
modules
=======
.. toctree::
:maxdepth: 2
modules
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

34
french_law/python/main.py Executable file
View File

@ -0,0 +1,34 @@
#!python3
from src.catala import date_of_numbers, Unit, integer_of_int, money_of_units_int, no_input
from src.allocations_familiales import interface_allocations_familiales, InterfaceAllocationsFamilialesIn, EnfantEntree, PriseEnCharge, PriseEnCharge_Code, Collectivite, Collectivite_Code
def main():
print(interface_allocations_familiales(
InterfaceAllocationsFamilialesIn(
date_courante_in=lambda _: date_of_numbers(2020, 4, 20),
enfants_in=lambda _: [
EnfantEntree(d_identifiant=integer_of_int(0), d_remuneration_mensuelle=integer_of_int(0),
d_date_de_naissance=date_of_numbers(2003, 2, 2),
d_prise_en_charge=PriseEnCharge(
PriseEnCharge_Code.EffectiveEtPermanente, Unit()),
d_a_deja_ouvert_droit_aux_allocations_familiales=True),
EnfantEntree(d_identifiant=integer_of_int(1), d_remuneration_mensuelle=integer_of_int(300),
d_date_de_naissance=date_of_numbers(2013, 9, 30),
d_prise_en_charge=PriseEnCharge(
PriseEnCharge_Code.GardeAlterneePartageAllocations, Unit()),
d_a_deja_ouvert_droit_aux_allocations_familiales=True)
],
ressources_menage_in=lambda _: money_of_units_int(30000),
residence_in=lambda _: Collectivite(
Collectivite_Code.Metropole, Unit()),
personne_charge_effective_permanente_est_parent_in=lambda _: True,
personne_charge_effective_permanente_remplit_titre_I_in=lambda _: True,
enfants_a_charge_in=no_input(),
montant_verse_in=no_input()
)))
if __name__ == '__main__':
main()

View File

@ -1,4 +0,0 @@
.. toctree::
:maxdepth: 4
catala_runtime

View File

@ -1,6 +1,6 @@
# This file has been generated by the Catala compiler, do not edit!
from .catala_runtime import *
from .catala import *
from typing import Any, List, Callable, Tuple
from enum import Enum
@ -18,6 +18,15 @@ class PriseEnCharge:
self.code = code
self.value = value
def __eq__(self, other: object) -> bool:
if isinstance(other, PriseEnCharge):
return self.code == other.code and self.value == other.value
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class SituationObligationScolaire_Code(Enum):
Avant = 0
@ -30,6 +39,15 @@ class SituationObligationScolaire:
self.code = code
self.value = value
def __eq__(self, other: object) -> bool:
if isinstance(other, SituationObligationScolaire):
return self.code == other.code and self.value == other.value
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class Collectivite_Code(Enum):
Guadeloupe = 0
@ -48,6 +66,15 @@ class Collectivite:
self.code = code
self.value = value
def __eq__(self, other: object) -> bool:
if isinstance(other, Collectivite):
return self.code == other.code and self.value == other.value
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class PriseEnCompte_Code(Enum):
Complete = 0
@ -60,6 +87,15 @@ class PriseEnCompte:
self.code = code
self.value = value
def __eq__(self, other: object) -> bool:
if isinstance(other, PriseEnCompte):
return self.code == other.code and self.value == other.value
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class VersementAllocations_Code(Enum):
Normal = 0
@ -71,6 +107,15 @@ class VersementAllocations:
self.code = code
self.value = value
def __eq__(self, other: object) -> bool:
if isinstance(other, VersementAllocations):
return self.code == other.code and self.value == other.value
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class ElementPrestationsFamiliales_Code(Enum):
PrestationAccueilJeuneEnfant = 0
@ -88,6 +133,15 @@ class ElementPrestationsFamiliales:
self.code = code
self.value = value
def __eq__(self, other: object) -> bool:
if isinstance(other, ElementPrestationsFamiliales):
return self.code == other.code and self.value == other.value
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class EnfantEntree:
def __init__(self, d_identifiant: Integer, d_remuneration_mensuelle: Money, d_date_de_naissance: Date, d_prise_en_charge: PriseEnCharge, d_a_deja_ouvert_droit_aux_allocations_familiales: bool) -> None:
@ -97,6 +151,19 @@ class EnfantEntree:
self.d_prise_en_charge = d_prise_en_charge
self.d_a_deja_ouvert_droit_aux_allocations_familiales = d_a_deja_ouvert_droit_aux_allocations_familiales
def __eq__(self, other: object) -> bool:
if isinstance(other, EnfantEntree):
return (self.d_identifiant == other.d_identifiant and
self.d_remuneration_mensuelle == other.d_remuneration_mensuelle and
self.d_date_de_naissance == other.d_date_de_naissance and
self.d_prise_en_charge == other.d_prise_en_charge and
self.d_a_deja_ouvert_droit_aux_allocations_familiales == other.d_a_deja_ouvert_droit_aux_allocations_familiales)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class Enfant:
def __init__(self, identifiant: Integer, obligation_scolaire: SituationObligationScolaire, remuneration_mensuelle: Money, date_de_naissance: Date, age: Integer, prise_en_charge: PriseEnCharge, a_deja_ouvert_droit_aux_allocations_familiales: bool) -> None:
@ -108,6 +175,21 @@ class Enfant:
self.prise_en_charge = prise_en_charge
self.a_deja_ouvert_droit_aux_allocations_familiales = a_deja_ouvert_droit_aux_allocations_familiales
def __eq__(self, other: object) -> bool:
if isinstance(other, Enfant):
return (self.identifiant == other.identifiant and
self.obligation_scolaire == other.obligation_scolaire and
self.remuneration_mensuelle == other.remuneration_mensuelle and
self.date_de_naissance == other.date_de_naissance and
self.age == other.age and
self.prise_en_charge == other.prise_en_charge and
self.a_deja_ouvert_droit_aux_allocations_familiales == other.a_deja_ouvert_droit_aux_allocations_familiales)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class SmicOut:
def __init__(self, date_courante_out: Date, residence_out: Collectivite, brut_horaire_out: Money) -> None:
@ -115,6 +197,17 @@ class SmicOut:
self.residence_out = residence_out
self.brut_horaire_out = brut_horaire_out
def __eq__(self, other: object) -> bool:
if isinstance(other, SmicOut):
return (self.date_courante_out == other.date_courante_out and
self.residence_out == other.residence_out and
self.brut_horaire_out == other.brut_horaire_out)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class SmicIn:
def __init__(self, date_courante_in: Callable[[Unit], Date], residence_in: Callable[[Unit], Collectivite], brut_horaire_in: Callable[[Unit], Money]) -> None:
@ -122,6 +215,17 @@ class SmicIn:
self.residence_in = residence_in
self.brut_horaire_in = brut_horaire_in
def __eq__(self, other: object) -> bool:
if isinstance(other, SmicIn):
return (self.date_courante_in == other.date_courante_in and
self.residence_in == other.residence_in and
self.brut_horaire_in == other.brut_horaire_in)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class PrestationsFamilialesOut:
def __init__(self, droit_ouvert_out: Callable[[Enfant], bool], conditions_hors_age_out: Callable[[Enfant], bool], plafond_l512_3_2_out: Money, age_l512_3_2_out: Integer, regime_outre_mer_l751_1_out: bool, date_courante_out: Date, prestation_courante_out: ElementPrestationsFamiliales, residence_out: Collectivite, base_mensuelle_out: Money) -> None:
@ -135,6 +239,23 @@ class PrestationsFamilialesOut:
self.residence_out = residence_out
self.base_mensuelle_out = base_mensuelle_out
def __eq__(self, other: object) -> bool:
if isinstance(other, PrestationsFamilialesOut):
return (self.droit_ouvert_out == other.droit_ouvert_out and
self.conditions_hors_age_out == other.conditions_hors_age_out and
self.plafond_l512_3_2_out == other.plafond_l512_3_2_out and
self.age_l512_3_2_out == other.age_l512_3_2_out and
self.regime_outre_mer_l751_1_out == other.regime_outre_mer_l751_1_out and
self.date_courante_out == other.date_courante_out and
self.prestation_courante_out == other.prestation_courante_out and
self.residence_out == other.residence_out and
self.base_mensuelle_out == other.base_mensuelle_out)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class PrestationsFamilialesIn:
def __init__(self, droit_ouvert_in: Callable[[Unit], (Callable[[Enfant], bool])], conditions_hors_age_in: Callable[[Unit], (Callable[[Enfant], bool])], plafond_l512_3_2_in: Callable[[Unit], Money], age_l512_3_2_in: Callable[[Unit], Integer], regime_outre_mer_l751_1_in: Callable[[Unit], bool], date_courante_in: Callable[[Unit], Date], prestation_courante_in: Callable[[Unit], ElementPrestationsFamiliales], residence_in: Callable[[Unit], Collectivite], base_mensuelle_in: Callable[[Unit], Money]) -> None:
@ -148,28 +269,83 @@ class PrestationsFamilialesIn:
self.residence_in = residence_in
self.base_mensuelle_in = base_mensuelle_in
def __eq__(self, other: object) -> bool:
if isinstance(other, PrestationsFamilialesIn):
return (self.droit_ouvert_in == other.droit_ouvert_in and
self.conditions_hors_age_in == other.conditions_hors_age_in and
self.plafond_l512_3_2_in == other.plafond_l512_3_2_in and
self.age_l512_3_2_in == other.age_l512_3_2_in and
self.regime_outre_mer_l751_1_in == other.regime_outre_mer_l751_1_in and
self.date_courante_in == other.date_courante_in and
self.prestation_courante_in == other.prestation_courante_in and
self.residence_in == other.residence_in and
self.base_mensuelle_in == other.base_mensuelle_in)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class AllocationFamilialesAvril2008Out:
def __init__(self, age_minimum_alinea_1_l521_3_out: Integer) -> None:
self.age_minimum_alinea_1_l521_3_out = age_minimum_alinea_1_l521_3_out
def __eq__(self, other: object) -> bool:
if isinstance(other, AllocationFamilialesAvril2008Out):
return (self.age_minimum_alinea_1_l521_3_out == other.age_minimum_alinea_1_l521_3_out)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class AllocationFamilialesAvril2008In:
def __init__(self, age_minimum_alinea_1_l521_3_in: Callable[[Unit], Integer]) -> None:
self.age_minimum_alinea_1_l521_3_in = age_minimum_alinea_1_l521_3_in
def __eq__(self, other: object) -> bool:
if isinstance(other, AllocationFamilialesAvril2008In):
return (self.age_minimum_alinea_1_l521_3_in == other.age_minimum_alinea_1_l521_3_in)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class EnfantLePlusAgeOut:
def __init__(self, enfants_out: List[Enfant], le_plus_age_out: Enfant) -> None:
self.enfants_out = enfants_out
self.le_plus_age_out = le_plus_age_out
def __eq__(self, other: object) -> bool:
if isinstance(other, EnfantLePlusAgeOut):
return (self.enfants_out == other.enfants_out and
self.le_plus_age_out == other.le_plus_age_out)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class EnfantLePlusAgeIn:
def __init__(self, enfants_in: Callable[[Unit], (List[Enfant])], le_plus_age_in: Callable[[Unit], Enfant]) -> None:
self.enfants_in = enfants_in
self.le_plus_age_in = le_plus_age_in
def __eq__(self, other: object) -> bool:
if isinstance(other, EnfantLePlusAgeIn):
return (self.enfants_in == other.enfants_in and
self.le_plus_age_in == other.le_plus_age_in)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class AllocationsFamilialesOut:
def __init__(self, personne_charge_effective_permanente_est_parent_out: bool, personne_charge_effective_permanente_remplit_titre_I_out: bool, ressources_menage_out: Money, residence_out: Collectivite, date_courante_out: Date, enfants_a_charge_out: List[Enfant], enfants_a_charge_droit_ouvert_prestation_familiale_out: List[Enfant], prise_en_compte_out: Callable[[Enfant], PriseEnCompte], versement_out: Callable[[Enfant], VersementAllocations], montant_verse_out: Money, droit_ouvert_base_out: bool, montant_initial_base_out: Money, montant_initial_base_premier_enfant_out: Money, montant_initial_base_deuxieme_enfant_out: Money, montant_initial_base_troisieme_enfant_et_plus_out: Money, rapport_enfants_total_moyen_out: Decimal, nombre_moyen_enfants_out: Decimal, nombre_total_enfants_out: Decimal, montant_avec_garde_alternee_base_out: Money, montant_verse_base_out: Money, droit_ouvert_forfaitaire_out: Callable[[Enfant], bool], montant_verse_forfaitaire_par_enfant_out: Money, montant_verse_forfaitaire_out: Money, droit_ouvert_majoration_out: Callable[[Enfant], bool], montant_initial_metropole_majoration_out: Callable[[Enfant], Money], montant_initial_majoration_out: Callable[[Enfant], Money], montant_avec_garde_alternee_majoration_out: Callable[[Enfant], Money], montant_verse_majoration_out: Money, droit_ouvert_complement_out: bool, montant_base_complement_pour_base_et_majoration_out: Money, complement_degressif_out: Callable[[Money], Money], montant_verse_complement_pour_base_et_majoration_out: Money, montant_verse_complement_pour_forfaitaire_out: Money, nombre_enfants_l521_1_out: Integer, age_minimum_alinea_1_l521_3_out: Callable[[Enfant], Integer], nombre_enfants_alinea_2_l521_3_out: Integer, est_enfant_le_plus_age_out: Callable[[Enfant], bool], plafond_I_d521_3_out: Money, plafond_II_d521_3_out: Money) -> None:
@ -213,6 +389,53 @@ class AllocationsFamilialesOut:
self.plafond_I_d521_3_out = plafond_I_d521_3_out
self.plafond_II_d521_3_out = plafond_II_d521_3_out
def __eq__(self, other: object) -> bool:
if isinstance(other, AllocationsFamilialesOut):
return (self.personne_charge_effective_permanente_est_parent_out == other.personne_charge_effective_permanente_est_parent_out and
self.personne_charge_effective_permanente_remplit_titre_I_out == other.personne_charge_effective_permanente_remplit_titre_I_out and
self.ressources_menage_out == other.ressources_menage_out and
self.residence_out == other.residence_out and
self.date_courante_out == other.date_courante_out and
self.enfants_a_charge_out == other.enfants_a_charge_out and
self.enfants_a_charge_droit_ouvert_prestation_familiale_out == other.enfants_a_charge_droit_ouvert_prestation_familiale_out and
self.prise_en_compte_out == other.prise_en_compte_out and
self.versement_out == other.versement_out and
self.montant_verse_out == other.montant_verse_out and
self.droit_ouvert_base_out == other.droit_ouvert_base_out and
self.montant_initial_base_out == other.montant_initial_base_out and
self.montant_initial_base_premier_enfant_out == other.montant_initial_base_premier_enfant_out and
self.montant_initial_base_deuxieme_enfant_out == other.montant_initial_base_deuxieme_enfant_out and
self.montant_initial_base_troisieme_enfant_et_plus_out == other.montant_initial_base_troisieme_enfant_et_plus_out and
self.rapport_enfants_total_moyen_out == other.rapport_enfants_total_moyen_out and
self.nombre_moyen_enfants_out == other.nombre_moyen_enfants_out and
self.nombre_total_enfants_out == other.nombre_total_enfants_out and
self.montant_avec_garde_alternee_base_out == other.montant_avec_garde_alternee_base_out and
self.montant_verse_base_out == other.montant_verse_base_out and
self.droit_ouvert_forfaitaire_out == other.droit_ouvert_forfaitaire_out and
self.montant_verse_forfaitaire_par_enfant_out == other.montant_verse_forfaitaire_par_enfant_out and
self.montant_verse_forfaitaire_out == other.montant_verse_forfaitaire_out and
self.droit_ouvert_majoration_out == other.droit_ouvert_majoration_out and
self.montant_initial_metropole_majoration_out == other.montant_initial_metropole_majoration_out and
self.montant_initial_majoration_out == other.montant_initial_majoration_out and
self.montant_avec_garde_alternee_majoration_out == other.montant_avec_garde_alternee_majoration_out and
self.montant_verse_majoration_out == other.montant_verse_majoration_out and
self.droit_ouvert_complement_out == other.droit_ouvert_complement_out and
self.montant_base_complement_pour_base_et_majoration_out == other.montant_base_complement_pour_base_et_majoration_out and
self.complement_degressif_out == other.complement_degressif_out and
self.montant_verse_complement_pour_base_et_majoration_out == other.montant_verse_complement_pour_base_et_majoration_out and
self.montant_verse_complement_pour_forfaitaire_out == other.montant_verse_complement_pour_forfaitaire_out and
self.nombre_enfants_l521_1_out == other.nombre_enfants_l521_1_out and
self.age_minimum_alinea_1_l521_3_out == other.age_minimum_alinea_1_l521_3_out and
self.nombre_enfants_alinea_2_l521_3_out == other.nombre_enfants_alinea_2_l521_3_out and
self.est_enfant_le_plus_age_out == other.est_enfant_le_plus_age_out and
self.plafond_I_d521_3_out == other.plafond_I_d521_3_out and
self.plafond_II_d521_3_out == other.plafond_II_d521_3_out)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class AllocationsFamilialesIn:
def __init__(self, personne_charge_effective_permanente_est_parent_in: Callable[[Unit], bool], personne_charge_effective_permanente_remplit_titre_I_in: Callable[[Unit], bool], ressources_menage_in: Callable[[Unit], Money], residence_in: Callable[[Unit], Collectivite], date_courante_in: Callable[[Unit], Date], enfants_a_charge_in: Callable[[Unit], (List[Enfant])], enfants_a_charge_droit_ouvert_prestation_familiale_in: Callable[[Unit], (List[Enfant])], prise_en_compte_in: Callable[[Unit], (Callable[[Enfant], PriseEnCompte])], versement_in: Callable[[Unit], (Callable[[Enfant], VersementAllocations])], montant_verse_in: Callable[[Unit], Money], droit_ouvert_base_in: Callable[[Unit], bool], montant_initial_base_in: Callable[[Unit], Money], montant_initial_base_premier_enfant_in: Callable[[Unit], Money], montant_initial_base_deuxieme_enfant_in: Callable[[Unit], Money], montant_initial_base_troisieme_enfant_et_plus_in: Callable[[Unit], Money], rapport_enfants_total_moyen_in: Callable[[Unit], Decimal], nombre_moyen_enfants_in: Callable[[Unit], Decimal], nombre_total_enfants_in: Callable[[Unit], Decimal], montant_avec_garde_alternee_base_in: Callable[[Unit], Money], montant_verse_base_in: Callable[[Unit], Money], droit_ouvert_forfaitaire_in: Callable[[Unit], (Callable[[Enfant], bool])], montant_verse_forfaitaire_par_enfant_in: Callable[[Unit], Money], montant_verse_forfaitaire_in: Callable[[Unit], Money], droit_ouvert_majoration_in: Callable[[Unit], (Callable[[Enfant], bool])], montant_initial_metropole_majoration_in: Callable[[Unit], (Callable[[Enfant], Money])], montant_initial_majoration_in: Callable[[Unit], (Callable[[Enfant], Money])], montant_avec_garde_alternee_majoration_in: Callable[[Unit], (Callable[[Enfant], Money])], montant_verse_majoration_in: Callable[[Unit], Money], droit_ouvert_complement_in: Callable[[Unit], bool], montant_base_complement_pour_base_et_majoration_in: Callable[[Unit], Money], complement_degressif_in: Callable[[Unit], (Callable[[Money], Money])], montant_verse_complement_pour_base_et_majoration_in: Callable[[Unit], Money], montant_verse_complement_pour_forfaitaire_in: Callable[[Unit], Money], nombre_enfants_l521_1_in: Callable[[Unit], Integer], age_minimum_alinea_1_l521_3_in: Callable[[Unit], (Callable[[Enfant], Integer])], nombre_enfants_alinea_2_l521_3_in: Callable[[Unit], Integer], est_enfant_le_plus_age_in: Callable[[Unit], (Callable[[Enfant], bool])], plafond_I_d521_3_in: Callable[[Unit], Money], plafond_II_d521_3_in: Callable[[Unit], Money]) -> None:
@ -256,6 +479,53 @@ class AllocationsFamilialesIn:
self.plafond_I_d521_3_in = plafond_I_d521_3_in
self.plafond_II_d521_3_in = plafond_II_d521_3_in
def __eq__(self, other: object) -> bool:
if isinstance(other, AllocationsFamilialesIn):
return (self.personne_charge_effective_permanente_est_parent_in == other.personne_charge_effective_permanente_est_parent_in and
self.personne_charge_effective_permanente_remplit_titre_I_in == other.personne_charge_effective_permanente_remplit_titre_I_in and
self.ressources_menage_in == other.ressources_menage_in and
self.residence_in == other.residence_in and
self.date_courante_in == other.date_courante_in and
self.enfants_a_charge_in == other.enfants_a_charge_in and
self.enfants_a_charge_droit_ouvert_prestation_familiale_in == other.enfants_a_charge_droit_ouvert_prestation_familiale_in and
self.prise_en_compte_in == other.prise_en_compte_in and
self.versement_in == other.versement_in and
self.montant_verse_in == other.montant_verse_in and
self.droit_ouvert_base_in == other.droit_ouvert_base_in and
self.montant_initial_base_in == other.montant_initial_base_in and
self.montant_initial_base_premier_enfant_in == other.montant_initial_base_premier_enfant_in and
self.montant_initial_base_deuxieme_enfant_in == other.montant_initial_base_deuxieme_enfant_in and
self.montant_initial_base_troisieme_enfant_et_plus_in == other.montant_initial_base_troisieme_enfant_et_plus_in and
self.rapport_enfants_total_moyen_in == other.rapport_enfants_total_moyen_in and
self.nombre_moyen_enfants_in == other.nombre_moyen_enfants_in and
self.nombre_total_enfants_in == other.nombre_total_enfants_in and
self.montant_avec_garde_alternee_base_in == other.montant_avec_garde_alternee_base_in and
self.montant_verse_base_in == other.montant_verse_base_in and
self.droit_ouvert_forfaitaire_in == other.droit_ouvert_forfaitaire_in and
self.montant_verse_forfaitaire_par_enfant_in == other.montant_verse_forfaitaire_par_enfant_in and
self.montant_verse_forfaitaire_in == other.montant_verse_forfaitaire_in and
self.droit_ouvert_majoration_in == other.droit_ouvert_majoration_in and
self.montant_initial_metropole_majoration_in == other.montant_initial_metropole_majoration_in and
self.montant_initial_majoration_in == other.montant_initial_majoration_in and
self.montant_avec_garde_alternee_majoration_in == other.montant_avec_garde_alternee_majoration_in and
self.montant_verse_majoration_in == other.montant_verse_majoration_in and
self.droit_ouvert_complement_in == other.droit_ouvert_complement_in and
self.montant_base_complement_pour_base_et_majoration_in == other.montant_base_complement_pour_base_et_majoration_in and
self.complement_degressif_in == other.complement_degressif_in and
self.montant_verse_complement_pour_base_et_majoration_in == other.montant_verse_complement_pour_base_et_majoration_in and
self.montant_verse_complement_pour_forfaitaire_in == other.montant_verse_complement_pour_forfaitaire_in and
self.nombre_enfants_l521_1_in == other.nombre_enfants_l521_1_in and
self.age_minimum_alinea_1_l521_3_in == other.age_minimum_alinea_1_l521_3_in and
self.nombre_enfants_alinea_2_l521_3_in == other.nombre_enfants_alinea_2_l521_3_in and
self.est_enfant_le_plus_age_in == other.est_enfant_le_plus_age_in and
self.plafond_I_d521_3_in == other.plafond_I_d521_3_in and
self.plafond_II_d521_3_in == other.plafond_II_d521_3_in)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class InterfaceAllocationsFamilialesOut:
def __init__(self, date_courante_out: Date, enfants_out: List[EnfantEntree], enfants_a_charge_out: List[Enfant], ressources_menage_out: Money, residence_out: Collectivite, montant_verse_out: Money, personne_charge_effective_permanente_est_parent_out: bool, personne_charge_effective_permanente_remplit_titre_I_out: bool) -> None:
@ -268,6 +538,22 @@ class InterfaceAllocationsFamilialesOut:
self.personne_charge_effective_permanente_est_parent_out = personne_charge_effective_permanente_est_parent_out
self.personne_charge_effective_permanente_remplit_titre_I_out = personne_charge_effective_permanente_remplit_titre_I_out
def __eq__(self, other: object) -> bool:
if isinstance(other, InterfaceAllocationsFamilialesOut):
return (self.date_courante_out == other.date_courante_out and
self.enfants_out == other.enfants_out and
self.enfants_a_charge_out == other.enfants_a_charge_out and
self.ressources_menage_out == other.ressources_menage_out and
self.residence_out == other.residence_out and
self.montant_verse_out == other.montant_verse_out and
self.personne_charge_effective_permanente_est_parent_out == other.personne_charge_effective_permanente_est_parent_out and
self.personne_charge_effective_permanente_remplit_titre_I_out == other.personne_charge_effective_permanente_remplit_titre_I_out)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
class InterfaceAllocationsFamilialesIn:
def __init__(self, date_courante_in: Callable[[Unit], Date], enfants_in: Callable[[Unit], (List[EnfantEntree])], enfants_a_charge_in: Callable[[Unit], (List[Enfant])], ressources_menage_in: Callable[[Unit], Money], residence_in: Callable[[Unit], Collectivite], montant_verse_in: Callable[[Unit], Money], personne_charge_effective_permanente_est_parent_in: Callable[[Unit], bool], personne_charge_effective_permanente_remplit_titre_I_in: Callable[[Unit], bool]) -> None:
@ -280,6 +566,22 @@ class InterfaceAllocationsFamilialesIn:
self.personne_charge_effective_permanente_est_parent_in = personne_charge_effective_permanente_est_parent_in
self.personne_charge_effective_permanente_remplit_titre_I_in = personne_charge_effective_permanente_remplit_titre_I_in
def __eq__(self, other: object) -> bool:
if isinstance(other, InterfaceAllocationsFamilialesIn):
return (self.date_courante_in == other.date_courante_in and
self.enfants_in == other.enfants_in and
self.enfants_a_charge_in == other.enfants_a_charge_in and
self.ressources_menage_in == other.ressources_menage_in and
self.residence_in == other.residence_in and
self.montant_verse_in == other.montant_verse_in and
self.personne_charge_effective_permanente_est_parent_in == other.personne_charge_effective_permanente_est_parent_in and
self.personne_charge_effective_permanente_remplit_titre_I_in == other.personne_charge_effective_permanente_remplit_titre_I_in)
else:
return False
def __ne__(self, other: object) -> bool:
return not (self == other)
def smic(smic_in_1: SmicIn):
date_courante_2 = smic_in_1.date_courante_in

View File

@ -163,8 +163,7 @@ class Date:
return Date(self.value + other.value)
def __sub__(self, other: 'Date') -> 'Duration':
# Careful: invert argument order
return Duration(dateutil.relativedelta.relativedelta(other.value, self.value))
return Duration(dateutil.relativedelta.relativedelta(self.value, other.value))
def __lt__(self, other: 'Date') -> bool:
return self.value < other.value
@ -253,6 +252,18 @@ class Unit:
def __init__(self) -> None:
...
def __eq__(self, other: object) -> bool:
if isinstance(other, Unit):
return True
else:
return False
def __ne__(self, other: object) -> bool:
if isinstance(other, Unit):
return False
else:
return True
class SourcePosition:
def __init__(self,
@ -269,6 +280,10 @@ class SourcePosition:
self.end_column = end_column
self.law_headings = law_headings
def __str__(self) -> str:
return "in file {}, from {}:{} to {}:{} ({})".format(
self.filename, self.start_line, self.start_column, self.end_line, self.end_column, ", ".join(self.law_headings))
# ==========
# Exceptions
# ==========
@ -303,8 +318,8 @@ def money_of_cents_string(v: str) -> Money:
return Money(Integer(v))
def money_of_cents_int(v: int) -> Money:
return Money(Integer(v))
def money_of_units_int(v: int) -> Money:
return Money(Integer(v) * Integer(100))
def money_of_cents_integer(v: Integer) -> Money:
@ -396,7 +411,9 @@ def date_to_string(d: Date) -> str:
def date_of_numbers(year: int, month: int, day: int) -> Date:
return Date(datetime.date(year, month, day))
# The datetime.date does not take year=0 as an entry, we trick it into
# 1 in that case because year=0 cases don't care about the actual year
return Date(datetime.date(year if year != 0 else 1, month, day))
# ---------
# Durations
@ -467,7 +484,7 @@ def handle_default(
def no_input() -> Callable[[Unit], Alpha]:
def closure(_: Unit()):
def closure(_: Unit):
raise EmptyError
return closure
@ -488,5 +505,7 @@ def log_end_call(headings: List[str], value: Alpha) -> Alpha:
return value
def log_decision_taken(pos: SourcePosition, value: Alpha) -> Alpha:
def log_decision_taken(pos: SourcePosition, value: bool) -> bool:
if value:
print(">> Decision taken {}".format(pos))
return value