# Path: pyxform/validators/error_cleaner.py
# class ErrorCleaner:
#     """Cleans up raw error messages from XForm validators for end users."""
# 
#     @staticmethod
#     def _replace_xpath_with_tokens(match):
#         strmatch = match.group()
#         # eliminate e.g /html/body/select1[@ref=/id_string/elId]/item/value
#         # instance('q4')/root/item[...]
#         if (
#             strmatch.startswith("/html/body")
#             or strmatch.startswith("/root/item")
#             or strmatch.startswith("/html/head/model/bind")
#             or strmatch.endswith("/item/value")
#         ):
#             return strmatch
#         line = match.group().split("/")
#         return "${%s}" % line[len(line) - 1]
# 
#     @staticmethod
#     def _cleanup_errors(error_message):
#         pattern = r"(/[a-z0-9\-_]+(?:/[a-z0-9\-_]+)+)"
#         error_message = re.sub(
#             pattern, ErrorCleaner._replace_xpath_with_tokens, error_message, flags=re.I
#         )
#         lines = str(error_message).strip().splitlines()
#         no_dupes = [
#             line for i, line in enumerate(lines) if line != lines[i - 1] or i == 0
#         ]
#         return no_dupes
# 
#     @staticmethod
#     def _remove_java_content(line):
#         # has a java filename (with line number)
#         has_java_filename = line.find(".java:") != -1
#         # starts with '    at java class path or method path'
#         is_a_java_method = line.find("\tat") != -1
#         if not has_java_filename and not is_a_java_method:
#             # remove java.lang.RuntimeException
#             if line.startswith("java.lang.RuntimeException: "):
#                 line = line.replace("java.lang.RuntimeException: ", "")
#             # remove org.javarosa.xpath.XPathUnhandledException
#             if line.startswith("org.javarosa.xpath.XPathUnhandledException: "):
#                 line = line.replace("org.javarosa.xpath.XPathUnhandledException: ", "")
#             # remove java.lang.NullPointerException
#             if line.startswith("java.lang.NullPointerException"):
#                 line = line.replace("java.lang.NullPointerException", "")
#             if line.startswith("org.javarosa.xform.parse.XFormParseException"):
#                 line = line.replace("org.javarosa.xform.parse.XFormParseException", "")
#             return line
# 
#     @staticmethod
#     def _join_final(error_messages):
#         return "\n".join(line for line in error_messages if line is not None)
# 
#     @staticmethod
#     def odk_validate(error_message):
#         if "Error: Unable to access jarfile" in error_message:
#             return error_message  # Avoids tokenising the file path.
#         common = ErrorCleaner._cleanup_errors(error_message)
#         java_clean = [ErrorCleaner._remove_java_content(i) for i in common]
#         final_message = ErrorCleaner._join_final(java_clean)
#         return final_message
# 
#     @staticmethod
#     def enketo_validate(error_message):
#         common = ErrorCleaner._cleanup_errors(error_message)
#         final_message = ErrorCleaner._join_final(common)
#         return final_message
# 
# Path: pyxform/validators/util.py
# XFORM_SPEC_PATH = os.path.join(HERE, "xlsform_spec_test.xml")
# 
# def check_readable(file_path, retry_limit=10, wait_seconds=0.5):
#     """
#     Check if a file is readable: True if so, IOError if not. Retry as per args.
# 
#     If a file that needs to be read may be locked by some other process (such
#     as for reading or writing), this can help avoid an error by waiting for the
#     lock to clear.
# 
#     :param file_path: Path to file to check.
#     :param retry_limit: Number of attempts to read the file.
#     :param wait_seconds: Amount of sleep time between read attempts.
#     :return: True or raise IOError.
#     """
# 
#     def catch_try():
#         try:
#             with io.open(file_path, mode="r"):
#                 return True
#         except IOError:
#             return False
# 
#     tries = 0
#     while not catch_try():
#         if tries < retry_limit:
#             tries += 1
#             time.sleep(wait_seconds)
#         else:
#             raise IOError("Could not read file: {f}".format(f=file_path))
#     return True
# 
# Path: tests/utils.py
# def prep_class_config(cls, test_dir="tests"):
#     cls.config = configparser.ConfigParser()
#     here = os.path.dirname(__file__)
#     root = os.path.dirname(here)
#     strings = os.path.join(root, test_dir, "fixtures", "strings.ini")
#     cls.config.read(strings)
#     cls.cls_name = cls.__name__


import os
from unittest import TestCase
from pyxform.validators.error_cleaner import ErrorCleaner
from pyxform.validators.util import XFORM_SPEC_PATH, check_readable
from tests.utils import prep_class_config
# -*- coding: utf-8 -*-
"""
Test pyxform.validators.utils module.
"""



class TestValidatorUtil(TestCase):
    maxDiff = None
    config = None
    cls_name = None

    @classmethod
    def setUpClass(cls):
        prep_class_config(cls=cls)

    def test_cleanup_error_message(self):
        test_str = self.config.get(self.cls_name, "test_cleanup_error_message_test")
        expected_str = self.config.get(
            self.cls_name, "test_cleanup_error_message_expected"
        )

# Path: pyxform/validators/error_cleaner.py
# class ErrorCleaner:
#     """Cleans up raw error messages from XForm validators for end users."""
# 
#     @staticmethod
#     def _replace_xpath_with_tokens(match):
#         strmatch = match.group()
#         # eliminate e.g /html/body/select1[@ref=/id_string/elId]/item/value
#         # instance('q4')/root/item[...]
#         if (
#             strmatch.startswith("/html/body")
#             or strmatch.startswith("/root/item")
#             or strmatch.startswith("/html/head/model/bind")
#             or strmatch.endswith("/item/value")
#         ):
#             return strmatch
#         line = match.group().split("/")
#         return "${%s}" % line[len(line) - 1]
# 
#     @staticmethod
#     def _cleanup_errors(error_message):
#         pattern = r"(/[a-z0-9\-_]+(?:/[a-z0-9\-_]+)+)"
#         error_message = re.sub(
#             pattern, ErrorCleaner._replace_xpath_with_tokens, error_message, flags=re.I
#         )
#         lines = str(error_message).strip().splitlines()
#         no_dupes = [
#             line for i, line in enumerate(lines) if line != lines[i - 1] or i == 0
#         ]
#         return no_dupes
# 
#     @staticmethod
#     def _remove_java_content(line):
#         # has a java filename (with line number)
#         has_java_filename = line.find(".java:") != -1
#         # starts with '    at java class path or method path'
#         is_a_java_method = line.find("\tat") != -1
#         if not has_java_filename and not is_a_java_method:
#             # remove java.lang.RuntimeException
#             if line.startswith("java.lang.RuntimeException: "):
#                 line = line.replace("java.lang.RuntimeException: ", "")
#             # remove org.javarosa.xpath.XPathUnhandledException
#             if line.startswith("org.javarosa.xpath.XPathUnhandledException: "):
#                 line = line.replace("org.javarosa.xpath.XPathUnhandledException: ", "")
#             # remove java.lang.NullPointerException
#             if line.startswith("java.lang.NullPointerException"):
#                 line = line.replace("java.lang.NullPointerException", "")
#             if line.startswith("org.javarosa.xform.parse.XFormParseException"):
#                 line = line.replace("org.javarosa.xform.parse.XFormParseException", "")
#             return line
# 
#     @staticmethod
#     def _join_final(error_messages):
#         return "\n".join(line for line in error_messages if line is not None)
# 
#     @staticmethod
#     def odk_validate(error_message):
#         if "Error: Unable to access jarfile" in error_message:
#             return error_message  # Avoids tokenising the file path.
#         common = ErrorCleaner._cleanup_errors(error_message)
#         java_clean = [ErrorCleaner._remove_java_content(i) for i in common]
#         final_message = ErrorCleaner._join_final(java_clean)
#         return final_message
# 
#     @staticmethod
#     def enketo_validate(error_message):
#         common = ErrorCleaner._cleanup_errors(error_message)
#         final_message = ErrorCleaner._join_final(common)
#         return final_message
# 
# Path: pyxform/validators/util.py
# XFORM_SPEC_PATH = os.path.join(HERE, "xlsform_spec_test.xml")
# 
# def check_readable(file_path, retry_limit=10, wait_seconds=0.5):
#     """
#     Check if a file is readable: True if so, IOError if not. Retry as per args.
# 
#     If a file that needs to be read may be locked by some other process (such
#     as for reading or writing), this can help avoid an error by waiting for the
#     lock to clear.
# 
#     :param file_path: Path to file to check.
#     :param retry_limit: Number of attempts to read the file.
#     :param wait_seconds: Amount of sleep time between read attempts.
#     :return: True or raise IOError.
#     """
# 
#     def catch_try():
#         try:
#             with io.open(file_path, mode="r"):
#                 return True
#         except IOError:
#             return False
# 
#     tries = 0
#     while not catch_try():
#         if tries < retry_limit:
#             tries += 1
#             time.sleep(wait_seconds)
#         else:
#             raise IOError("Could not read file: {f}".format(f=file_path))
#     return True
# 
# Path: tests/utils.py
# def prep_class_config(cls, test_dir="tests"):
#     cls.config = configparser.ConfigParser()
#     here = os.path.dirname(__file__)
#     root = os.path.dirname(here)
#     strings = os.path.join(root, test_dir, "fixtures", "strings.ini")
#     cls.config.read(strings)
#     cls.cls_name = cls.__name__


# Path: tests/test_validator_util.py
import os
from unittest import TestCase
from pyxform.validators.error_cleaner import ErrorCleaner
from pyxform.validators.util import XFORM_SPEC_PATH, check_readable
from tests.utils import prep_class_config

# -*- coding: utf-8 -*-
"""
Test pyxform.validators.utils module.
"""



class TestValidatorUtil(TestCase):
    maxDiff = None
    config = None
    cls_name = None

    @classmethod
    def setUpClass(cls):
        prep_class_config(cls=cls)

    def test_cleanup_error_message(self):
        test_str = self.config.get(self.cls_name, "test_cleanup_error_message_test")
        expected_str = self.config.get(
            self.cls_name, "test_cleanup_error_message_expected"
        )

        self.assertEqual(ErrorCleaner.odk_validate(test_str), expected_str.strip())