Skip to content

Commit 29ecb83

Browse files
authored
Merge pull request #25 from bnusunny/fix/issue-24-unicode-file-paths
fix: handle non-ASCII file paths in build graph (closes #24)
2 parents 5486e43 + 600d795 commit 29ecb83

2 files changed

Lines changed: 81 additions & 4 deletions

File tree

samcli/lib/build/build_graph.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ def _write_source_hash(
378378
if not self._filepath.exists():
379379
open(self._filepath, "a+").close() # pylint: disable=consider-using-with
380380

381-
txt = self._filepath.read_text()
381+
txt = self._filepath.read_text(encoding="utf-8")
382382
# .loads() returns a TOMLDocument,
383383
# and it behaves like a standard dictionary according to https://github.com/sdispater/tomlkit.
384384
# in tomlkit 0.7.2, the types are broken (tomlkit#128, #130, #134) so here we convert it to Dict.
@@ -400,7 +400,7 @@ def _write_source_hash(
400400
layer_build_definition[MANIFEST_HASH_FIELD] = hashing_info.manifest_hash
401401
LOG.info("Updated source_hash and manifest_hash field in build.toml for layer with UUID %s", layer_uuid)
402402

403-
self._filepath.write_text(tomlkit.dumps(cast(TOMLDocument, document)))
403+
self._filepath.write_text(tomlkit.dumps(cast(TOMLDocument, document)), encoding="utf-8")
404404

405405
def _read(self) -> None:
406406
"""
@@ -412,7 +412,7 @@ def _read(self) -> None:
412412
self._layer_build_definitions = []
413413
document = {}
414414
try:
415-
txt = self._filepath.read_text()
415+
txt = self._filepath.read_text(encoding="utf-8")
416416
# .loads() returns a TOMLDocument,
417417
# and it behaves like a standard dictionary according to https://github.com/sdispater/tomlkit.
418418
# in tomlkit 0.7.2, the types are broken (tomlkit#128, #130, #134) so here we convert it to Dict.
@@ -470,7 +470,7 @@ def _write(self) -> None:
470470
if not self._filepath.exists():
471471
open(self._filepath, "a+").close() # pylint: disable=consider-using-with
472472

473-
self._filepath.write_text(tomlkit.dumps(document))
473+
self._filepath.write_text(tomlkit.dumps(document), encoding="utf-8")
474474

475475
def _atomic_write(self) -> None:
476476
"""

tests/unit/lib/build_module/test_build_graph.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,83 @@ def test_get_function_build_definition_with_logical_id(self):
691691
)
692692

693693

694+
class TestBuildGraphNonAsciiPaths(TestCase):
695+
"""Regression tests for issue #24: non-ASCII file paths in build graph."""
696+
697+
NON_ASCII_CODEURI = "src/données"
698+
UUID = "3c1c254e-cd4b-4d94-8c74-7ab870b36063"
699+
LAYER_UUID = "7dnc257e-cd4b-4d94-8c74-7ab870b3abc3"
700+
701+
BUILD_GRAPH_CONTENTS_NON_ASCII = f"""
702+
[function_build_definitions]
703+
[function_build_definitions.{UUID}]
704+
codeuri = "{NON_ASCII_CODEURI}"
705+
runtime = "python3.8"
706+
source_hash = "abc123"
707+
manifest_hash = "def456"
708+
packagetype = "{ZIP}"
709+
architecture = "{X86_64}"
710+
handler = "app.handler"
711+
functions = ["MyFunction"]
712+
713+
[layer_build_definitions]
714+
[layer_build_definitions.{LAYER_UUID}]
715+
layer_name = "MyLayer"
716+
codeuri = "{NON_ASCII_CODEURI}"
717+
build_method = "python3.8"
718+
compatible_runtimes = ["python3.8"]
719+
architecture = "{X86_64}"
720+
source_hash = "abc123"
721+
manifest_hash = "def456"
722+
layer = "MyLayer"
723+
"""
724+
725+
def test_read_build_graph_with_non_ascii_codeuri(self):
726+
with osutils.mkdir_temp() as temp_base_dir:
727+
build_dir = Path(temp_base_dir, ".aws-sam", "build")
728+
build_dir.mkdir(parents=True)
729+
build_graph_path = Path(build_dir.parent, "build.toml")
730+
build_graph_path.write_text(self.BUILD_GRAPH_CONTENTS_NON_ASCII, encoding="utf-8")
731+
732+
build_graph = BuildGraph(str(build_dir))
733+
734+
func_defs = list(build_graph.get_function_build_definitions())
735+
self.assertEqual(len(func_defs), 1)
736+
self.assertEqual(func_defs[0].codeuri, self.NON_ASCII_CODEURI)
737+
738+
layer_defs = list(build_graph.get_layer_build_definitions())
739+
self.assertEqual(len(layer_defs), 1)
740+
self.assertEqual(layer_defs[0].codeuri, self.NON_ASCII_CODEURI)
741+
742+
def test_write_and_read_build_graph_with_non_ascii_codeuri(self):
743+
with osutils.mkdir_temp() as temp_base_dir:
744+
build_dir = Path(temp_base_dir, ".aws-sam", "build")
745+
build_dir.mkdir(parents=True)
746+
747+
build_graph = BuildGraph(str(build_dir))
748+
func_def = FunctionBuildDefinition(
749+
"python3.8", self.NON_ASCII_CODEURI, None, ZIP, X86_64, {}, "app.handler", "abc123", "def456"
750+
)
751+
function = generate_function(runtime="python3.8", codeuri=self.NON_ASCII_CODEURI)
752+
build_graph.put_function_build_definition(func_def, function)
753+
754+
layer_def = LayerBuildDefinition(
755+
"MyLayer", self.NON_ASCII_CODEURI, "python3.8", ["python3.8"], "abc123", "def456"
756+
)
757+
layer = generate_layer(compatible_runtimes=["python3.8"], codeuri=self.NON_ASCII_CODEURI)
758+
build_graph.put_layer_build_definition(layer_def, layer)
759+
760+
build_graph.clean_redundant_definitions_and_update(True)
761+
762+
# Read it back
763+
build_graph2 = BuildGraph(str(build_dir))
764+
func_defs = list(build_graph2.get_function_build_definitions())
765+
self.assertEqual(func_defs[0].codeuri, self.NON_ASCII_CODEURI)
766+
767+
layer_defs = list(build_graph2.get_layer_build_definitions())
768+
self.assertEqual(layer_defs[0].codeuri, self.NON_ASCII_CODEURI)
769+
770+
694771
class TestBuildDefinition(TestCase):
695772
def test_single_function_should_return_function_and_handler_name(self):
696773
build_definition = FunctionBuildDefinition(

0 commit comments

Comments
 (0)