Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add editorial content on parameter and variable #717

Merged
merged 19 commits into from
Oct 2, 2018

Conversation

sandcha
Copy link
Collaborator

@sandcha sandcha commented Aug 27, 2018

Connected to openfisca/legislation-explorer#124

New features

Allow for multiline editorial content on parameters and variables:

  • Introduce ParameterNode.documentation, Parameter.documentation and Variable.documentation attributes
  • User can access a documentation attribute through Web API
    • on /parameter nodes as /parameter/benefits

      = python ParameterNode.documentation
      = documentation string attribute of index.yaml

    • on /parameter leafs as /parameter/benefits/housing_allowance

      = python Parameter.documentation
      = yaml documentation string attribute

    • on /variable leafs as /variable/housing_allowance

      = python Variable.documentation

    • on every /variable leaf formula

      = python Variable formula docstring

Here is web API /variable/housing_allowance example:

  {
    "description": "Housing allowance",
    "documentation": "This allowance was introduced on the 1st of Jan 1980.\nIt needs the   'rent' value (same month) but doesn't care about the 'housing_occupancy_status'.",
    "entity": "household",
    "formulas": {
      "1980-01-01": {
        "content": "def formula_1980(household, period, parameters):\n    '''This is my specific life statement.'''\n    return     household('rent', period) * parameters(period).benefits.housing_allowance\n",
        "documentation": "This is my specific life statement.",
        "source": "https://github.com/openfisca/country-template/blob/3.3.0/openfisca_country_template/variables/benefits.py#L47-L49"
      },
      "2016-12-01": null
    },
    "id": "housing_allowance",
    (...)
  }

The formula doctoring is in the formula content and documentation attributes.

@benjello
Copy link
Member

benjello commented Aug 28, 2018

@sandcha : I am ok with that. My only concern is performance. Does the inclusion of an new attribute for all the variables may alter performance when instantiating a tax benefit system ?

response = subject.get('/variable/housing_allowance')
variable = json.loads(response.data.decode('utf-8'))
assert_equal(variable['documentation'],
"\nThis allowance was introduced on the 1st of Jan 1980.\nIt needs the 'rent' value "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first line break is not relevant, and should be removed somehow. Same for the last one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #714 (comment) for an easy implem

@@ -78,6 +78,9 @@ def build_variable(variable, country_package_metadata, tax_benefit_system):
),
}

if variable.documentation:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at OpenFisca France, a lot of doc string is added at the formula level. This PR is not exposing this doc though the API. We should probably do that too :)

@@ -120,19 +120,23 @@ def __init__(self, name, data, file_path = None):
_validate_parameter(self, data, data_type = dict)
self.description = None
self.metadata = {}
self.documentation = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also add this new attributes to parameter nodes? I'm not sure there is a good reason to do it only for leads.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you see some use case for documentation on ParameterNodeobjects?
As I see it, for now, we wouldn't use it so it would be over-engineering it.

Copy link
Member

@fpagnoux fpagnoux Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, imagine something like: rsa.plafonds.1_enfant, rsa.plafonds.2_enfants, rsa.plafonds.par_enfant_supp.

In that case, it's probably more interesting to document the rsa.plafonds rather than the specific values.

In many case, parameters work by group and are not semantically fully independent. In that case, the nodes may be the thing we want to document.

'A fraction of the rent. \nFrom the 1st of Dec 2016, the housing allowance no longer exists.\n')


@raises(AttributeError)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if we chose not to give parameter nodes a documentation, I'm not sure about the relevance of such a test.

When reading this test, it feels like we are testing that Python sends an AttributeError when calling an undefined attribute, which doesn't say much about OpenFisca itself

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

It was there to define the expected behaviour before coding but is irrelevant now.

:param string name: Name of the parameter, e.g. "taxes.some_tax.some_param"
:param dict data: Data loaded from a YAML file.
:param string file_path: File the parameter was loaded from.
:param string documentation: Some documentation describing parameter usage and context.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some documentation -> Documentation

@@ -315,6 +320,7 @@ def __init__(self, name = "", directory_path = None, data = None, file_path = No
:param string name: Name of the node, eg "taxes.some_tax".
:param string directory_path: Directory containing YAML files describing the node.
:param dict data: Object representing the parameter node. It usually has been extracted from a YAML file.
:param string documentation: Some documentation describing parameter node usage and context.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some documentation -> Documentation

self.description = data.get('description', None)
self.documentation = data.get('documentation', None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None is already the default 2nd argument of get, specifying is redundant.

self.description = data.get('description', None)
self.documentation = data.get('documentation', None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary 2nd argument

@@ -378,8 +386,9 @@ def __init__(self, name = "", directory_path = None, data = None, file_path = No
else:
self.file_path = file_path
_validate_parameter(self, data, data_type = dict, allowed_keys = self._allowed_keys)
# We allow to set a reference and a description for a node.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems outdated (we don't set a reference around it). I'd just remove it 🙂

@@ -78,6 +82,9 @@ def build_variable(variable, country_package_metadata, tax_benefit_system):
),
}

if variable.documentation:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way we handle unspecified documentation in the Web API is currently inconsistent:

  • documentation: null for parameters
  • documentation: "" for formulas
  • no documentation key for variables

I'd be in favor of generalizing the 3rd option, as it makes the JSON more readable, lighter, and doesn't change anything for JS clients.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed for Web API : a documentation attribute is exposed only when it exists and its value is cleaned from start and end spaces.

On Python API : the documentation attribute value is not modified at all.
For variable formulas, there is no specific documentation attribute as the user can already get formula docstring with formula.__doc__.

def test_parameter_documentation():
parameter = tax_benefit_system.parameters.benefits.housing_allowance
assert_equal(parameter.documentation,
'A fraction of the rent. \nFrom the 1st of Dec 2016, the housing allowance no longer exists.\n')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This last line break is not really relevant. Cleaning the trailing line breaks with a strip in parameters parsing would be nice.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done for web API (not for python API).

variable = json.loads(response.data.decode('utf-8'))
assert_equal(variable['documentation'],
"This allowance was introduced on the 1st of Jan 1980.\nIt needs the 'rent' value "
+ "(same month) but doesn't care about the 'housing_occupancy_status'.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The + is not necessary, Python automatically concatenates strings.

@sandcha sandcha requested a review from fpagnoux September 27, 2018 16:54
@@ -68,7 +68,11 @@ def test_parameter_node():
assert_equal(response.status_code, OK)
parameter = json.loads(response.data)
assert_equal(sorted(list(parameter.keys())), ['description', 'documentation', 'id', 'metadata', 'source', 'subparams'])
assert_equal(parameter['documentation'], 'This (optional) file defines metadata for the node parameters.benefits in the parameter tree.')
assert_equal(parameter['documentation'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For test robustness sake, I'd just check that parameter['documentation'] contains a key expression, like "Government support for the citizens and residents".

@sandcha
Copy link
Collaborator Author

sandcha commented Oct 1, 2018

@benjello Including one attribute of primitive type for all the variables won't have significant effect on tax benefit system instantiation. For now, documentation attributes will mainly gather existing comments and have very short contents.

@sandcha sandcha force-pushed the editorialized-model-le124 branch from 8fcc772 to c638fcd Compare October 1, 2018 16:32
@sandcha sandcha force-pushed the editorialized-model-le124 branch from 89a4bb8 to 691fbde Compare October 1, 2018 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:feat A feature request, a feature deprecation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants