Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Compatibility with EmPy 4 #627

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 56 additions & 14 deletions colcon_core/shell/template/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@
import os

from colcon_core.logging import colcon_logger

# The complicated import below is meant to handle 3 things:
# 1. Empy 4 - the newest version as of 2024-08-07, which has a different
# API from Empy 3.
# 2. Empy 3 - the version available since 2003.
# 3. The ancient "em" tool, which has no relation to what we are doing here
# but sadly shares the "em" package name with empy. We can't use that
# package, but we detect if it is installed.

try:
# Empy 4 and Empy 3 have the Interpreter object, while "em" does not.
from em import Interpreter
from em import OVERRIDE_OPT
except ImportError as e:
try:
import em # noqa: F401
Expand All @@ -18,6 +27,15 @@
'not be installed since both packages share the same namespace'
raise e from None

try:
# Only Empy 4 has the Configuration object
from em import Configuration
em_has_configuration = True
except ImportError:

Check warning on line 34 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L34

Added line #L34 was not covered by tests
# We have Empy 3
from em import OVERRIDE_OPT
em_has_configuration = False

Check warning on line 37 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L36-L37

Added lines #L36 - L37 were not covered by tests

logger = colcon_logger.getChild(__name__)


Expand All @@ -33,13 +51,25 @@
:raises: Any exception which `em.Interpreter.string` might raise
"""
output = StringIO()
interpreter = None
try:
# disable OVERRIDE_OPT to avoid saving / restoring stdout
interpreter = CachingInterpreter(
output=output, options={OVERRIDE_OPT: False})
if em_has_configuration:
config = Configuration(
defaultRoot=str(template_path),
defaultStdout=output,
useProxy=False)
interpreter = CachingInterpreter(config=config, dispatcher=False)
else:
# disable OVERRIDE_OPT to avoid saving / restoring stdout
interpreter = CachingInterpreter(

Check warning on line 64 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L64

Added line #L64 was not covered by tests
output=output, options={OVERRIDE_OPT: False})
with template_path.open('r') as h:
content = h.read()
interpreter.string(content, str(template_path), locals=data)
if em_has_configuration:
interpreter.string(content, locals=data)
else:
interpreter.string(content, str(template_path), locals=data)

Check warning on line 71 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L71

Added line #L71 was not covered by tests

output = output.getvalue()
except Exception as e: # noqa: F841
logger.error(
Expand All @@ -54,21 +84,27 @@
with destination_path.open('w') as h:
h.write(output)
finally:
interpreter.shutdown()
if interpreter is not None:
interpreter.shutdown()


class BypassStdoutInterpreter(Interpreter):
"""Interpreter for EmPy which keeps `stdout` unchanged."""
cached_tokens = {}

def installProxy(self): # noqa: D102 N802
# avoid replacing stdout with ProxyFile
pass
empy_inheritance = None
if em_has_configuration:
empy_inheritance = Interpreter
else:
class BypassStdoutInterpreter(Interpreter):
"""Interpreter for EmPy which keeps `stdout` unchanged."""

def installProxy(self): # noqa: D102 N802

Check warning on line 100 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L100

Added line #L100 was not covered by tests
# avoid replacing stdout with ProxyFile
pass

Check warning on line 102 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L102

Added line #L102 was not covered by tests

cached_tokens = {}
empy_inheritance = BypassStdoutInterpreter

Check warning on line 104 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L104

Added line #L104 was not covered by tests


class CachingInterpreter(BypassStdoutInterpreter):
class CachingInterpreter(empy_inheritance):
"""Interpreter for EmPy which which caches parsed tokens."""

def parse(self, scanner, locals=None): # noqa: A002 D102
Expand All @@ -90,4 +126,10 @@
self.invoke('atParse', scanner=scanner, locals=locals)
for token in tokens:
self.invoke('atToken', token=token)
token.run(self, locals)
if em_has_configuration:
self.run(token, locals)
scanner.accumulate()
else:
token.run(self, locals)

Check warning on line 133 in colcon_core/shell/template/__init__.py

View check run for this annotation

Codecov / codecov/patch

colcon_core/shell/template/__init__.py#L133

Added line #L133 was not covered by tests
if em_has_configuration:
return True
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ python_requires = >=3.6
install_requires =
coloredlogs; sys_platform == 'win32'
distlib
EmPy<4
EmPy
importlib-metadata; python_version < "3.8"
packaging
# the pytest dependency and its extensions are provided for convenience
Expand Down
Loading