Switch from pkgutil to importlib.resources.
For loading resources, use `importlib.resources.files()` instead of
`pkgutil.get_data()`. This works across project boundaries with Bazel
7, as well as through the `embossc` driver.
Also packaged resource loading into a utility function, so that
further changes can be more easily accomodated.
diff --git a/compiler/back_end/cpp/BUILD b/compiler/back_end/cpp/BUILD
index 3d31ec2..427b724 100644
--- a/compiler/back_end/cpp/BUILD
+++ b/compiler/back_end/cpp/BUILD
@@ -53,6 +53,7 @@
"//compiler/util:ir_pb2",
"//compiler/util:ir_util",
"//compiler/util:name_conversion",
+ "//compiler/util:resources",
],
)
diff --git a/compiler/back_end/cpp/header_generator.py b/compiler/back_end/cpp/header_generator.py
index 922d80b..a761bde 100644
--- a/compiler/back_end/cpp/header_generator.py
+++ b/compiler/back_end/cpp/header_generator.py
@@ -29,11 +29,11 @@
from compiler.util import ir_pb2
from compiler.util import ir_util
from compiler.util import name_conversion
+from compiler.util import resources
from compiler.util import traverse_ir
-_TEMPLATES = code_template.parse_templates(pkgutil.get_data(
- "compiler.back_end.cpp",
- "generated_code_templates").decode(encoding="UTF-8"))
+_TEMPLATES = code_template.parse_templates(resources.load(
+ "compiler.back_end.cpp", "generated_code_templates"))
_CPP_RESERVED_WORDS = set((
# C keywords. A few of these are not (yet) C++ keywords, but some compilers
diff --git a/compiler/front_end/BUILD b/compiler/front_end/BUILD
index 024524d..776efed 100644
--- a/compiler/front_end/BUILD
+++ b/compiler/front_end/BUILD
@@ -98,6 +98,7 @@
":lr1",
":module_ir",
":tokenizer",
+ "//compiler/util:resources",
"//compiler/util:simple_memoizer",
],
)
@@ -137,6 +138,7 @@
"//compiler/util:ir_pb2",
"//compiler/util:error",
"//compiler/util:parser_types",
+ "//compiler/util:resources",
],
)
@@ -322,6 +324,7 @@
"//compiler/util:ir_pb2",
"//compiler/util:error",
"//compiler/util:ir_util",
+ "//compiler/util:resources",
"//compiler/util:traverse_ir",
],
)
diff --git a/compiler/front_end/constraints.py b/compiler/front_end/constraints.py
index 6beaf31..5f67d7c 100644
--- a/compiler/front_end/constraints.py
+++ b/compiler/front_end/constraints.py
@@ -14,12 +14,11 @@
"""Routines to check miscellaneous constraints on the IR."""
-import pkgutil
-
from compiler.front_end import attributes
from compiler.util import error
from compiler.util import ir_pb2
from compiler.util import ir_util
+from compiler.util import resources
from compiler.util import traverse_ir
@@ -394,9 +393,8 @@
global _RESERVED_WORDS
_RESERVED_WORDS = {}
language = None
- for line in pkgutil.get_data(
- "compiler.front_end",
- "reserved_words").decode(encoding="UTF-8").splitlines():
+ for line in resources.load(
+ "compiler.front_end", "reserved_words").splitlines():
stripped_line = line.partition("#")[0].strip()
if not stripped_line:
continue
diff --git a/compiler/front_end/glue.py b/compiler/front_end/glue.py
index c19385d..0dceaf9 100644
--- a/compiler/front_end/glue.py
+++ b/compiler/front_end/glue.py
@@ -19,7 +19,6 @@
"""
import collections
-import pkgutil
from compiler.front_end import attribute_checker
from compiler.front_end import constraints
@@ -36,6 +35,7 @@
from compiler.util import error
from compiler.util import ir_pb2
from compiler.util import parser_types
+from compiler.util import resources
_IrDebugInfo = collections.namedtuple("IrDebugInfo", ["ir", "debug_info",
"errors"])
@@ -202,9 +202,7 @@
def get_prelude():
"""Returns the module IR and debug info of the Emboss Prelude."""
return parse_module_text(
- pkgutil.get_data("compiler.front_end",
- "prelude.emb").decode(encoding="UTF-8"),
- "")
+ resources.load("compiler.front_end", "prelude.emb"), "")
def parse_emboss_file(file_name, file_reader, stop_before_step=None):
diff --git a/compiler/front_end/parser.py b/compiler/front_end/parser.py
index 600b644..6ece324 100644
--- a/compiler/front_end/parser.py
+++ b/compiler/front_end/parser.py
@@ -14,11 +14,10 @@
"""Routines to generate a shift-reduce parser from the module_ir module."""
-import pkgutil
-
from compiler.front_end import lr1
from compiler.front_end import module_ir
from compiler.front_end import tokenizer
+from compiler.util import resources
from compiler.util import simple_memoizer
@@ -104,9 +103,8 @@
@simple_memoizer.memoize
def _load_module_parser():
- path = "compiler.front_end"
error_examples = parse_error_examples(
- pkgutil.get_data(path, "error_examples").decode("utf-8"))
+ resources.load("compiler.front_end", "error_examples"))
return generate_parser(module_ir.START_SYMBOL, module_ir.PRODUCTIONS,
error_examples)
diff --git a/compiler/util/BUILD b/compiler/util/BUILD
index 4c34cc1..d0e3d3f 100644
--- a/compiler/util/BUILD
+++ b/compiler/util/BUILD
@@ -167,3 +167,9 @@
":name_conversion",
],
)
+
+py_library(
+ name = "resources",
+ srcs = ["resources.py"],
+ deps = [],
+)
diff --git a/compiler/util/resources.py b/compiler/util/resources.py
new file mode 100644
index 0000000..606b1d9
--- /dev/null
+++ b/compiler/util/resources.py
@@ -0,0 +1,23 @@
+# Copyright 2024 Google LLC
+#
+# 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
+#
+# https://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.
+
+"""Routines to load resource files from within the compiler."""
+
+import importlib.resources
+
+def load(package, file, encoding="utf-8"):
+ """Returns the contents of `file` from the Python package loader."""
+ with importlib.resources.files(
+ package).joinpath(file).open("r", encoding=encoding) as f:
+ return f.read()