diff --git a/specialist.py b/specialist.py index c7d305d..12ffc0a 100644 --- a/specialist.py +++ b/specialist.py @@ -36,6 +36,7 @@ def _audit_imports(event: str, args: "typing.Sequence[object]") -> None: import itertools import opcode import os +import re import runpy import shlex import sysconfig @@ -44,6 +45,7 @@ def _audit_imports(event: str, args: "typing.Sequence[object]") -> None: import typing import webbrowser +_RE_WHITESPACE = re.compile(r"(\s*\n\s*)") _FIRST_POSTION = (1, 0) _LAST_POSITION = (sys.maxsize, 0) _CACHE_FORMAT = frozenset(opcode._cache_format) # type: ignore [attr-defined] # pylint: disable = protected-access @@ -119,9 +121,13 @@ def add(self, source: str, stats: "_Stats") -> None: color = self._color(stats) attribute = "color" if self._dark else "background-color" source = html.escape(source) - if color != "#ffffff": - source = f"{source}" - self._parts.append(source) + if color == "#ffffff": + self._parts.append(source) + else: + for part in filter(None, _RE_WHITESPACE.split(source)): + if _RE_WHITESPACE.fullmatch(part) is None: + part = f"{part}" + self._parts.append(part) def emit(self) -> str: """Emit the HTML.""" diff --git a/test-data/output-blue/output-0-3-12.html b/test-data/output-blue/output-0-3-12.html index a62facc..88e382f 100644 --- a/test-data/output-blue/output-0-3-12.html +++ b/test-data/output-blue/output-0-3-12.html @@ -1,8 +1,8 @@
def encode_decode(key: str, text: str) -> str:
     out = []
-    for i, t in enumerate(text):
-        k = key[i % len(key)]
-        out.append(chr(ord(t) ^ ord(k)))
+    for i, t in enumerate(text):
+        k = key[i % len(key)]
+        out.append(chr(ord(t) ^ ord(k)))
     return "".join(out)
 
 if __name__ == "__main__":
diff --git a/test-data/output-blue/output-1-3-12.html b/test-data/output-blue/output-1-3-12.html
index 8baceea..32f407c 100644
--- a/test-data/output-blue/output-1-3-12.html
+++ b/test-data/output-blue/output-1-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-blue/output-2-3-12.html b/test-data/output-blue/output-2-3-12.html
index 10a78a8..188ce96 100644
--- a/test-data/output-blue/output-2-3-12.html
+++ b/test-data/output-blue/output-2-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-blue/output-3-3-12.html b/test-data/output-blue/output-3-3-12.html
index 401e01a..4bd4554 100644
--- a/test-data/output-blue/output-3-3-12.html
+++ b/test-data/output-blue/output-3-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-blue/output-4-3-12.html b/test-data/output-blue/output-4-3-12.html
index 7f44632..43135a9 100644
--- a/test-data/output-blue/output-4-3-12.html
+++ b/test-data/output-blue/output-4-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark-blue/output-0-3-12.html b/test-data/output-dark-blue/output-0-3-12.html
index 98dea1b..e44c3eb 100644
--- a/test-data/output-dark-blue/output-0-3-12.html
+++ b/test-data/output-dark-blue/output-0-3-12.html
@@ -1,8 +1,8 @@
 
def encode_decode(key: str, text: str) -> str:
     out = []
-    for i, t in enumerate(text):
-        k = key[i % len(key)]
-        out.append(chr(ord(t) ^ ord(k)))
+    for i, t in enumerate(text):
+        k = key[i % len(key)]
+        out.append(chr(ord(t) ^ ord(k)))
     return "".join(out)
 
 if __name__ == "__main__":
diff --git a/test-data/output-dark-blue/output-1-3-12.html b/test-data/output-dark-blue/output-1-3-12.html
index b35a1af..de623f5 100644
--- a/test-data/output-dark-blue/output-1-3-12.html
+++ b/test-data/output-dark-blue/output-1-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark-blue/output-2-3-12.html b/test-data/output-dark-blue/output-2-3-12.html
index 98acbe6..dec9750 100644
--- a/test-data/output-dark-blue/output-2-3-12.html
+++ b/test-data/output-dark-blue/output-2-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark-blue/output-3-3-12.html b/test-data/output-dark-blue/output-3-3-12.html
index 7321441..f3f04e7 100644
--- a/test-data/output-dark-blue/output-3-3-12.html
+++ b/test-data/output-dark-blue/output-3-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark-blue/output-4-3-12.html b/test-data/output-dark-blue/output-4-3-12.html
index c12553b..2a6d43c 100644
--- a/test-data/output-dark-blue/output-4-3-12.html
+++ b/test-data/output-dark-blue/output-4-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark/output-0-3-12.html b/test-data/output-dark/output-0-3-12.html
index 3f3eb77..e3bad25 100644
--- a/test-data/output-dark/output-0-3-12.html
+++ b/test-data/output-dark/output-0-3-12.html
@@ -1,8 +1,8 @@
 
def encode_decode(key: str, text: str) -> str:
     out = []
-    for i, t in enumerate(text):
-        k = key[i % len(key)]
-        out.append(chr(ord(t) ^ ord(k)))
+    for i, t in enumerate(text):
+        k = key[i % len(key)]
+        out.append(chr(ord(t) ^ ord(k)))
     return "".join(out)
 
 if __name__ == "__main__":
diff --git a/test-data/output-dark/output-1-3-12.html b/test-data/output-dark/output-1-3-12.html
index 118220c..a6be1be 100644
--- a/test-data/output-dark/output-1-3-12.html
+++ b/test-data/output-dark/output-1-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark/output-2-3-12.html b/test-data/output-dark/output-2-3-12.html
index 8eeadd2..87a8e9f 100644
--- a/test-data/output-dark/output-2-3-12.html
+++ b/test-data/output-dark/output-2-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark/output-3-3-12.html b/test-data/output-dark/output-3-3-12.html
index 2efe77d..0d13fef 100644
--- a/test-data/output-dark/output-3-3-12.html
+++ b/test-data/output-dark/output-3-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output-dark/output-4-3-12.html b/test-data/output-dark/output-4-3-12.html
index 9bd6f8f..39409f6 100644
--- a/test-data/output-dark/output-4-3-12.html
+++ b/test-data/output-dark/output-4-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output/output-0-3-12.html b/test-data/output/output-0-3-12.html
index 2dee727..7b56b1e 100644
--- a/test-data/output/output-0-3-12.html
+++ b/test-data/output/output-0-3-12.html
@@ -1,8 +1,8 @@
 
def encode_decode(key: str, text: str) -> str:
     out = []
-    for i, t in enumerate(text):
-        k = key[i % len(key)]
-        out.append(chr(ord(t) ^ ord(k)))
+    for i, t in enumerate(text):
+        k = key[i % len(key)]
+        out.append(chr(ord(t) ^ ord(k)))
     return "".join(out)
 
 if __name__ == "__main__":
diff --git a/test-data/output/output-1-3-12.html b/test-data/output/output-1-3-12.html
index da6a63b..34e97b6 100644
--- a/test-data/output/output-1-3-12.html
+++ b/test-data/output/output-1-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output/output-2-3-12.html b/test-data/output/output-2-3-12.html
index 7422a88..161a0f2 100644
--- a/test-data/output/output-2-3-12.html
+++ b/test-data/output/output-2-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output/output-3-3-12.html b/test-data/output/output-3-3-12.html
index b4b244b..c5ecff3 100644
--- a/test-data/output/output-3-3-12.html
+++ b/test-data/output/output-3-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test-data/output/output-4-3-12.html b/test-data/output/output-4-3-12.html
index 1129188..a0ab976 100644
--- a/test-data/output/output-4-3-12.html
+++ b/test-data/output/output-4-3-12.html
@@ -13,8 +13,8 @@
 TEST_VALUES = [-459.67, -273.15, 0.0, 32.0, 42.0, 273.15, 100.0, 212.0, 373.15]
 
 def test_conversions() -> None:
-    for t in TEST_VALUES:
-        assert_round_trip(t)
+    for t in TEST_VALUES:
+        assert_round_trip(t)
 
 def assert_round_trip(t: float) -> None:
     # Round-trip Fahrenheit through Celsius:
diff --git a/test_specialist.py b/test_specialist.py
index c3a80d9..f2a499b 100644
--- a/test_specialist.py
+++ b/test_specialist.py
@@ -291,6 +291,41 @@ def test_main_targets_output_c(tmp_path: pathlib.Path) -> None:
         assert actual.read_text() == expected.read_text()
 
 
+def test_main_leading_and_trailing_whitespace() -> None:
+    """$ specialist -c 'pass'"""
+
+    if sys.version_info < (3, 12):
+        expected = (
+            "
[i \n*\n i for i in range(100)]"
+        )
+    else:
+        expected = (
+            "
[i \n*\n i for i in range(100)]"
+        )
+    with assert_browses([expected]):
+        no_trace_main(["-c", "[i \n*\n i for i in range(100)]"])
+
+
 def test_main_package() -> None:
     """$ specialist -m test-data.input-package"""
     if sys.version_info < (3, 12):