Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CS-2323 _aliases: Do not replace non-top-level directories #34

Merged
merged 5 commits into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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("/"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome :P

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()
CoenSchalkwijk marked this conversation as resolved.
Show resolved Hide resolved
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