Repository: sissaschool/elementpath

Issue:
Issue translating regular expression (via XMLSchema)
https://github.com/sissaschool/elementpath/blob/4a166804290924b07067433e4d2b88723bb3567f/elementpath/regex/patterns.py#L125

Hi, I'm running into a problem in xmlschema, but I think it may be related to this library.

I am developing an application to generate code from a specific XML schema, and I need to extract patterns from an XSD into python regular expressions for injection into templates.

Generally, it works quite well! However, I have noticed an issue with the pattern `\\S(.*\\S)?`, intended to describe a string with no leading or trailing spaces. This pattern is translated into `^(?:\\S(?:[^\r\n]*\\S)?)$(?!\\n\\Z)` - note that the [^\r\n] in the middle of the string does not have a double escape. 

I believe the line I reference above is the culprit - it does not use a raw string, like the rest of the examples in this module. The result is that this sequence is translated into:

```
"^(?:\S(?:[^
]*\S)?)$(?!\n\Z)")
```

when I pass it to another library.  Does this appear to be the issue? I can submit a pull request, but wanted to see if you agree with my troubleshooting.

Thanks!

Discussion:
@RS-Credentive: I have confirmed this fixes the issue. Submitting PR@brunato: Hi, 
thank you for reporting the issue and for the PR. 
If you can fix the failing tests with another commit in the PR (then i squash and merge the PR into a single commit anyway) I would appreciate.
@RS-Credentive: I have added what I believe will fix the failing tests, but I'm not sure how to trigger a re-test.@brunato: You cannot trigger CI tests on the origin repo, maybe you could set something in your fork project. But for this case running local tests in the usual mode for `unittest` or with `tox` is sufficient (the fix is not strictly related to the platform or the version of Python).

I'll keep this issue open until the next release of the package is published.

thank you
@RS-Credentive: It appears that the tests have run successfully for the updated PR! Let me know if you have any other concerns.@brunato: Hi, a new release of the package is available, so i close the issue.


Solution patch:
diff --git a/elementpath/regex/patterns.py b/elementpath/regex/patterns.py
index d4fbe00..f9177f9 100644
--- a/elementpath/regex/patterns.py
+++ b/elementpath/regex/patterns.py
@@ -122,7 +122,7 @@ def translate_pattern(pattern: str, flags: int = 0, xsd_version: str = '1.0',
     while pos < pattern_len:
         ch = pattern[pos]
         if ch == '.':
-            regex.append(ch if dot_all else '[^\r\n]')
+            regex.append(ch if dot_all else r'[^\r\n]')
         elif ch in ('^', '$'):
             if not anchors:
                 regex.append(r'\%s' % ch)


Test patch:
diff --git a/tests/test_regex.py b/tests/test_regex.py
index c9a5773..b8e0646 100644
--- a/tests/test_regex.py
+++ b/tests/test_regex.py
@@ -626,7 +626,7 @@ class TestPatterns(unittest.TestCase):
 
     def test_dot_wildcard(self):
         regex = translate_pattern('.+', anchors=False)
-        self.assertEqual(regex, '^([^\r\n]+)$(?!\\n\\Z)')
+        self.assertEqual(regex, '^([^\\r\\n]+)$(?!\\n\\Z)')
         pattern = re.compile(regex)
         self.assertIsNone(pattern.search('line1\rline2\r'))
         self.assertIsNone(pattern.search('line1\nline2'))
@@ -635,7 +635,7 @@ class TestPatterns(unittest.TestCase):
         self.assertEqual(pattern.search('abc').group(0), 'abc')
 
         regex = translate_pattern('.+T.+(Z|[+-].+)', anchors=False)
-        self.assertEqual(regex, '^([^\r\n]+T[^\r\n]+(Z|[\\+\\-][^\r\n]+))$(?!\\n\\Z)')
+        self.assertEqual(regex, '^([^\\r\\n]+T[^\\r\\n]+(Z|[\\+\\-][^\\r\\n]+))$(?!\\n\\Z)')
         pattern = re.compile(regex)
         self.assertEqual(pattern.search('12T0A3+36').group(0), '12T0A3+36')
         self.assertEqual(pattern.search('12T0A3Z').group(0), '12T0A3Z')
@@ -903,7 +903,7 @@ class TestPatterns(unittest.TestCase):
 
     def test_lazy_quantifiers(self):
         regex = translate_pattern('.*?')
-        self.assertEqual(regex, '[^\r\n]*?')
+        self.assertEqual(regex, '[^\\r\\n]*?')
         regex = translate_pattern('[a-z]{2,3}?')
         self.assertEqual(regex, '[a-z]{2,3}?')
         regex = translate_pattern('[a-z]*?')