Beispiel #1
0
def check_decomposition_xml_file(file_path):
    decomposition_tree = xml.etree.ElementTree.parse(os.path.join(file_path))
    decomposition_xml_json = conv.check(decompositionsxml.xml_decomposition_to_json)(decomposition_tree.getroot(),
        state = conv.default_state)

    decomposition_xml_json, errors = decompositionsxml.make_validate_node_xml_json(base.tax_benefit_system)(
        decomposition_xml_json, state = conv.default_state)
    if errors is not None:
        errors = conv.embed_error(decomposition_xml_json, 'errors', errors)
        if errors is None:
            raise ValueError(unicode(json.dumps(decomposition_xml_json, ensure_ascii = False,
                indent = 2)).encode('utf-8'))
        raise ValueError(u'{0} for: {1}'.format(
            unicode(json.dumps(errors, ensure_ascii = False, indent = 2, sort_keys = True)),
            unicode(json.dumps(decomposition_xml_json, ensure_ascii = False, indent = 2)),
            ).encode('utf-8'))

    decomposition_json = decompositionsxml.transform_node_xml_json_to_json(decomposition_xml_json)

    decomposition_json, errors = decompositions.make_validate_node_json(base.tax_benefit_system)(
        decomposition_json, state = conv.default_state)
    if errors is not None:
        errors = conv.embed_error(decomposition_json, 'errors', errors)
        if errors is None:
            raise ValueError(unicode(json.dumps(decomposition_json, ensure_ascii = False, indent = 2)).encode('utf-8'))
        raise ValueError(u'{0} for: {1}'.format(
            unicode(json.dumps(errors, ensure_ascii = False, indent = 2, sort_keys = True)),
            unicode(json.dumps(decomposition_json, ensure_ascii = False, indent = 2)),
            ).encode('utf-8'))
def get_decomposition_json(tax_benefit_system, xml_file_path=None):
    if xml_file_path is None:
        xml_file_path = tax_benefit_system.decomposition_file_path
    decomposition_tree = ElementTree.parse(xml_file_path)
    decomposition_xml_json = conv.check(
        decompositionsxml.xml_decomposition_to_json)(
            decomposition_tree.getroot(), state=conv.State)
    decomposition_xml_json = conv.check(
        decompositionsxml.make_validate_node_xml_json(tax_benefit_system))(
            decomposition_xml_json, state=conv.State)
    decomposition_json = decompositionsxml.transform_node_xml_json_to_json(
        decomposition_xml_json)
    return decomposition_json
Beispiel #3
0
def get_cached_or_new_decomposition_json(tax_benefit_system, xml_file_name = None):
    if xml_file_name is None:
        xml_file_name = tax_benefit_system.DEFAULT_DECOMP_FILE
    global decomposition_json_by_file_path_cache
    decomposition_json = decomposition_json_by_file_path_cache.get(xml_file_name)
    if decomposition_json is None:
        xml_file_path = os.path.join(tax_benefit_system.DECOMP_DIR, xml_file_name)
        decomposition_tree = xml.etree.ElementTree.parse(xml_file_path)
        decomposition_xml_json = conv.check(decompositionsxml.xml_decomposition_to_json)(
            decomposition_tree.getroot())
        decomposition_xml_json = conv.check(decompositionsxml.make_validate_node_xml_json(tax_benefit_system))(
            decomposition_xml_json)
        decomposition_json = decompositionsxml.transform_node_xml_json_to_json(decomposition_xml_json)
        decomposition_json_by_file_path_cache[xml_file_name] = decomposition_json
    return decomposition_json
def api1_simulate(req):
    ctx = contexts.Ctx(req)
    headers = wsgihelpers.handle_cross_origin_resource_sharing(ctx)

    assert req.method == 'POST', req.method

    content_type = req.content_type
    if content_type is not None:
        content_type = content_type.split(';', 1)[0].strip()
    if content_type != 'application/json':
        return wsgihelpers.respond_json(ctx,
            collections.OrderedDict(sorted(dict(
                apiVersion = '1.0',
                error = collections.OrderedDict(sorted(dict(
                    code = 400,  # Bad Request
                    message = ctx._(u'Bad content-type: {}').format(content_type),
                    ).iteritems())),
                method = req.script_name,
                url = req.url.decode('utf-8'),
                ).iteritems())),
            headers = headers,
            )

    inputs, error = conv.pipe(
        conv.make_input_to_json(),
        conv.test_isinstance(dict),
        conv.not_none,
        )(req.body, state = ctx)
    if error is not None:
        return wsgihelpers.respond_json(ctx,
            collections.OrderedDict(sorted(dict(
                apiVersion = '1.0',
                error = collections.OrderedDict(sorted(dict(
                    code = 400,  # Bad Request
                    errors = [error],
                    message = ctx._(u'Invalid JSON in request POST body'),
                    ).iteritems())),
                method = req.script_name,
                params = req.body,
                url = req.url.decode('utf-8'),
                ).iteritems())),
            headers = headers,
            )

    data, errors = conv.struct(
        dict(
#            api_key = conv.pipe(  # Shared secret between client and server
#                conv.test_isinstance(basestring),
#                conv.input_to_uuid,
#                conv.not_none,
#                ),
            context = conv.test_isinstance(basestring),  # For asynchronous calls
            decomposition = conv.noop,  # Real conversion is done once tax-benefit system is known.
            scenarios = conv.pipe(
                conv.test_isinstance(list),
                conv.uniform_sequence(
                    conv.not_none,  # Real conversion is done once tax-benefit system is known.
                    ),
                conv.test(lambda scenarios: len(scenarios) >= 1, error = N_(u'At least one scenario is required')),
                conv.test(lambda scenarios: len(scenarios) <= 100,
                    error = N_(u"There can't be more than 100 scenarios")),
                conv.not_none,
                ),
            tax_benefit_system = ctx.TaxBenefitSystem.json_to_instance,
            trace = conv.pipe(
                conv.test_isinstance((bool, int)),
                conv.anything_to_bool,
                conv.default(False),
                ),
            validate = conv.pipe(
                conv.test_isinstance((bool, int)),
                conv.anything_to_bool,
                conv.default(False),
                ),
            ),
        )(inputs, state = ctx)
    if errors is None:
        tax_benefit_system = data['tax_benefit_system']
        data, errors = conv.struct(
            dict(
                decomposition = conv.pipe(
                    conv.condition(
                        conv.test_isinstance(basestring),
                        conv.test(lambda filename: filename in os.listdir(tax_benefit_system.DECOMP_DIR)),
                        decompositions.make_validate_node_json(tax_benefit_system),
                        ),
                    conv.default(os.path.join(tax_benefit_system.DECOMP_DIR, tax_benefit_system.DEFAULT_DECOMP_FILE)),
                    ),
                scenarios = conv.uniform_sequence(
                    tax_benefit_system.Scenario.make_json_to_instance(cache_dir = conf['cache_dir'],
                        tax_benefit_system = tax_benefit_system),
                    ),
                ),
            default = conv.noop,
            )(data, state = ctx)
    if errors is not None:
        return wsgihelpers.respond_json(ctx,
            collections.OrderedDict(sorted(dict(
                apiVersion = '1.0',
                context = inputs.get('context'),
                error = collections.OrderedDict(sorted(dict(
                    code = 400,  # Bad Request
                    errors = [errors],
                    message = ctx._(u'Bad parameters in request'),
                    ).iteritems())),
                method = req.script_name,
                params = inputs,
                url = req.url.decode('utf-8'),
                ).iteritems())),
            headers = headers,
            )

#    api_key = data['api_key']
#    account = model.Account.find_one(
#        dict(
#            api_key = api_key,
#            ),
#        as_class = collections.OrderedDict,
#        )
#    if account is None:
#        return wsgihelpers.respond_json(ctx,
#            collections.OrderedDict(sorted(dict(
#                apiVersion = '1.0',
#                context = data['context'],
#                error = collections.OrderedDict(sorted(dict(
#                    code = 401,  # Unauthorized
#                    message = ctx._('Unknown API Key: {}').format(api_key),
#                    ).iteritems())),
#                method = req.script_name,
#                params = inputs,
#                url = req.url.decode('utf-8'),
#                ).iteritems())),
#            headers = headers,
#            )

    suggestions = {}
    for scenario_index, scenario in enumerate(data['scenarios']):
        suggestion = scenario.suggest()
        if suggestion is not None:
            suggestions.setdefault('scenarios', {})[scenario_index] = suggestion
    if not suggestions:
        suggestions = None

    if data['validate']:
        # Only a validation is requested. Don't launch simulation
        return wsgihelpers.respond_json(ctx,
            collections.OrderedDict(sorted(dict(
                apiVersion = '1.0',
                context = inputs.get('context'),
                method = req.script_name,
                params = inputs,
                suggestions = suggestions,
                url = req.url.decode('utf-8'),
                ).iteritems())),
            headers = headers,
            )

    if isinstance(data['decomposition'], basestring):
        # TODO: Cache decomposition_json.
        decomposition_tree = xml.etree.ElementTree.parse(os.path.join(tax_benefit_system.DECOMP_DIR,
            data['decomposition']))
        decomposition_xml_json = conv.check(decompositionsxml.xml_decomposition_to_json)(decomposition_tree.getroot(),
            state = ctx)
        decomposition_xml_json = conv.check(decompositionsxml.make_validate_node_xml_json(tax_benefit_system))(
            decomposition_xml_json, state = ctx)
        decomposition_json = decompositionsxml.transform_node_xml_json_to_json(decomposition_xml_json)
    else:
        decomposition_json = data['decomposition']

    simulations = []
    for scenario in data['scenarios']:
        simulation = scenario.new_simulation(trace = data['trace'])
        for node in decompositions.iter_decomposition_nodes(decomposition_json):
            if not node.get('children'):
                simulation.calculate(node['code'])
        simulations.append(simulation)

    response_json = copy.deepcopy(decomposition_json)
    for node in decompositions.iter_decomposition_nodes(response_json, children_first = True):
        children = node.get('children')
        if children:
            node['values'] = map(lambda *l: sum(l), *(
                child['values']
                for child in children
                ))
        else:
            node['values'] = values = []
            for simulation in simulations:
                holder = simulation.get_holder(node['code'])
                values.extend(holder.new_test_case_array().tolist())

    if data['trace']:
        tracebacks = []
        for simulation in simulations:
            traceback_json = collections.OrderedDict()
            for step in simulation.traceback:
                holder = step['holder']
                column = holder.column
                traceback_json[column.name] = dict(
                    array = holder.array.tolist() if holder.array is not None else None,
                    default_arguments = step['default_arguments'],
                    entity = column.entity,
                    label = column.label,
                    )
            tracebacks.append(traceback_json)
    else:
        tracebacks = None

    return wsgihelpers.respond_json(ctx,
        collections.OrderedDict(sorted(dict(
            apiVersion = '1.0',
            context = data['context'],
            method = req.script_name,
            params = inputs,
            suggestions = suggestions,
            tracebacks = tracebacks,
            url = req.url.decode('utf-8'),
            value = response_json,
            ).iteritems())),
        headers = headers,
        )