Skip to content

Commit

Permalink
Merge branch 'master' into fix_blark
Browse files Browse the repository at this point in the history
  • Loading branch information
klauer authored Aug 22, 2023
2 parents fc913d5 + b6701db commit 78e9e97
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 6 deletions.
22 changes: 21 additions & 1 deletion whatrecord/bin/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"whatrecord parse" is used to parse and interpret any of whatrecord's supported
file formats, dumping the results to the console (standard output) in JSON
format, by default.
Unless ``--disable-macros`` is specified, all text will go through the macro
context as if the files were being loaded in an IOC shell.
"""

import argparse
Expand Down Expand Up @@ -67,6 +70,12 @@ def build_arg_parser(parser=None):
help="Macro to add, in the usual form ``macro=value,...``",
)

parser.add_argument(
"--disable-macros",
action="store_true",
help="Disable macro handling, leaving unexpanded macros in the output."
)

parser.add_argument(
"-o", "--output",
type=str,
Expand Down Expand Up @@ -105,6 +114,7 @@ def parse_from_cli_args(
dbd: Optional[str] = None,
standin_directory: Optional[List[str]] = None,
macros: Optional[str] = None,
disable_macros: bool = False,
use_gdb: bool = False,
format: Optional[str] = None,
expand: bool = False,
Expand All @@ -116,6 +126,9 @@ def parse_from_cli_args(
This variant uses the raw CLI arguments, mapping them on to those that
`parse` expects. For programmatic usage, please use ``parse()`` directly.
Unless ``disable_macros`` is set, all text will go through the macro
context as if the files were being loaded in an IOC shell.
Parameters
----------
filename : str or pathlib.Path
Expand All @@ -128,7 +141,11 @@ def parse_from_cli_args(
A list of substitute directories of the form ``DirectoryA=DirectoryB``.
macros : str, optional
Macro string to use when parsing the file.
Macro string to use when parsing the file. Ignored if
``disable_macros`` is set.
disable_macros : bool, optional
Disable macro handling, leaving unexpanded macros in the output.
expand : bool, optional
Expand a substitutions file.
Expand Down Expand Up @@ -163,6 +180,7 @@ def parse_from_cli_args(
dbd=dbd,
standin_directories=standin_directories,
macros=macros,
disable_macros=disable_macros,
use_gdb=use_gdb,
format=format,
expand=expand,
Expand All @@ -178,6 +196,7 @@ def main(
output_format: str = "json",
output: Optional[str] = None,
macros: Optional[str] = None,
disable_macros: bool = False,
use_gdb: bool = False,
expand: bool = False,
v3: bool = False,
Expand All @@ -187,6 +206,7 @@ def main(
dbd=dbd,
standin_directory=standin_directory,
macros=macros,
disable_macros=disable_macros,
use_gdb=use_gdb,
format=input_format,
expand=expand,
Expand Down
26 changes: 24 additions & 2 deletions whatrecord/macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@ def macros_from_string(
return macro_context.define_from_string(macro_string)


class PassthroughMacroContext(MacroContext):
"""
A stand-in MacroContext which performs no macro expansion.
That is, a pass-through/no-operation macro context.
"""

def expand(self, value: str, **_) -> str:
return value

def expand_by_line(self, contents: str, *, delimiter: str = "\n") -> str:
return delimiter.join(
line
for line in contents.splitlines()
)


@dataclasses.dataclass
class _SerializedMacroContext:
#: Show warnings
Expand All @@ -43,6 +60,8 @@ class _SerializedMacroContext:
string_encoding: str
#: The macros, including any environment variables (if use_environment set).
macros: Dict[str, str]
#: If the context is a passthrough one.
passthrough: bool


RE_MACRO_KEY_SKIP = []
Expand Down Expand Up @@ -124,6 +143,7 @@ def _serialize_macro_context(ctx: MacroContext) -> Dict[str, Any]:
show_warnings=ctx.show_warnings,
string_encoding=ctx.string_encoding,
macros=macros,
passthrough=isinstance(ctx, PassthroughMacroContext),
)
)

Expand All @@ -134,12 +154,14 @@ def _deserialize_macro_context(info: Dict[str, Any]) -> MacroContext:
_SerializedMacroContext,
info
)
return MacroContext(

cls = PassthroughMacroContext if obj.passthrough else MacroContext
return cls(
show_warnings=obj.show_warnings,
string_encoding=obj.string_encoding,
use_environment=False,
macros=obj.macros,
)


__all__ = ["MacroContext", "macros_from_string"]
__all__ = ["MacroContext", "PassthroughMacroContext", "macros_from_string"]
11 changes: 9 additions & 2 deletions whatrecord/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .db import Database
from .dbtemplate import TemplateSubstitution
from .gateway import PVList as GatewayPVList
from .macro import MacroContext
from .macro import MacroContext, PassthroughMacroContext
from .makefile import Makefile
from .shell import LoadedIoc
from .snl import SequencerProgram
Expand All @@ -39,6 +39,7 @@ def parse(
dbd: Optional[str] = None,
standin_directories: Optional[Dict[str, str]] = None,
macros: Optional[str] = None,
disable_macros: bool = False,
use_gdb: bool = False,
format: Optional[FileFormat] = None,
expand: bool = False,
Expand Down Expand Up @@ -67,6 +68,9 @@ def parse(
macros : str, optional
Macro string to use when parsing the file.
disable_macros : bool, optional
Disable macro handling, leaving unexpanded macros in the output.
expand : bool, optional
Expand a substitutions file.
Expand Down Expand Up @@ -95,7 +99,10 @@ def parse(
filename = pathlib.Path(filename)

# The shared macro context - used in different ways below:
macro_context = MacroContext(macro_string=macros or "")
if disable_macros:
macro_context = PassthroughMacroContext()
else:
macro_context = MacroContext(macro_string=macros or "")

if format is None:
format = FileFormat.from_filename(filename)
Expand Down
15 changes: 14 additions & 1 deletion whatrecord/tests/test_macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pytest

from .. import settings
from ..macro import MacroContext
from ..macro import MacroContext, PassthroughMacroContext


def test_skip_keys(monkeypatch):
Expand Down Expand Up @@ -46,8 +46,21 @@ def test_env_include_exclude(monkeypatch, include: bool):
monkeypatch.setattr(settings, "MACRO_INCLUDE_ENV", include)
ctx = MacroContext(use_environment=True)
keys = set(apischema.serialize(MacroContext, ctx)["macros"])
assert not apischema.serialize(MacroContext, ctx)["passthrough"]

if not include:
assert set(keys) == set()
else:
assert 0 < len(set(keys)) <= len(os.environ)


def test_passthrough():
ctx = PassthroughMacroContext()
assert ctx.expand("$(ABC)") == "$(ABC)"

serialized = apischema.serialize(MacroContext, ctx)
assert serialized["passthrough"]

deserialized = apischema.deserialize(MacroContext, serialized)
assert isinstance(deserialized, PassthroughMacroContext)
assert deserialized.expand("$(ABC)") == "$(ABC)"

0 comments on commit 78e9e97

Please sign in to comment.