Skip to content

Commit

Permalink
Fix escaping in JSON schema patterns (#487)
Browse files Browse the repository at this point in the history
The escaping logic for patterns in JSON schema got convoluted, and we
introduced inadvertently inconsistencies in the formatting. Namely,
we first *unescaped* all the characters before passing them into
the parser for regular expressions. This unescaped characters later
propagated and mixed with *escaped* characters when the expression was
transpiled for UTF-16.

To solve this mess, we remove the unescaping step at the beginning and
test more thoroughly to specify & observe the expected behavior.

Fixes #485.
  • Loading branch information
mristin authored May 8, 2024
1 parent 13c671b commit 4a8a01e
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 79 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Call the generator with the appropriate target:
.. code-block::
usage: aas-core-codegen [-h] --model_path MODEL_PATH --snippets_dir
SNIPPETS_DIR --output_dir OUTPUT_DIR --target
SNIPPETS_DIR --output_dir OUTPUT_DIR --target
{csharp,cpp,golang,java,jsonschema,python,typescript,rdf_shacl,xsd,jsonld_context,protobuf}
[--version]
Expand Down
45 changes: 1 addition & 44 deletions aas_core_codegen/jsonschema/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Generate JSON schema corresponding to the meta-model."""
import collections
import json
import re
from typing import (
TextIO,
Any,
Expand Down Expand Up @@ -141,51 +140,9 @@ def _define_type(
)


# noinspection RegExpSimplifiable
_ESCAPE_BACKSLASH_X_U_U_RE = re.compile(
r"(\\x([a-fA-f0-9]{2})|\\u([a-fA-f0-9]{4})|\\U([a-fA-f0-9]{8}))"
)


def _undo_escaping_backslash_x_u_and_U_in_pattern(pattern: str) -> str:
"""
Undo the escaping of ``\\x??``, ``\\u????`` and ``\\U????????`` in the ``pattern``.
This is necessary since Greenery does not know how to handle such escape
sequences in the patterns and need the verbatim characters.
"""
parts = [] # type: List[str]
cursor = None # type: Optional[int]
for mtch in re.finditer(_ESCAPE_BACKSLASH_X_U_U_RE, pattern):
if cursor is None:
parts.append(pattern[: mtch.start()])
else:
parts.append(pattern[cursor : mtch.start()])

substring = mtch.group(0)
assert len(substring) > 2
assert substring[0] == "\\"

hex_code = substring[2:]
code_point = int(hex_code, base=16)
character = chr(code_point)
parts.append(character)
cursor = mtch.end()

if cursor is None:
parts.append(pattern)
else:
if cursor < len(pattern):
parts.append(pattern[cursor:])

return "".join(parts)


def _fix_pattern_for_utf16(pattern: str) -> str:
"""Fix the pattern for UTF-16-only regex engines."""
regex, error = parse_retree.parse(
[_undo_escaping_backslash_x_u_and_U_in_pattern(pattern)]
)
regex, error = parse_retree.parse([pattern])
if error is not None:
raise ValueError(
f"The pattern could not be parsed: {pattern!r}; error was: {error}"
Expand Down
13 changes: 11 additions & 2 deletions aas_core_codegen/parse/retree/_parse.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Parse a regular expression defined over a possibly-formatted string."""

import collections.abc
import io
import math
import re
Expand Down Expand Up @@ -89,7 +89,16 @@ class Cursor:
)
for first, second in zip(values, values[1:])
),
"No consecutive strings"
"No consecutive strings expected in the parsed sequence of an AST expression "
"representing a string interpolation"
)
# NOTE (mristin, 2024-05-08):
# We add a runtime test here since it already happened that we supplied ``values``
# as a string during development, causing an unnecessary long debugging session.
@require(
lambda values:
isinstance(values, collections.abc.Sequence),
"values must be a sequence"
)
# fmt: on
def __init__(self, values: Sequence[Union[str, FormattedValue]]) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22378,7 +22378,7 @@ public static class Serialize
public static void to(
IClass that,
XMLStreamWriter writer) throws SerializeException {
VisitorWithWriter visitor = new VisitorWithWriter();
VisitorWithWriter visitor = new VisitorWithWriter();
visitor.visit(
that, writer);
}
Expand Down
Loading

0 comments on commit 4a8a01e

Please sign in to comment.