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

Make sure all errors messages are correctly encoded #595

Merged
merged 10 commits into from
Jan 17, 2018
Merged

Conversation

sandcha
Copy link
Collaborator

@sandcha sandcha commented Nov 16, 2017

Fixes #587
Connected to #580

Bug fix

  • Fix API response encoding from ascii to utf-8 (to manage non ascii characters).
    • Improve user message by displaying UnicodeDecodeError information in json error response

@sandcha sandcha requested a review from Anna-Livia November 16, 2017 17:00
Copy link
Contributor

@Anna-Livia Anna-Livia left a comment

Choose a reason for hiding this comment

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

A/ Would it be helpful to check Openfisca-france for any error message ?
B/ Would you create an accentfull enum in country template and have test in core checking that the encoding works in error messages ?
C/ When testing entity names with accent, I got an internal server error

{
	"persons": {
		"bill": {
			"salary": {
				"2017": 60000
			}
		},
		"béll": {
			"salary": {
				"2017": 60000
			}
		}
	},
	"households": {
		"_": {
			"parents": ["bill", "béll"],
			"housing_tax": {
				"2017": null
			},
			"accomodation_size": {
				"2017-01": 300
			},
			"housing_occupancy_status": {
				"2017-01": "Tenant"
			}
		}
	}
}

resulted in :

  "error": "Internal server error: 'ascii' codec can't encode character u'\\xe9' in position 1: ordinal not in range(128)"

also, accents in place of periods make the server angry:

{
	"persons": {
		"bill": {
			"salary": {
				"2017": 60000
			}
		},
		"bell": {
			"salary": {
				"2017": 60000
			}
		}
	},
	"households": {
		"_": {
			"parents": ["bill", "bell"],
			"housing_tax": {
				"à": null
			},
			"accomodation_size": {
				"2017-01": 300
			},
			"housing_occupancy_status": {
				"2017-01": "Tenant"
			}
		}
	}
}

results in:

  "error": "Internal server error: 'ascii' codec can't encode character u'\\xe0' in position 0: ordinal not in range(128)"

@@ -71,7 +71,7 @@ def init_variable_values(self, entity_object, entity_id):

if not isinstance(variable_values, dict):
raise SituationParsingError(path_in_json,
'Invalid type: must be of type object. Input variables must be set for specific periods. For instance: {"salary": {"2017-01": 2000, "2017-02": 2500}}')
u'Invalid type: must be of type object. Input variables must be set for specific periods. For instance: {"salary": {"2017-01": 2000, "2017-02": 2500}}')
Copy link
Contributor

Choose a reason for hiding this comment

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

When tested with curl, got :

 For instance: {\"salary\": {\"2017-01\": 2000, \"2017-02\": 2500}}"

I was expecting :

 For instance: {"salary": {"2017-01": 2000, "2017-02": 2500}}"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For instance: {\"salary\": {\"2017-01\": 2000, \"2017-02\": 2500}} is correct as it is included in a JSON response like:

{
  "persons": {
    "bill": {
      "salary": "Invalid type: must be of type object. Input variables must be set for specific periods. For instance: {\"salary\": {\"2017-01\": 2000, \"2017-02\": 2500}}"
    }
  }
}

"'{}' is not a valid value for '{}'. Possible values are ['{}'].".format(
value, variable_name, "', '".join(holder.variable.possible_values.list)
).encode('utf-8')
u"'{}' is not a valid value for '{}'. Possible values are ['{}'].".format(
Copy link
Contributor

Choose a reason for hiding this comment

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

Works great when Value has accents. Woudl it be possible to add a accentfull enum to country template to test if possible values works also ?

)
try:
array[entity_index] = value
except (ValueError, TypeError) as e:
raise SituationParsingError(path_in_json,
'Invalid type: must be of type {}.'.format(holder.variable.json_type))
u'Invalid type: must be of type {}.'.format(holder.variable.json_type))
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see how to test for this 🤔

@@ -115,7 +114,7 @@ def finalize_variables_init(self):
# It is only raised when we consume the buffer. We thus don't know which exact key caused the error.
# We do a basic research to find the culprit path
culprit_path = next(
dpath.search(self.entities_json, "*/{}/{}".format(e.variable_name, str(e.period)), yielded = True),
dpath.search(self.entities_json, u"*/{}/{}".format(e.variable_name, str(e.period)), yielded = True),
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see how to test for this 🤔

@@ -145,7 +144,7 @@ def clone(self, new_simulation):
def __getattr__(self, attribute):
projector = get_projector_from_shortcut(self, attribute)
if not projector:
raise Exception("Entity {} has no attribute {}".format(self.key, attribute))
raise Exception(u"Entity {} has no attribute {}".format(self.key, attribute))
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see how to test for this 🤔

@@ -319,12 +318,12 @@ def init_members(self, roles_json, entity_id):
check_type(person_id, basestring, [self.plural, entity_id, role_id, str(index)])
if person_id not in self.simulation.persons.ids:
raise SituationParsingError([self.plural, entity_id, role_id],
"Unexpected value: {0}. {0} has been declared in {1} {2}, but has not been declared in {3}.".format(
u"Unexpected value: {0}. {0} has been declared in {1} {2}, but has not been declared in {3}.".format(
Copy link
Contributor

Choose a reason for hiding this comment

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

Tested, works well :)

@@ -305,7 +304,7 @@ def init_from_json(self, entities_json):
if self.persons_to_allocate:
unallocated_person = self.persons_to_allocate.pop()
raise SituationParsingError([self.plural],
'{0} has been declared in {1}, but is not a member of any {2}. All {1} must be allocated to a {2}.'.format(
u'{0} has been declared in {1}, but is not a member of any {2}. All {1} must be allocated to a {2}.'.format(
Copy link
Contributor

Choose a reason for hiding this comment

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

Works well :)

@@ -254,7 +254,7 @@ def check_type(input, type, path = []):

if not isinstance(input, type):
raise SituationParsingError(path,
"Invalid type: must be of type '{}'.".format(json_type_map[type]))
u"Invalid type: must be of type '{}'.".format(json_type_map[type]))
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@sandcha
Copy link
Collaborator Author

sandcha commented Nov 20, 2017

B/ On enums with accents:
Before merging enums pr #589, enums with accents work. This is conditioned to the use of unicode on key names. Str keys with accent raise KeyError on enumerations.py:16. But this file disappears in #589.

@sandcha
Copy link
Collaborator Author

sandcha commented Nov 22, 2017

Definition of done:

  • When a non ASCII encoding is sent to the API, print a 500 error message with the incriminated character.
  • Add unit tests on encoding in API requests

@sandcha
Copy link
Collaborator Author

sandcha commented Jan 17, 2018

Before, on UnicodeDecodeError :

  • Error 500
{
  "error": "Internal server error: 'ascii' codec can't encode character u'\\u2018' in position 1: ordinal not in range(128)"
}

After:

  • Error 400 (500 if something was missed):
{
  "error": "'O‘Ryan' is not a valid ASCII value."
}

@sandcha sandcha merged commit 8e784a6 into master Jan 17, 2018
@sandcha sandcha deleted the msg-encoding-587 branch January 17, 2018 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make sure all errors messages are correctly encoded
2 participants