Skip to content

Commit

Permalink
Merge pull request #34 from Ultimaker/CS-2323/do-not-replace-non-top-…
Browse files Browse the repository at this point in the history
…level-dirs

CS-2323 `_aliases`: Do not replace non-top-level directories
  • Loading branch information
Xiaozhou Li authored Sep 7, 2021
2 parents 3ce7b18 + c6c08c8 commit 6d6f1c7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 7 deletions.
4 changes: 2 additions & 2 deletions Charon/filetypes/GCodeFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def parseHeader(stream: IO[bytes], *, prefix: str = "") -> Dict[str, Any]:
@staticmethod
def __insertKeyValuePair(
metadata: Dict[str, Any],
key_elements: Union[str, List[str]],
key_elements: Any,
value: Any
) -> Any:
if not key_elements:
Expand Down Expand Up @@ -151,7 +151,7 @@ def __cleanGriffinHeader(metadata: Dict[str, Any]) -> None:
# must exist on the location of that key element
# @return True if the key is available and not empty
@staticmethod
def __isAvailable(metadata: Dict[str, Any], keys: List[str]) -> None:
def __isAvailable(metadata: Dict[str, Any], keys: List[Any]) -> bool:
if not keys:
return True

Expand Down
8 changes: 6 additions & 2 deletions Charon/filetypes/OpenPackagingConvention.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class OpenPackagingConvention(FileInterface):
_global_metadata_file = "/Metadata/OPC_Global.json" # Where the global metadata file is.
_opc_metadata_relationship_type = "http://schemas.ultimaker.org/package/2018/relationships/opc_metadata" # Unique identifier of the relationship type that relates OPC metadata to files.
_metadata_prefix = "/metadata"
_aliases = OrderedDict([]) # A standard OPC file doest not have default aliases. These must be implemented in inherited classes.
_aliases:Dict[str, str] = OrderedDict([]) # A standard OPC file doest not have default aliases. These must be implemented in inherited classes.

mime_type = "application/x-opc"

Expand Down Expand Up @@ -298,7 +298,11 @@ def _processAliases(self, virtual_path: str) -> str:

# Replace all aliases.
for regex, replacement in self._aliases.items():
virtual_path = re.sub(regex, replacement, virtual_path)
if regex.startswith("/"):
expression = rf"^{regex}"
else:
expression = regex
virtual_path = re.sub(expression, replacement, virtual_path)

return virtual_path

Expand Down
31 changes: 28 additions & 3 deletions tests/filetypes/TestOpenPackagingConvention.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import pytest #This module contains unit tests.
import zipfile #To inspect the contents of the zip archives.
import xml.etree.ElementTree as ET #To inspect the contents of the OPC-spec files in the archives.
from collections import OrderedDict
from typing import List, Generator

from Charon.filetypes.OpenPackagingConvention import OpenPackagingConvention, OPCError # The class we're testing.
from Charon.OpenMode import OpenMode #To open archives.
Expand All @@ -14,7 +16,7 @@
# The package has no resources at all, so reading from it will not find
# anything.
@pytest.fixture()
def empty_read_opc() -> OpenPackagingConvention:
def empty_read_opc() -> Generator[OpenPackagingConvention, None, None]:
result = OpenPackagingConvention()
result.openStream(open(os.path.join(os.path.dirname(__file__), "resources", "empty.opc"), "rb"))
yield result
Expand All @@ -26,7 +28,7 @@ def empty_read_opc() -> OpenPackagingConvention:
# The file is called "hello.txt" and contains the text "Hello world!" encoded
# in UTF-8.
@pytest.fixture()
def single_resource_read_opc() -> OpenPackagingConvention:
def single_resource_read_opc() -> Generator[OpenPackagingConvention, None, None]:
result = OpenPackagingConvention()
result.openStream(open(os.path.join(os.path.dirname(__file__), "resources", "hello.opc"), "rb"))
yield result
Expand All @@ -38,7 +40,7 @@ def single_resource_read_opc() -> OpenPackagingConvention:
# Note that you can't really test the output of the write since you don't have
# the stream it writes to.
@pytest.fixture()
def empty_write_opc() -> OpenPackagingConvention:
def empty_write_opc() -> Generator[OpenPackagingConvention, None, None]:
result = OpenPackagingConvention()
result.openStream(io.BytesIO(), "application/x-opc", OpenMode.WriteOnly)
yield result
Expand Down Expand Up @@ -89,6 +91,29 @@ def test_cycleSetDataGetData(virtual_path: str):
assert result[virtual_path] == test_data #The data itself is still correct.


@pytest.mark.parametrize("virtual_path, path_list", [
("/foo/materials", ["/foo/materials", "/[Content_Types].xml", "/_rels/.rels"]),
("/materials", ["/files/materials", "/[Content_Types].xml", "/_rels/.rels"])
])
def test_aliases_replacement(virtual_path: str, path_list: List[str]):
test_data = b"Let's see if we can read this data back."

stream = io.BytesIO()
package = OpenPackagingConvention()
package._aliases = OrderedDict([
(r"/materials", "/files/materials")
])
package.openStream(stream, mode = OpenMode.WriteOnly)
package.setData({virtual_path: test_data})
package.close()

stream.seek(0)
package = OpenPackagingConvention()
package.openStream(stream)
result = package.listPaths()

assert result == path_list

## Tests writing data via a stream to an archive, then reading it back via a
# stream.
@pytest.mark.parametrize("virtual_path", ["/dir/file", "/file", "/Metadata"])
Expand Down

0 comments on commit 6d6f1c7

Please sign in to comment.