From 65e90c3aa9e6e64d19cfb82af6eb9137157d8ade Mon Sep 17 00:00:00 2001 From: SHIVANSH-ux-ys Date: Fri, 30 Oct 2026 19:39:19 +0530 Subject: [PATCH] fix(parser): disable PLY table writing to support read-only filesystems (#838) By default, PLY yacc attempts to write cached parsing tables to `parsetab.py` and log debug tables to `parser.out`. On read-only filesystems (e.g. inside container images, serverless environments, or read-only volume mounts), this triggers spurious warnings and `OSError: [Errno 30] Read-only file system`. Setting `write_tables=False` and `debug=False` by default in `Parser.__init__` disables table file generation while constructing the parser in-memory (~4ms), allowing `Parser` to run seamlessly in read-only environments while still allowing callers to override via kwargs if desired. Fixes #838 Signed-off-by: SHIVANSH-ux-ys --- src/spdx_tools/spdx/parser/tagvalue/parser.py | 2 ++ .../parser/tagvalue/test_tag_value_parser.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/spdx_tools/spdx/parser/tagvalue/parser.py b/src/spdx_tools/spdx/parser/tagvalue/parser.py index 50096bda2..2fd803b3e 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/parser.py @@ -91,6 +91,8 @@ def __init__(self, **kwargs): self.elements_built = dict() self.lex = SPDXLexer() self.lex.build(reflags=re.UNICODE) + kwargs.setdefault("write_tables", False) + kwargs.setdefault("debug", False) self.yacc = yacc.yacc(module=self, **kwargs) @grammar_rule("start : start attrib ") diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index c866e2726..8ccfd43b5 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -162,3 +162,20 @@ def test_parse_none_or_no_assertion_as_text(): assert package.summary == "NONE" assert package.license_concluded == SpdxNone() assert package.license_declared == SpdxNoAssertion() + + +def test_parser_init_does_not_write_tables(monkeypatch): + import builtins + + orig_open = builtins.open + + def mock_open(file, *args, **kwargs): + mode = args[0] if args else kwargs.get("mode", "r") + if str(file).endswith(("parsetab.py", "parser.out")) and any(m in mode for m in ("w", "a", "+")): + raise OSError(30, "Read-only file system") + return orig_open(file, *args, **kwargs) + + monkeypatch.setattr(builtins, "open", mock_open) + parser = Parser() + assert parser is not None +