Skip to content

Commit

Permalink
Use context_diff over custom function
Browse files Browse the repository at this point in the history
  • Loading branch information
hughesjj committed Mar 2, 2024
1 parent c21047b commit 1bdd500
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
)
from opentelemetry.semconv.model.utils import ID_RE
from opentelemetry.semconv.templating.markdown.options import MarkdownOptions
from .utils import VisualDiffer

_REQUIREMENT_LEVEL_URL = (
"https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import difflib
import os


class VisualDiffer:
"""Colorize differential outputs, which can be useful in development of
semantic conventions
"""

@staticmethod
def colorize_text(r: int, g: int, b: int, text: str):
"""
Colorize text according to ANSI standards
The way this works is we send out a control character,
then send the color information (the r,g,b parts),
then the normal text, then an escape char to end the coloring
## Breakdown of magic values
33 (octal) == 1b (hexadecimal) == ESC control character
ESC[38 => This sets foreground color
https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
ESC[38;2; => Set foreground color with 24-bit color mode
https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit
ESC[0m => Resets foreground color (basically turn off "coloring mode")
{r};{g};{b};m => Sets the color mode. "m" denotes the end of the escape sequence prefix
For more information and colors, see
https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
"""
escape_color_24bitmode = "\x1b[38;2"
reset_color = "\x1b[0m"
return f"{escape_color_24bitmode};{r};{g};{b}m{text}{reset_color}"

@classmethod
def removed(cls, text: str) -> str:
return cls.colorize_text(255, 0, 0, text)

@classmethod
def added(cls, text: str) -> str:
return cls.colorize_text(0, 255, 0, text)

@classmethod
def visual_diff(cls, a: str, b: str):
"""
Prints git-like colored diff using ANSI terminal coloring.
Diff is "from a to b", that is, red text is text deleted in `a`
while green text is new to `b`
"""
if "true" != os.environ.get("COLORED_DIFF", "false").lower():
return "".join(difflib.context_diff(a, b))

colored_diff = []
diff_partitions = difflib.SequenceMatcher(None, a, b)
for operation, a_start, a_end, b_start, b_end in diff_partitions.get_opcodes():
if operation == "equal":
colored_diff.append(a[a_start:a_end])
elif operation == "insert":
colored_diff.append(cls.added(b[b_start:b_end]))
elif operation == "delete":
colored_diff.append(cls.removed(a[a_start:a_end]))
elif operation == "replace":
colored_diff.append(cls.added(b[b_start:b_end]))
colored_diff.append(cls.removed(a[a_start:a_end]))
else:
# Log.warn would be best here
raise ValueError(
f"Unhandled opcode from difflib in semantic conversion markdown renderer: {operation}"
)
return "".join(colored_diff)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
***
---
***************
*** 145,157 ****
A t r i b u t e- | --- 145,157 ----
A t+ t r i b u t e | ***************
*** 176,181 ****
--- 176,182 ----
o n + | E***************
*** 243,248 ****
--- 244,250 ----
- - -+ - | ***************
*** 280,292 ****
| ` b a r- .- f- o- o ` |--- 282,294 ----
| `+ f+ o+ o+ . b a r ` |***************
*** 311,316 ****
--- 313,319 ----
s u m+ z |
73 changes: 73 additions & 0 deletions semantic-conventions/src/tests/semconv/templating/test_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,79 @@ def test_attribute_templates(self):
def test_sorting(self):
self.check("markdown/sorting/")

def testVisualDiffer(self):
with open(
self.get_file_path("markdown/table_generation_conflict/input-1.md"),
encoding="utf8",
) as fin:
sample_1 = fin.read()
with open(
self.get_file_path("markdown/table_generation_conflict/input-2.md"),
encoding="utf8",
) as fin:
sample_2 = fin.read()
with open(
self.get_file_path(
"markdown/table_generation_conflict/expected-no-colors.md"
),
encoding="utf8",
) as fin:
expected = fin.read()
actual = VisualDiffer.visual_diff(sample_1, sample_2)
with open(
self.get_file_path(
"markdown/table_generation_conflict/expected-no-colors.md"
),
"w+",
encoding="utf8",
) as out:
out.writelines(actual)
self.assertEqual(expected, actual)

@patch.dict(os.environ, {"COLORED_DIFF": "false"})
def testVisualDifferExplicitNoColors(self):
with open(
self.get_file_path("markdown/table_generation_conflict/input-1.md"),
encoding="utf8",
) as fin:
sample_1 = fin.read()
with open(
self.get_file_path("markdown/table_generation_conflict/input-2.md"),
encoding="utf8",
) as fin:
sample_2 = fin.read()
with open(
self.get_file_path(
"markdown/table_generation_conflict/expected-no-colors.md"
),
encoding="utf8",
) as fin:
expected = fin.read()
actual = VisualDiffer.visual_diff(sample_1, sample_2)
self.assertEqual(expected, actual)

@patch.dict(os.environ, {"COLORED_DIFF": "true"})
def testColoredVisualDiffer(self):
with open(
self.get_file_path("markdown/table_generation_conflict/input-1.md"),
encoding="utf8",
) as fin:
sample_1 = fin.read()
with open(
self.get_file_path("markdown/table_generation_conflict/input-2.md"),
encoding="utf8",
) as fin:
sample_2 = fin.read()
with open(
self.get_file_path(
"markdown/table_generation_conflict/expected-with-colors.md",
),
encoding="utf8",
) as fin:
expected = fin.read()
actual = VisualDiffer.visual_diff(sample_1, sample_2)
self.assertEqual(expected, actual)

def check(
self,
input_dir: str,
Expand Down

0 comments on commit 1bdd500

Please sign in to comment.