From 0b484beab8dd3559ce3e454b56f7d5ae2bb0a82d Mon Sep 17 00:00:00 2001 From: vince Date: Sun, 14 Apr 2019 22:03:08 -0600 Subject: [PATCH 1/3] warning (that needs tweak) on default lang with no translation problem --- pyxform/survey.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/pyxform/survey.py b/pyxform/survey.py index 484d2be9c..122d4441c 100644 --- a/pyxform/survey.py +++ b/pyxform/survey.py @@ -178,7 +178,7 @@ def get_nsmap(self): return NSMAP - def xml(self): + def xml(self, warnings=None): """ calls necessary preparation methods, then returns the xml. """ @@ -432,13 +432,13 @@ def _generate_instances(self): yield i.instance seen[i.name] = i - def xml_model(self): + def xml_model(self, warnings=None): """ Generate the xform element """ self._setup_translations() self._setup_media() - self._add_empty_translations() + self._add_empty_translations(warnings) model_children = [] if self._translations: @@ -555,13 +555,16 @@ def _setup_choice_translations(name, choice_value, itext_id): choice_value, ) - def _add_empty_translations(self): + def _add_empty_translations(self, warnings=None): """ Adds translations so that every itext element has the same elements \ accross every language. When translations are not provided "-" will be used. This disables any of the default_language fallback functionality. """ + if warnings is None: + warnings = [] + paths = {} for lang, translation in self._translations.items(): for path, content in translation.items(): @@ -573,6 +576,13 @@ def _add_empty_translations(self): self._translations[lang][path] = {} for content_type in content_types: if content_type not in self._translations[lang][path]: + if lang == 'default': + warnings.append('\tDefault language not set,' + + ' with no default translations for ' + content_type + + ' Please consider setting a `default_language` in your' + + ' settings tab to insure questions and options appear' + + ' as expected.' + ) self._translations[lang][path][content_type] = "-" def _setup_media(self): @@ -712,10 +722,10 @@ def date_stamp(self): """Returns a date string with the format of %Y_%m_%d.""" return self._created.strftime("%Y_%m_%d") - def _to_ugly_xml(self): - return '' + self.xml().toxml() + def _to_ugly_xml(self, warnings=None): + return '' + self.xml(warnings).toxml() - def _to_pretty_xml(self): + def _to_pretty_xml(self, warnings=None): """ I want the to_xml method to by default validate the xml we are producing. @@ -837,6 +847,8 @@ def print_xform_to_file( Print the xForm to a file and optionally validate it as well by throwing exceptions and adding warnings to the warnings array. """ + print('print xform to file') + print('i has warnigns!') if warnings is None: warnings = [] if not path: @@ -844,9 +856,9 @@ def print_xform_to_file( try: with codecs.open(path, mode="w", encoding="utf-8") as file_obj: if pretty_print: - file_obj.write(self._to_pretty_xml()) + file_obj.write(self._to_pretty_xml(warnings)) else: - file_obj.write(self._to_ugly_xml()) + file_obj.write(self._to_ugly_xml(warnings)) except Exception as error: if os.path.exists(path): os.unlink(path) @@ -896,9 +908,9 @@ def to_xml(self, validate=True, pretty_print=True, warnings=None, enketo=False): if os.path.exists(tmp.name): os.remove(tmp.name) if pretty_print: - return self._to_pretty_xml() + return self._to_pretty_xml(warnings) - return self._to_ugly_xml() + return self._to_ugly_xml(warnings) def instantiate(self): """ From e1f08b3a1446ade967f676cf62b96fa985932318 Mon Sep 17 00:00:00 2001 From: vince Date: Sun, 14 Apr 2019 22:03:28 -0600 Subject: [PATCH 2/3] Make and test warning for blanked fields with no translation. --- pyxform/survey.py | 58 +++++++++++++++----- pyxform/tests_v1/test_language_warnings.py | 62 +++++++++++++++++++++- 2 files changed, 107 insertions(+), 13 deletions(-) diff --git a/pyxform/survey.py b/pyxform/survey.py index 122d4441c..b3aef4306 100644 --- a/pyxform/survey.py +++ b/pyxform/survey.py @@ -191,7 +191,7 @@ def xml(self, warnings=None): return node( "h:html", - node("h:head", node("h:title", self.title), self.xml_model()), + node("h:head", node("h:title", self.title), self.xml_model(warnings)), node("h:body", *self.xml_control(), **body_kwargs), **nsmap ) @@ -562,6 +562,7 @@ def _add_empty_translations(self, warnings=None): When translations are not provided "-" will be used. This disables any of the default_language fallback functionality. """ + if warnings is None: warnings = [] @@ -571,19 +572,54 @@ def _add_empty_translations(self, warnings=None): paths[path] = paths.get(path, set()).union(content.keys()) for lang, translation in self._translations.items(): + this_path_has_warning = False for path, content_types in paths.items(): if path not in self._translations[lang]: self._translations[lang][path] = {} + # missing question/question thingy thats like a hint + question_and_column = path.split(":") + missing_warning = self._generate_missing_translation_warning( + lang, question_and_column[0], question_and_column[1] + ) + warnings.append(missing_warning) + # no need to warn about content types missing translations since the + # whole path has a warning now. + this_path_has_warning = True + for content_type in content_types: if content_type not in self._translations[lang][path]: - if lang == 'default': - warnings.append('\tDefault language not set,' + - ' with no default translations for ' + content_type - + ' Please consider setting a `default_language` in your' - + ' settings tab to insure questions and options appear' - + ' as expected.' - ) - self._translations[lang][path][content_type] = "-" + self._translations[lang][path][content_type] = u"-" + # missing question thingy thats like media + if not this_path_has_warning: + # the path has a translation but the content type is missing one. + missing_warning = self._generate_missing_translation_warning( + lang, path.split(":")[0], content_type + ) + warnings.append(missing_warning) + + def _generate_missing_translation_warning(self, lang, question_name, column_name): + found_on_msg = ( + "\n--\n Question missing translation: " + + question_name + + "\n Column missing: " + + column_name + ) + + if lang == "default": + return ( + "\tDefault language not set," + " with missing default translations." + " Please consider setting a `default_language` in your" + + " settings tab to insure questions and options appear" + + " as expected." + + found_on_msg + ) + + return ( + "\tMissing field translations found for " + + lang + + " field may not appear as expected." + + found_on_msg + ) def _setup_media(self): """ @@ -734,7 +770,7 @@ def _to_pretty_xml(self, warnings=None): # space to text # TODO: check out pyxml # http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/ - xml_with_linebreaks = self.xml().toprettyxml(indent=" ") + xml_with_linebreaks = self.xml(warnings).toprettyxml(indent=" ") text_re = re.compile(r"(>)\n\s*(\s[^<>\s].*?)\n\s*(\s)\n(\s\s)*") pretty_xml = text_re.sub( @@ -847,8 +883,6 @@ def print_xform_to_file( Print the xForm to a file and optionally validate it as well by throwing exceptions and adding warnings to the warnings array. """ - print('print xform to file') - print('i has warnigns!') if warnings is None: warnings = [] if not path: diff --git a/pyxform/tests_v1/test_language_warnings.py b/pyxform/tests_v1/test_language_warnings.py index 762f9148d..8b5772757 100644 --- a/pyxform/tests_v1/test_language_warnings.py +++ b/pyxform/tests_v1/test_language_warnings.py @@ -72,6 +72,66 @@ def test_label_with_unknown_subtag_should_warn(self): ) os.unlink(tmp.name) + def test_missing_translation_no_default_lang_media_has_no_language(self): + # form should test media tag w NO default language set. + survey = self.md_to_pyxform_survey( + """ + | survey | | | | | + | | type | name | label::English (en) | media::image| + | | integer | nums | How many nums? | opt1.jpg | + """ + ) + + warnings = [] + tmp = tempfile.NamedTemporaryFile(suffix=".xml", delete=False) + tmp.close() + survey.print_xform_to_file(tmp.name, warnings=warnings) + + # In this survey, when 'default' s selected the label of this question will be '-'. + # Also, when 'English (en)` is selected, the medial will be '-' + self.assertTrue(len(warnings) == 2) + os.unlink(tmp.name) + + def test_missing_translation_media(self): + survey = self.md_to_pyxform_survey( + """ + | survey | | | | | | + | | type | name | label::English (en) | label::French (fr) | media::image::French (fr)| + | | integer | nums | How many nums? | Combien noms? | opt1.jpg | + """ + ) + + warnings = [] + tmp = tempfile.NamedTemporaryFile(suffix=".xml", delete=False) + tmp.close() + survey.print_xform_to_file(tmp.name, warnings=warnings) + self.assertTrue(len(warnings) == 1) + self.assertIn( + "Question missing translation: /pyxform_autotestname/nums", warnings[0] + ) + self.assertIn("Column missing: image", warnings[0]) + os.unlink(tmp.name) + + def test_missing_translation_hint(self): + survey = self.md_to_pyxform_survey( + """ + | survey | | | | | | + | | type | name | label::English (en) | label::French (fr) | hint::French (fr) | + | | integer | nums | How many nums? | Combien noms? | noms est nombres | + """ + ) + + warnings = [] + tmp = tempfile.NamedTemporaryFile(suffix=".xml", delete=False) + tmp.close() + survey.print_xform_to_file(tmp.name, warnings=warnings) + self.assertTrue(len(warnings) == 1) + self.assertIn( + "Question missing translation: /pyxform_autotestname/nums", warnings[0] + ) + self.assertIn("Column missing: hint", warnings[0]) + os.unlink(tmp.name) + def test_default_language_only_should_not_warn(self): survey = self.md_to_pyxform_survey( """ @@ -82,7 +142,7 @@ def test_default_language_only_should_not_warn(self): | | list_name | name | label | fake | | | opts | opt1 | Opt1 | 1 | | | opts | opt2 | Opt2 | 1 | - """ + """ ) warnings = [] From 4f2e7bd44fe9be72be1e87020bf08dd4e866c698 Mon Sep 17 00:00:00 2001 From: vince Date: Sun, 14 Jul 2019 15:51:29 -0600 Subject: [PATCH 3/3] ws change --- pyxform/survey.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyxform/survey.py b/pyxform/survey.py index b3aef4306..6e3924522 100644 --- a/pyxform/survey.py +++ b/pyxform/survey.py @@ -562,7 +562,6 @@ def _add_empty_translations(self, warnings=None): When translations are not provided "-" will be used. This disables any of the default_language fallback functionality. """ - if warnings is None: warnings = []