diff -Nru libcharon-4.8/build_for_ultimaker.sh libcharon-4.13.0/build_for_ultimaker.sh --- libcharon-4.8/build_for_ultimaker.sh 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/build_for_ultimaker.sh 2021-10-19 07:41:39.000000000 +0000 @@ -1,7 +1,5 @@ #!/bin/sh # -# SPDX-License-Identifier: AGPL-3.0+ -# # Copyright (C) 2019 Ultimaker B.V. # # SPDX-License-Identifier: LGPL-3.0+ diff -Nru libcharon-4.8/Charon/filetypes/GCodeFile.py libcharon-4.13.0/Charon/filetypes/GCodeFile.py --- libcharon-4.8/Charon/filetypes/GCodeFile.py 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/Charon/filetypes/GCodeFile.py 2021-10-19 07:41:39.000000000 +0000 @@ -96,7 +96,7 @@ @staticmethod def __insertKeyValuePair( metadata: Dict[str, Any], - key_elements: Union[str, List[str]], + key_elements: Any, value: Any ) -> Any: if not key_elements: @@ -151,7 +151,7 @@ # 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 diff -Nru libcharon-4.8/Charon/filetypes/GCodeSocket.py libcharon-4.13.0/Charon/filetypes/GCodeSocket.py --- libcharon-4.8/Charon/filetypes/GCodeSocket.py 1970-01-01 00:00:00.000000000 +0000 +++ libcharon-4.13.0/Charon/filetypes/GCodeSocket.py 2021-10-19 07:41:39.000000000 +0000 @@ -0,0 +1,81 @@ +# Copyright (c) 2021 Ultimaker B.V. +# libCharon is released under the terms of the LGPLv3 or higher. + +import socket +import struct +from io import BytesIO, SEEK_SET, SEEK_CUR + +from typing import Any, Dict, IO, Optional, List + +from Charon.filetypes.GCodeFile import GCodeFile +from urllib.parse import urlparse + + +## This class is used to read GCode stream that are served +# dynamically over a TCP connection. +class SocketFileStream(BytesIO): + def __init__(self, sock_object: socket.socket) -> None: + super().__init__() + self.current_line = 0 + self.__socket = sock_object + + def seekable(self) -> bool: + return True + + def seek(self, offset: int, whence: Optional[int] = None) -> int: + if whence is None or whence == SEEK_SET: + self.current_line = offset + elif whence == SEEK_CUR: + self.current_line += offset + else: + raise ValueError('Unsupported whence mode in seek: %d' % whence) + return offset + + def readline(self, _size: int = -1) -> bytes: + self.__socket.send(struct.pack('>I', self.current_line)) + line = b'' + char = b'' + + while char != b'\n': + char = self.__socket.recv(1) + line += char + + self.current_line += 1 + return line + + def read(self, _size: int = -1) -> bytes: + raise NotImplementedError("Only readline has been implemented") + + def readlines(self, _hint: int = -1) -> List[bytes]: + raise NotImplementedError("Only readline has been implemented") + + def tell(self) -> int: + raise NotImplementedError("Only readline has been implemented") + + def close(self) -> None: + self.__socket.close() + + def __iter__(self): + return self + + def __next__(self): + return self.readline() + + +class GCodeSocket(GCodeFile): + mime_type = "text/x-gcode-socket" + + MaximumHeaderLength = 100 + + def __init__(self) -> None: + super().__init__() + self.__stream = None # type: Optional[IO[bytes]] + self.__metadata = {} # type: Dict[str, Any] + self.__sock = None + + @staticmethod + def stream_handler(path: str, mode: str) -> IO: + url = urlparse(path) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((url.hostname, 1337)) + return SocketFileStream(sock) diff -Nru libcharon-4.8/Charon/filetypes/OpenPackagingConvention.py libcharon-4.13.0/Charon/filetypes/OpenPackagingConvention.py --- libcharon-4.8/Charon/filetypes/OpenPackagingConvention.py 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/Charon/filetypes/OpenPackagingConvention.py 2021-10-19 07:41:39.000000000 +0000 @@ -25,7 +25,7 @@ _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 = OrderedDict([]) # type: Dict[str, str] # A standard OPC file doest not have default aliases. These must be implemented in inherited classes. mime_type = "application/x-opc" @@ -298,7 +298,11 @@ # Replace all aliases. for regex, replacement in self._aliases.items(): - virtual_path = re.sub(regex, replacement, virtual_path) + if regex.startswith("/"): + expression = r"^" + regex + else: + expression = regex + virtual_path = re.sub(expression, replacement, virtual_path) return virtual_path diff -Nru libcharon-4.8/Charon/VirtualFile.py libcharon-4.13.0/Charon/VirtualFile.py --- libcharon-4.8/Charon/VirtualFile.py 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/Charon/VirtualFile.py 2021-10-19 07:41:39.000000000 +0000 @@ -8,18 +8,21 @@ from Charon.filetypes.UltimakerFormatPackage import UltimakerFormatPackage from Charon.filetypes.GCodeFile import GCodeFile from Charon.filetypes.GCodeGzFile import GCodeGzFile +from Charon.filetypes.GCodeSocket import GCodeSocket extension_to_mime = { ".ufp": "application/x-ufp", ".gcode": "text/x-gcode", ".gz": "text/x-gcode-gz", - ".gcode.gz": "text/x-gcode-gz" + ".gcode.gz": "text/x-gcode-gz", + ".gsock": "text/x-gcode-socket" } mime_to_implementation = { "application/x-ufp": UltimakerFormatPackage, "text/x-gcode": GCodeFile, - "text/x-gcode-gz": GCodeGzFile + "text/x-gcode-gz": GCodeGzFile, + "text/x-gcode-socket": GCodeSocket } diff -Nru libcharon-4.8/ci/mypy.sh libcharon-4.13.0/ci/mypy.sh --- libcharon-4.8/ci/mypy.sh 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/ci/mypy.sh 2021-10-19 07:41:39.000000000 +0000 @@ -8,7 +8,7 @@ echo "Testing ${MYPY_FILES}" for file in ${MYPY_FILES} ; do echo "Mypying ${file}" - mypy --config-file=mypy.ini --cache-dir=/dev/null "${file}" + mypy --config-file=mypy.ini --follow-imports=skip --cache-dir=/dev/null "${file}" done fi diff -Nru libcharon-4.8/CMakeLists.txt libcharon-4.13.0/CMakeLists.txt --- libcharon-4.8/CMakeLists.txt 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/CMakeLists.txt 2021-10-19 07:41:39.000000000 +0000 @@ -12,7 +12,7 @@ set(Python3_VERSION_MINOR ${PYTHON_VERSION_MINOR}) else() # Use FindPython3 for CMake >=3.12 - find_package(Python3 3.4 REQUIRED COMPONENTS Interpreter) + find_package(Python3 ${CURA_PYTHON_VERSION} EXACT REQUIRED COMPONENTS Interpreter) endif() option(INSTALL_SERVICE "Install the Charon DBus-service" ON) diff -Nru libcharon-4.8/CPackConfig.cmake libcharon-4.13.0/CPackConfig.cmake --- libcharon-4.8/CPackConfig.cmake 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/CPackConfig.cmake 2021-10-19 07:41:39.000000000 +0000 @@ -1,5 +1,5 @@ set(CPACK_PACKAGE_VENDOR "Ultimaker") -set(CPACK_PACKAGE_CONTACT "Ruben Dulek ") +set(CPACK_PACKAGE_CONTACT "Ultimaker ") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Library to read and write 3D printer related files including G-Code and Ultimaker File Package.") set(CPACK_PACKAGE_VERSION_MAJOR 1) set(CPACK_PACKAGE_VERSION_MINOR 0) diff -Nru libcharon-4.8/debian/changelog libcharon-4.13.0/debian/changelog --- libcharon-4.8/debian/changelog 2021-10-17 13:59:05.000000000 +0000 +++ libcharon-4.13.0/debian/changelog 2022-01-14 08:07:02.000000000 +0000 @@ -1,8 +1,9 @@ -libcharon (4.8-1build1) jammy; urgency=medium +libcharon (4.13.0-1) unstable; urgency=medium - * No-change rebuild to add python3.10. + * Fix GitHub watch file. + * New upstream version 4.13.0. - -- Matthias Klose Sun, 17 Oct 2021 15:59:05 +0200 + -- Christoph Berg Fri, 14 Jan 2022 09:07:02 +0100 libcharon (4.8-1) unstable; urgency=medium diff -Nru libcharon-4.8/debian/watch libcharon-4.13.0/debian/watch --- libcharon-4.8/debian/watch 2020-11-13 15:26:49.000000000 +0000 +++ libcharon-4.13.0/debian/watch 2022-01-14 08:02:55.000000000 +0000 @@ -1,3 +1,3 @@ version=4 opts=uversionmangle=s/-beta/~beta/ \ -https://github.com/Ultimaker/libCharon/tags .*/archive/(\d\.\S+)\.tar\.gz +https://github.com/Ultimaker/libCharon/tags .*/(\d\.\S+)\.tar\.gz diff -Nru libcharon-4.8/.gitlab-ci.yml libcharon-4.13.0/.gitlab-ci.yml --- libcharon-4.8/.gitlab-ci.yml 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/.gitlab-ci.yml 2021-10-19 07:41:39.000000000 +0000 @@ -3,21 +3,6 @@ ref: master file: /gitlab_ci_templates/jedi-gitlab-ci-template.yml -# Prepare stage, prepares a Docker image based on the Docker file in /docker_env subfolder of the repository. -# To have early feedback when setting up your Docker image, make sure you implement a buildenv_check.sh script, -# see the exeample in this repository. -# ================================================================================== - -prepare_environment: - extends: - - .jobs_common - - .environment_common - stage: prepare - variables: - GIT_STRATEGY: clone - script: - - ./make_docker.sh "${BUILD_PIPELINE_IMAGE}" - complexity: extends: - .jobs_common diff -Nru libcharon-4.8/make_docker.sh libcharon-4.13.0/make_docker.sh --- libcharon-4.8/make_docker.sh 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/make_docker.sh 2021-10-19 07:41:39.000000000 +0000 @@ -1,7 +1,5 @@ #!/bin/sh # -# SPDX-License-Identifier: AGPL-3.0+ -# # Copyright (C) 2019 Ultimaker B.V. # # SPDX-License-Identifier: LGPL-3.0+ diff -Nru libcharon-4.8/mypy.ini libcharon-4.13.0/mypy.ini --- libcharon-4.8/mypy.ini 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/mypy.ini 2021-10-19 07:41:39.000000000 +0000 @@ -1,4 +1,5 @@ [mypy] +python_version = 3.4 disallow_untyped_calls = False disallow_untyped_defs = False disallow_incomplete_defs = False diff -Nru libcharon-4.8/setup.py libcharon-4.13.0/setup.py --- libcharon-4.8/setup.py 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/setup.py 2021-10-19 07:41:39.000000000 +0000 @@ -8,7 +8,7 @@ version = "1.0", description = "Library to read and write file packages.", author = "Ultimaker", - author_email = "r.dulek@ultimaker.com", + author_email = "plugins@ultimaker.com", url = "https://github.com/Ultimaker/libCharon", packages = ["Charon", "Charon.Client", "Charon.Service", "Charon.filetypes"] ) diff -Nru libcharon-4.8/tests/filetypes/TestOpenPackagingConvention.py libcharon-4.13.0/tests/filetypes/TestOpenPackagingConvention.py --- libcharon-4.8/tests/filetypes/TestOpenPackagingConvention.py 2020-04-16 10:34:42.000000000 +0000 +++ libcharon-4.13.0/tests/filetypes/TestOpenPackagingConvention.py 2021-10-19 07:41:39.000000000 +0000 @@ -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. @@ -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 @@ -26,7 +28,7 @@ # 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 @@ -38,7 +40,7 @@ # 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 @@ -89,6 +91,29 @@ 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"])