Si vous constatez la perte de tickets, de commentaires ou de projets, veuillez consulter la page https://status.framasoft.org/incident/626.

Commit c1592e8e authored by Christophe Benz's avatar Christophe Benz

Update transpiler, core and generated files

parent 83299906
# -*- coding: utf-8 -*-
import inspect
import logging
import importlib
from . import formulas
from .generated.variables_definitions import variable_definition_by_name
# Formulas helpers
log = logging.getLogger(__name__)
VARIABLE_SAISIE_DEFAULT_VALUE = 0
def find_definition(variable_name):
assert variable_name in variable_definition_by_name, \
'Definition not found for variable "{}"'.format(variable_name)
return variable_definition_by_name[variable_name]
def find_formula(variable_name):
return formulas.__dict__.get(variable_name)
def has_tag(tag, variable_definition):
return tag in variable_definition.get('attributes', {}).get('tags', [])
saisies = None # Global variable used by formulas, filled by `calculate_formulas`
def is_positive(n):
return n > 0
def load_environment():
formulas.load_formulas()
def is_zero(n):
return n == 0
# Core functions
class Simulation(object):
def __init__(self, value_by_variable_name=None):
self.value_by_variable_name = {} if value_by_variable_name is None else value_by_variable_name
def calculate(self, variable_name):
variable_definition = find_definition(variable_name)
if variable_definition['type'] == 'variable_calculee':
if variable_name not in self.value_by_variable_name:
formula = find_formula(variable_name)
if formula is None:
error_message = 'Formula not found for variable "{}"'.format(variable_name)
if has_tag('base', variable_definition):
log.warning(error_message + ' => use value 0')
value = 0
else:
raise ValueError(error_message)
else:
formula_args_names = inspect.getargspec(formula).args
formula_args = list(map(self.calculate, formula_args_names))
value = formula(*formula_args)
self.value_by_variable_name[variable_name] = value
value = self.value_by_variable_name[variable_name]
elif variable_definition['type'] == 'variable_saisie':
value = self.value_by_variable_name.get(variable_name, VARIABLE_SAISIE_DEFAULT_VALUE)
else:
raise NotImplementedError(variable_definition)
return value
def calculate_formulas(variables_saisies=None):
if variables_saisies is None:
variables_saisies = {}
global saisies
saisies = variables_saisies
importlib.import_module(name='.generated.formulas', package='calculateur_impots')
# -*- coding: utf-8 -*-
import glob
import importlib
import os
import pkg_resources
def load_formulas():
distribution_dir_path = pkg_resources.get_distribution('calculateur_impots').location
for file_path in sorted(glob.iglob(os.path.join(distribution_dir_path, 'calculateur_impots', 'generated', '*.py'))):
file_name = os.path.splitext(os.path.basename(file_path))[0]
importlib.import_module('.generated.' + file_name, 'calculateur_impots')
This diff is collapsed.
......@@ -20,20 +20,6 @@ log = logging.getLogger(script_name)
script_dir_name = os.path.dirname(os.path.abspath(__file__))
def iter_name_and_value(variables):
for variable in variables:
if '=' in variable:
variable_name, value = variable.split('=')
try:
value = float(value)
except ValueError:
raise ValueError('Invalid value "{}" provided for variable "{}"'.format(value, variable_name))
else:
variable_name = variable
value = None
yield variable_name, value
def iter_variables_calculees(variables):
for variable_name, value in iter_name_and_value(variables):
if value is None:
......@@ -43,35 +29,38 @@ def iter_variables_calculees(variables):
yield variable_name
def iter_variables_saisies(variables):
for variable_name, value in iter_name_and_value(variables):
if value is not None:
variable_definition = core.find_definition(variable_name)
assert variable_definition['type'] == 'variable_saisie', \
'Value provided for variable "{}" but type != "variable_saisie"'.format(variable_name)
yield variable_name, value
def iter_variables_saisies(values):
for variable_name, value in map(lambda value: value.split('=', 1), values):
variable_definition = core.find_definition(variable_name)
assert variable_definition['type'] == 'variable_saisie', \
'Value provided for variable "{}" but type != "variable_saisie"'.format(variable_name)
yield variable_name, value
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Increase output verbosity')
parser.add_argument('-d', '--debug', action='store_true', default=False, help='Display debug messages')
parser.add_argument('variables', metavar='variable or variable=value', nargs='+',
help='Variables (to calculate or input)')
parser.add_argument('--calculee', dest='calculees', default='IINET', metavar='variable', nargs='+',
help='Variables calculées')
parser.add_argument('--saisie', dest='saisies', metavar='variable', nargs='+', help='Variables saisies')
global args
args = parser.parse_args()
logging.basicConfig(level=logging.DEBUG if args.verbose or args.debug else logging.WARNING, stream=sys.stdout)
core.load_environment()
variables_saisies = {variable_name: value for variable_name, value in iter_variables_saisies(args.saisies)} \
if args.saisies is not None \
else None
core.calculate_formulas(variables_saisies=variables_saisies)
variables_saisies = {variable_name: value for variable_name, value in iter_variables_saisies(args.variables)}
simulation = core.Simulation(value_by_variable_name=variables_saisies)
variables_calculees = [variable_name for variable_name in iter_variables_calculees(args.variables)]
result = {
variable_name: simulation.calculate(variable_name)
for variable_name in variables_calculees
}
print(result)
calculees = [variable_name for variable_name in iter_variables_calculees(args.calculees)]
print(calculees)
# result = {
# variable_name: simulation.calculate(variable_name)
# for variable_name in variables_calculees
# }
# print(result)
return 0
......
......@@ -167,11 +167,11 @@ def node_to_python_source(node, parenthesised=False):
m_function_name = node['name']
python_function_name_by_m_function_name = {
'abs': 'abs',
# 'arr': '',
'arr': 'round',
# 'inf': '',
'max': 'max',
'min': 'min',
# 'null': '',
'null': 'is_zero',
# 'positif_ou_nul': '',
'positif': 'is_positive',
# 'present': '',
......@@ -443,16 +443,12 @@ def load_verifs_file(json_file_name):
def get_formula_source(formula_name):
return state['formulas_sources'].get(
formula_name,
'{} = 0 # Formula source not found'.format(formula_name),
'{} = 0'.format(formula_name),
)
def get_ordered_formulas_names(formulas_dependencies):
"""Return a list of formula names in a dependencies resolution order."""
def is_writable(formula_name):
variable_type = state['variables_definitions'][formula_name]['type']
return variable_type == 'variable_calculee' and not has_tag(formula_name, 'base')
writable_formulas_dependencies = {
key: set(filter(is_writable, values))
for key, values in formulas_dependencies.items()
......@@ -465,7 +461,8 @@ def get_ordered_formulas_names(formulas_dependencies):
ordered_formulas_names = []
expected_formulas_count = len(writable_formulas_names) # Store it since writable_formulas_names is mutated below.
while len(ordered_formulas_names) < expected_formulas_count:
for writable_formula_name in writable_formulas_names:
# Iterate sorted set for stability between executions of the script.
for writable_formula_name in sorted(writable_formulas_names):
if all(map(
lambda dependency_name: dependency_name in ordered_formulas_names,
writable_formulas_dependencies.get(writable_formula_name, []),
......@@ -477,9 +474,9 @@ def get_ordered_formulas_names(formulas_dependencies):
return ordered_formulas_names
def has_tag(variable_name, tag):
variable_definition = state['variables_definitions'][variable_name]
return tag in variable_definition.get('attributes', {}).get('tags', [])
def is_writable(formula_name):
variable_type = state['variables_definitions'][formula_name]['type']
return variable_type == 'variable_calculee'
# Main
......@@ -567,7 +564,14 @@ def main():
)
write_source(
file_name='formulas.py',
source=lines_to_python_source(map(get_formula_source, ordered_formulas_names)),
source=lines_to_python_source(itertools.chain(
(
'from ..core import *',
'from .constants import *',
'\n',
),
map(get_formula_source, ordered_formulas_names),
)),
)
return 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment