amulet-zlib 1.0.0a0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,92 @@
1
+ cmake_minimum_required(VERSION 3.13)
2
+
3
+ project(amulet_zlib LANGUAGES CXX)
4
+
5
+ # Set C++20
6
+ set(CMAKE_CXX_STANDARD 20)
7
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
8
+ set(CMAKE_CXX_EXTENSIONS OFF)
9
+
10
+ # Set platform variables
11
+ if (WIN32)
12
+ # set windows 7 as the minimum version
13
+ add_definitions(-D_WIN32_WINNT=0x0601)
14
+ elseif(APPLE)
15
+ set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
16
+ else()
17
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
18
+ endif()
19
+
20
+ if (MSVC)
21
+ add_definitions("/MP")
22
+ endif()
23
+
24
+ include(FetchContent)
25
+
26
+ # Add zlib
27
+ set(ZLIB_BUILD_EXAMPLES OFF)
28
+ FetchContent_Declare(
29
+ zlib
30
+ GIT_REPOSITORY https://github.com/madler/zlib.git
31
+ GIT_TAG 51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf
32
+ )
33
+ FetchContent_MakeAvailable(zlib)
34
+ set(ZLIB_ROOT ${zlib_SOURCE_DIR})
35
+ set(ZLIB_USE_STATIC_LIBS ON)
36
+ set(ZLIB_LIBRARY ${INSTALL_LIB_DIR})
37
+ find_package(ZLIB REQUIRED)
38
+ target_compile_definitions(zlibstatic PUBLIC ZLIB_CONST)
39
+
40
+ # Add pybind11
41
+ find_package(pybind11 CONFIG REQUIRED)
42
+ find_package(amulet_pybind11_extensions CONFIG REQUIRED)
43
+
44
+ # Find C++ files
45
+ file(REAL_PATH src SOURCE_PATH)
46
+ file(GLOB_RECURSE SOURCES LIST_DIRECTORIES false ${SOURCE_PATH}/amulet/*.cpp)
47
+ file(GLOB_RECURSE HEADERS LIST_DIRECTORIES false ${SOURCE_PATH}/amulet/*.hpp)
48
+ file(GLOB_RECURSE EXTENSION_SOURCES LIST_DIRECTORIES false ${SOURCE_PATH}/amulet/*.py.cpp)
49
+ file(GLOB_RECURSE EXTENSION_HEADERS LIST_DIRECTORIES false ${SOURCE_PATH}/amulet/*.py.hpp)
50
+ list(REMOVE_ITEM SOURCES ${EXTENSION_SOURCES})
51
+ list(REMOVE_ITEM HEADERS ${EXTENSION_HEADERS})
52
+
53
+ # Add implementation
54
+ add_library(amulet_zlib SHARED)
55
+ target_link_libraries( amulet_zlib PRIVATE zlibstatic )
56
+ target_compile_definitions(amulet_zlib PRIVATE ExportAmuletZlib)
57
+ target_include_directories(amulet_zlib PUBLIC "src")
58
+ target_sources(amulet_zlib PRIVATE ${SOURCES} ${HEADERS})
59
+ foreach(FILE ${SOURCES} ${HEADERS})
60
+ file(RELATIVE_PATH REL_PATH ${SOURCE_PATH} ${FILE})
61
+ get_filename_component(GROUP ${REL_PATH} DIRECTORY)
62
+ string(REPLACE "/" "\\" GROUP ${GROUP})
63
+ source_group(${GROUP} FILES ${FILE})
64
+ endforeach()
65
+
66
+ # Add python extension
67
+ pybind11_add_module(_amulet_zlib)
68
+ target_compile_definitions(_amulet_zlib PRIVATE PYBIND11_DETAILED_ERROR_MESSAGES)
69
+ target_compile_definitions(_amulet_zlib PRIVATE PYBIND11_VERSION="${pybind11_VERSION}")
70
+ target_compile_definitions(_amulet_zlib PRIVATE COMPILER_ID="${CMAKE_CXX_COMPILER_ID}")
71
+ target_compile_definitions(_amulet_zlib PRIVATE COMPILER_VERSION="${CMAKE_CXX_COMPILER_VERSION}")
72
+ target_link_libraries(_amulet_zlib PRIVATE amulet_pybind11_extensions)
73
+ target_link_libraries(_amulet_zlib PRIVATE amulet_zlib)
74
+ target_sources(_amulet_zlib PRIVATE ${EXTENSION_SOURCES} ${EXTENSION_HEADERS})
75
+ foreach(FILE ${EXTENSION_SOURCES} ${EXTENSION_HEADERS})
76
+ file(RELATIVE_PATH REL_PATH ${SOURCE_PATH} ${FILE})
77
+ get_filename_component(GROUP ${REL_PATH} DIRECTORY)
78
+ string(REPLACE "/" "\\" GROUP ${GROUP})
79
+ source_group(${GROUP} FILES ${FILE})
80
+ endforeach()
81
+
82
+ if(NOT DEFINED AMULET_ZLIB_EXT_DIR)
83
+ set(AMULET_ZLIB_EXT_DIR ${amulet_zlib_DIR})
84
+ endif()
85
+
86
+ # Install
87
+ install(TARGETS amulet_zlib DESTINATION ${amulet_zlib_DIR})
88
+ install(TARGETS _amulet_zlib DESTINATION ${AMULET_ZLIB_EXT_DIR})
89
+
90
+ if (TEST_AMULET_ZLIB_DIR)
91
+ add_subdirectory(tests)
92
+ endif()
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 gentlegiantJGC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ include build_requires.py
2
+ include requirements.py
3
+
4
+ recursive-include src/amulet *.cpp *.hpp *Config.cmake
5
+
6
+ include CMakeLists.txt
7
+
8
+ prune tests
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: amulet-zlib
3
+ Version: 1.0.0a0
4
+ Summary: A Python and C++ wrapper around zlib.
5
+ Author: James Clare
6
+ Project-URL: Homepage, https://www.amuletmc.com
7
+ Project-URL: Repository, https://github.com/Amulet-Team/Amulet-zlib
8
+ Project-URL: Issues, https://github.com/Amulet-Team/Amulet-zlib/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: amulet-compiler-target==1.0
15
+ Requires-Dist: amulet-compiler-version==3.0.0
16
+ Provides-Extra: docs
17
+ Requires-Dist: Sphinx>=1.7.4; extra == "docs"
18
+ Requires-Dist: sphinx-autodoc-typehints>=1.3.0; extra == "docs"
19
+ Requires-Dist: sphinx_rtd_theme>=0.3.1; extra == "docs"
20
+ Provides-Extra: dev
21
+ Requires-Dist: setuptools>=42; extra == "dev"
22
+ Requires-Dist: versioneer; extra == "dev"
23
+ Requires-Dist: packaging; extra == "dev"
24
+ Requires-Dist: wheel; extra == "dev"
25
+ Requires-Dist: pybind11==2.13.6; extra == "dev"
26
+ Requires-Dist: amulet_pybind11_extensions~=1.0; extra == "dev"
27
+ Requires-Dist: black>=22.3; extra == "dev"
28
+ Requires-Dist: mypy; extra == "dev"
29
+ Requires-Dist: types-pyinstaller; extra == "dev"
30
+ Requires-Dist: amulet-test-utils~=1.1; extra == "dev"
31
+ Dynamic: license-file
32
+ Dynamic: requires-dist
33
+
34
+ # Amulet-zlib
35
+
36
+ A Python and C++ wrapper around zlib.
@@ -0,0 +1,3 @@
1
+ # Amulet-zlib
2
+
3
+ A Python and C++ wrapper around zlib.
@@ -0,0 +1,25 @@
1
+ from typing import Union, Mapping
2
+
3
+ from setuptools import build_meta
4
+ from setuptools.build_meta import *
5
+
6
+ import requirements
7
+
8
+
9
+ def get_requires_for_build_wheel(
10
+ config_settings: Union[Mapping[str, Union[str, list[str], None]], None] = None,
11
+ ) -> list[str]:
12
+ return [
13
+ *build_meta.get_requires_for_build_wheel(config_settings),
14
+ "wheel",
15
+ *requirements.get_build_dependencies(),
16
+ ]
17
+
18
+
19
+ def get_requires_for_build_editable(
20
+ config_settings: Union[Mapping[str, Union[str, list[str], None]], None] = None,
21
+ ) -> list[str]:
22
+ return [
23
+ *build_meta.get_requires_for_build_editable(config_settings),
24
+ *requirements.get_build_dependencies(),
25
+ ]
@@ -0,0 +1,73 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools>=42",
4
+ "versioneer",
5
+ "packaging",
6
+ "amulet-compiler-version@git+https://github.com/Amulet-Team/Amulet-Compiler-Version.git@3.0"
7
+ ]
8
+ build-backend = "build_requires"
9
+ backend-path = [""]
10
+
11
+ [project]
12
+ name = "amulet-zlib"
13
+ authors = [
14
+ {name = "James Clare"},
15
+ ]
16
+ description = "A Python and C++ wrapper around zlib."
17
+ dynamic = ["version", "readme", "dependencies"]
18
+ requires-python = ">=3.11"
19
+ classifiers = [
20
+ "Programming Language :: Python :: 3",
21
+ "Operating System :: OS Independent",
22
+ ]
23
+
24
+ [project.optional-dependencies]
25
+ docs = [
26
+ "Sphinx>=1.7.4",
27
+ "sphinx-autodoc-typehints>=1.3.0",
28
+ "sphinx_rtd_theme>=0.3.1",
29
+ ]
30
+ dev = [
31
+ "setuptools>=42",
32
+ "versioneer",
33
+ "packaging",
34
+ "wheel",
35
+ "pybind11==2.13.6",
36
+ "amulet_pybind11_extensions~=1.0",
37
+ "black>=22.3",
38
+ "mypy",
39
+ "types-pyinstaller",
40
+ "amulet-test-utils~=1.1",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://www.amuletmc.com"
45
+ Repository = "https://github.com/Amulet-Team/Amulet-zlib"
46
+ Issues = "https://github.com/Amulet-Team/Amulet-zlib/issues"
47
+
48
+ [tool.setuptools]
49
+ include-package-data = false
50
+
51
+ [tool.setuptools.package-data]
52
+ "*" = [
53
+ "*Config.cmake",
54
+ "**/*.hpp",
55
+ "**/*.dll",
56
+ "**/*.so",
57
+ "**/*.dylib",
58
+ "**/*.lib",
59
+ ]
60
+
61
+ [tool.setuptools.dynamic]
62
+ readme = {file = ["README.md"], content-type = "text/markdown"}
63
+
64
+ [project.entry-points.pyinstaller40]
65
+ hook-dirs = "amulet.zlib.__pyinstaller:get_hook_dirs"
66
+
67
+ [tool.versioneer]
68
+ VCS = "git"
69
+ style = "pep440"
70
+ versionfile_source = "src/amulet/zlib/_version.py"
71
+ versionfile_build = "amulet/zlib/_version.py"
72
+ tag_prefix = ""
73
+ parentdir_prefix = "amulet_zlib-"
@@ -0,0 +1,28 @@
1
+ import os
2
+ from packaging.version import Version
3
+
4
+ import amulet_compiler_version
5
+
6
+ PYBIND11_REQUIREMENT = "==2.13.6"
7
+ AMULET_COMPILER_TARGET_REQUIREMENT = "==1.0"
8
+ AMULET_COMPILER_VERSION_REQUIREMENT = "==3.0.0"
9
+ AMULET_PYBIND11_EXTENSIONS_REQUIREMENT = "~=1.0"
10
+
11
+
12
+ if os.environ.get("AMULET_FREEZE_COMPILER", None):
13
+ AMULET_COMPILER_VERSION_REQUIREMENT = f"=={amulet_compiler_version.__version__}"
14
+
15
+
16
+ def get_build_dependencies() -> list:
17
+ return [
18
+ f"pybind11{PYBIND11_REQUIREMENT}",
19
+ f"amulet_pybind11_extensions{AMULET_PYBIND11_EXTENSIONS_REQUIREMENT}",
20
+ f"amulet-compiler-version{AMULET_COMPILER_VERSION_REQUIREMENT}",
21
+ ]
22
+
23
+
24
+ def get_runtime_dependencies() -> list[str]:
25
+ return [
26
+ f"amulet-compiler-target{AMULET_COMPILER_TARGET_REQUIREMENT}",
27
+ f"amulet-compiler-version{AMULET_COMPILER_VERSION_REQUIREMENT}",
28
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,122 @@
1
+ import os
2
+ import subprocess
3
+ import sys
4
+ from pathlib import Path
5
+ import platform
6
+ import datetime
7
+
8
+ from setuptools import setup, Extension, Command
9
+ from setuptools.command.build_ext import build_ext
10
+
11
+ from packaging.version import Version
12
+ import versioneer
13
+
14
+ import requirements
15
+
16
+
17
+ if (
18
+ os.environ.get("AMULET_FREEZE_COMPILER", None)
19
+ and sys.platform == "darwin"
20
+ and platform.machine() != "arm64"
21
+ ):
22
+ raise Exception("The MacOS frozen build must be created on arm64")
23
+
24
+
25
+ def fix_path(path: str) -> str:
26
+ return os.path.realpath(path).replace(os.sep, "/")
27
+
28
+
29
+ dependencies = requirements.get_runtime_dependencies()
30
+
31
+ cmdclass: dict[str, type[Command]] = versioneer.get_cmdclass()
32
+
33
+
34
+ class CMakeBuild(cmdclass.get("build_ext", build_ext)):
35
+ def build_extension(self, ext):
36
+ import pybind11
37
+ import amulet.pybind11_extensions
38
+
39
+ ext_dir = (
40
+ (Path.cwd() / self.get_ext_fullpath("")).parent.resolve()
41
+ / "amulet"
42
+ / "zlib"
43
+ )
44
+ zlib_src_dir = (
45
+ Path.cwd() / "src" / "amulet" / "zlib" if self.editable_mode else ext_dir
46
+ )
47
+
48
+ platform_args = []
49
+ if sys.platform == "win32":
50
+ platform_args.extend(["-G", "Visual Studio 17 2022"])
51
+ if sys.maxsize > 2**32:
52
+ platform_args.extend(["-A", "x64"])
53
+ else:
54
+ platform_args.extend(["-A", "Win32"])
55
+ platform_args.extend(["-T", "v143"])
56
+ elif sys.platform == "darwin":
57
+ if platform.machine() == "arm64":
58
+ platform_args.append("-DCMAKE_OSX_ARCHITECTURES=x86_64;arm64")
59
+
60
+ if subprocess.run(
61
+ [
62
+ "cmake",
63
+ *platform_args,
64
+ f"-DPYTHON_EXECUTABLE={sys.executable}",
65
+ f"-Dpybind11_DIR={fix_path(pybind11.get_cmake_dir())}",
66
+ f"-Damulet_pybind11_extensions_DIR={(amulet.pybind11_extensions.__path__[0])}",
67
+ f"-Damulet_zlib_DIR={fix_path(zlib_src_dir)}",
68
+ f"-DAMULET_ZLIB_EXT_DIR={fix_path(ext_dir)}",
69
+ f"-DCMAKE_INSTALL_PREFIX=install",
70
+ "-B",
71
+ "build",
72
+ ]
73
+ ).returncode:
74
+ raise RuntimeError("Error configuring amulet_zlib")
75
+ if subprocess.run(
76
+ ["cmake", "--build", "build", "--config", "Release"]
77
+ ).returncode:
78
+ raise RuntimeError("Error installing amulet_zlib")
79
+ if subprocess.run(
80
+ ["cmake", "--install", "build", "--config", "Release"]
81
+ ).returncode:
82
+ raise RuntimeError("Error installing amulet_zlib")
83
+
84
+
85
+ cmdclass["build_ext"] = CMakeBuild
86
+
87
+
88
+ def _get_version() -> str:
89
+ version_str: str = versioneer.get_version()
90
+
91
+ if os.environ.get("AMULET_FREEZE_COMPILER", None):
92
+ date_format = "%y%m%d%H%M%S"
93
+ try:
94
+ with open("build/timestamp.txt", "r") as f:
95
+ timestamp = datetime.datetime.strptime(f.read(), date_format)
96
+ print("using cached timestamp")
97
+ except Exception:
98
+ timestamp = datetime.datetime(1, 1, 1)
99
+ if datetime.timedelta(minutes=10) < datetime.datetime.now() - timestamp:
100
+ print("get timestamp")
101
+ timestamp = datetime.datetime.now()
102
+ os.makedirs("build", exist_ok=True)
103
+ with open("build/timestamp.txt", "w") as f:
104
+ f.write(timestamp.strftime(date_format))
105
+
106
+ version = Version(version_str)
107
+ epoch = f"{version.epoch}!" if version.epoch else ""
108
+ release = ".".join(map(str, version.release))
109
+ pre = "".join(map(str, version.pre)) if version.is_prerelease else ""
110
+ post = f".post{timestamp.strftime(date_format)}"
111
+ local = f"+{version.local}" if version.local else ""
112
+ version_str = f"{epoch}{release}{pre}{post}{local}"
113
+
114
+ return version_str
115
+
116
+
117
+ setup(
118
+ version=_get_version(),
119
+ cmdclass=cmdclass,
120
+ ext_modules=[Extension("amulet.zlib._amulet_zlib", [])],
121
+ install_requires=dependencies,
122
+ )
@@ -0,0 +1,42 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from amulet.zlib import _version
4
+
5
+ __version__ = _version.get_versions()["version"]
6
+
7
+ if TYPE_CHECKING:
8
+
9
+ class ZipBombException(RuntimeError):
10
+ pass
11
+
12
+ def get_max_decompression_size() -> int: ...
13
+ def set_max_decompression_size(max_decompression_size: int) -> None: ...
14
+
15
+ def decompress_zlib_gzip(src: bytes) -> bytes: ...
16
+ def compress_zlib(src: bytes) -> bytes: ...
17
+ def compress_gzip(src: bytes) -> bytes: ...
18
+
19
+
20
+ def _init() -> None:
21
+ import os
22
+ import sys
23
+ import ctypes
24
+
25
+ if sys.platform == "win32":
26
+ lib_path = os.path.join(os.path.dirname(__file__), "amulet_zlib.dll")
27
+ elif sys.platform == "darwin":
28
+ lib_path = os.path.join(os.path.dirname(__file__), "libamulet_zlib.dylib")
29
+ elif sys.platform == "linux":
30
+ lib_path = os.path.join(os.path.dirname(__file__), "libamulet_zlib.so")
31
+ else:
32
+ raise RuntimeError(f"Unsupported platform {sys.platform}")
33
+
34
+ # Load the shared library
35
+ ctypes.cdll.LoadLibrary(lib_path)
36
+
37
+ from ._amulet_zlib import init
38
+
39
+ init(sys.modules[__name__])
40
+
41
+
42
+ _init()
@@ -0,0 +1,2 @@
1
+ def get_hook_dirs():
2
+ return __path__
@@ -0,0 +1,3 @@
1
+ from PyInstaller.utils.hooks import collect_submodules
2
+
3
+ hiddenimports = collect_submodules("amulet.zlib")
@@ -0,0 +1,66 @@
1
+ #include <pybind11/pybind11.h>
2
+
3
+ #include <amulet/pybind11_extensions/compatibility.hpp>
4
+
5
+ #include <amulet/zlib/zlib.hpp>
6
+
7
+ namespace py = pybind11;
8
+ namespace pyext = Amulet::pybind11_extensions;
9
+
10
+ void init_module(py::module& m)
11
+ {
12
+ pyext::init_compiler_config(m);
13
+
14
+ py::register_exception<Amulet::zlib::ZipBombException>(m, "ZipBombException");
15
+
16
+ m.def(
17
+ "get_max_decompression_size",
18
+ &Amulet::zlib::get_max_decompression_size,
19
+ py::doc("Get the configured maximum decompressed size in bytes. (Default 100MB)"));
20
+ m.def(
21
+ "set_max_decompression_size",
22
+ &Amulet::zlib::set_max_decompression_size,
23
+ py::doc(
24
+ "Set the configured maximum decompressed size in bytes.\n"
25
+ "If decompression requires more memory than this it will raise ZipBombException."));
26
+
27
+ m.def(
28
+ "decompress_zlib_gzip",
29
+ [](py::bytes src) {
30
+ std::string dst;
31
+ {
32
+ py::gil_scoped_release nogil;
33
+ Amulet::zlib::decompress_zlib_gzip(src, dst);
34
+ }
35
+ return py::bytes(dst);
36
+ },
37
+ py::doc(
38
+ "Decompress a bytes object compressed with either zlib or gzip.\n"
39
+ "Raises ZipBombException if decompression requires more than the configured maximum decompression size."));
40
+ m.def(
41
+ "compress_zlib",
42
+ [](py::bytes src) {
43
+ std::string dst;
44
+ {
45
+ py::gil_scoped_release nogil;
46
+ Amulet::zlib::compress_zlib(src, dst);
47
+ }
48
+ return py::bytes(dst);
49
+ },
50
+ py::doc("Compress a bytes object using the zlib compression format."));
51
+ m.def(
52
+ "compress_gzip",
53
+ [](py::bytes src) {
54
+ std::string dst;
55
+ {
56
+ py::gil_scoped_release nogil;
57
+ Amulet::zlib::compress_gzip(src, dst);
58
+ }
59
+ return py::bytes(dst); },
60
+ py::doc("Compress a bytes object using the gzip compression format."));
61
+ }
62
+
63
+ PYBIND11_MODULE(_amulet_zlib, m)
64
+ {
65
+ m.def("init", &init_module);
66
+ }
@@ -0,0 +1,21 @@
1
+
2
+ # This file was generated by 'versioneer.py' (0.29) from
3
+ # revision-control system data, or from the parent directory name of an
4
+ # unpacked source archive. Distribution tarballs contain a pre-generated copy
5
+ # of this file.
6
+
7
+ import json
8
+
9
+ version_json = '''
10
+ {
11
+ "date": "2025-05-30T13:52:49+0100",
12
+ "dirty": false,
13
+ "error": null,
14
+ "full-revisionid": "1e657bcaad7fd55c431ae3fb311b4ebd90026ab4",
15
+ "version": "1.0.0a0"
16
+ }
17
+ ''' # END VERSION_JSON
18
+
19
+
20
+ def get_versions():
21
+ return json.loads(version_json)
@@ -0,0 +1,13 @@
1
+ if (NOT TARGET amulet_zlib)
2
+ message(STATUS "Finding amulet_zlib")
3
+
4
+ set(amulet_zlib_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
5
+ find_library(amulet_zlib_LIBRARY NAMES amulet_zlib PATHS "${CMAKE_CURRENT_LIST_DIR}")
6
+ message(STATUS "amulet_zlib_LIBRARY: ${amulet_zlib_LIBRARY}")
7
+
8
+ add_library(amulet_zlib SHARED IMPORTED)
9
+ set_target_properties(amulet_zlib PROPERTIES
10
+ INTERFACE_INCLUDE_DIRECTORIES "${amulet_zlib_INCLUDE_DIR}"
11
+ IMPORTED_IMPLIB "${amulet_zlib_LIBRARY}"
12
+ )
13
+ endif()
@@ -0,0 +1,19 @@
1
+ #ifndef AMULET_ZLIB_EXPORT
2
+ #ifdef _WIN32
3
+ #ifdef ExportAmuletZlib
4
+ #define AMULET_ZLIB_EXPORT __declspec(dllexport)
5
+ #else
6
+ #define AMULET_ZLIB_EXPORT __declspec(dllimport)
7
+ #endif
8
+ #else
9
+ #define AMULET_ZLIB_EXPORT
10
+ #endif
11
+ #endif
12
+
13
+ #if !defined(AMULET_ZLIB_EXPORT_EXCEPTION)
14
+ #if defined(_LIBCPP_EXCEPTION)
15
+ #define AMULET_ZLIB_EXPORT_EXCEPTION __attribute__((visibility("default")))
16
+ #else
17
+ #define AMULET_ZLIB_EXPORT_EXCEPTION
18
+ #endif
19
+ #endif
File without changes
@@ -0,0 +1,190 @@
1
+ #include <limits>
2
+ #include <stdexcept>
3
+ #include <string>
4
+ #include <string_view>
5
+
6
+ #include <zlib.h>
7
+
8
+ #include <amulet/zlib/zlib.hpp>
9
+
10
+ #define MAX_AVAIL_IN std::numeric_limits<uInt>::max()
11
+ #define DST_CHUNK_SIZE 65536
12
+ static_assert(MAX_AVAIL_IN <= std::numeric_limits<uInt>::max());
13
+ static_assert(DST_CHUNK_SIZE <= std::numeric_limits<uInt>::max());
14
+
15
+ namespace Amulet {
16
+ namespace zlib {
17
+
18
+ static size_t _max_decompression_size = 100000000; // 100MB
19
+
20
+ size_t get_max_decompression_size()
21
+ {
22
+ return _max_decompression_size;
23
+ }
24
+
25
+ void set_max_decompression_size(size_t max_decompression_size)
26
+ {
27
+ _max_decompression_size = max_decompression_size;
28
+ }
29
+
30
+ void decompress_zlib_gzip(const std::string_view src, std::string& dst)
31
+ {
32
+ // Initialise the stream
33
+ z_stream stream = { 0 };
34
+ switch (inflateInit2(&stream, 32 + MAX_WBITS)) {
35
+ case Z_MEM_ERROR:
36
+ throw std::bad_alloc();
37
+ case Z_VERSION_ERROR:
38
+ throw std::runtime_error("Incompatible zlib library.");
39
+ case Z_STREAM_ERROR:
40
+ throw std::runtime_error("zlib stream is invalid.");
41
+ }
42
+
43
+ size_t src_index = 0;
44
+ size_t dst_start_size = dst.size();
45
+ size_t dst_index = dst.size();
46
+ int err;
47
+
48
+ do {
49
+ stream.avail_in = static_cast<uInt>(std::min<size_t>(src.size() - src_index, MAX_AVAIL_IN));
50
+ if (stream.avail_in == 0) {
51
+ break;
52
+ }
53
+ stream.next_in = reinterpret_cast<z_const Bytef*>(&src[src_index]);
54
+ src_index += stream.avail_in;
55
+
56
+ do {
57
+ // zip bomb check
58
+ if (_max_decompression_size < dst_index - dst_start_size) {
59
+ throw ZipBombException("Decompression requires more memory than the configured maximum.");
60
+ }
61
+ // allocate data after dst
62
+ dst.resize(dst_index + DST_CHUNK_SIZE);
63
+ // Assign the location to decompress into
64
+ stream.next_out = reinterpret_cast<Bytef*>(&dst[dst_index]);
65
+ stream.avail_out = DST_CHUNK_SIZE;
66
+
67
+ // Decompress
68
+ err = inflate(&stream, Z_NO_FLUSH);
69
+
70
+ switch (err) {
71
+ case Z_NEED_DICT:
72
+ case Z_DATA_ERROR:
73
+ inflateEnd(&stream);
74
+ throw std::invalid_argument("Cannot decompress corrupt zlib data.");
75
+ case Z_MEM_ERROR:
76
+ inflateEnd(&stream);
77
+ throw std::bad_alloc();
78
+ case Z_STREAM_ERROR:
79
+ inflateEnd(&stream);
80
+ throw std::runtime_error("zlib stream is invalid.");
81
+ }
82
+ // increment dst_index
83
+ dst_index += DST_CHUNK_SIZE - stream.avail_out;
84
+ } while (stream.avail_out == 0);
85
+ } while (err != Z_STREAM_END);
86
+
87
+ // Remove unused bytes
88
+ dst.resize(dst_index);
89
+ // Clear stream data
90
+ inflateEnd(&stream);
91
+ }
92
+
93
+ void compress_zlib(const std::string_view src, std::string& dst)
94
+ {
95
+ // Initialise the stream
96
+ z_stream stream = { 0 };
97
+ switch (deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY)) {
98
+ case Z_MEM_ERROR:
99
+ throw std::bad_alloc();
100
+ case Z_VERSION_ERROR:
101
+ throw std::runtime_error("Incompatible zlib library.");
102
+ case Z_STREAM_ERROR:
103
+ throw std::runtime_error("zlib stream is invalid.");
104
+ }
105
+
106
+ size_t src_index = 0;
107
+ size_t dst_index = dst.size();
108
+ int err;
109
+ int flush;
110
+
111
+ do {
112
+ stream.avail_in = static_cast<uInt>(std::min<size_t>(src.size() - src_index, MAX_AVAIL_IN));
113
+ stream.next_in = reinterpret_cast<z_const Bytef*>(&src[src_index]);
114
+ src_index += stream.avail_in;
115
+ flush = (src.size() == src_index) ? Z_FINISH : Z_NO_FLUSH;
116
+
117
+ do {
118
+ // allocate data after dst
119
+ dst.resize(dst_index + DST_CHUNK_SIZE);
120
+ // Assign the location to decompress into
121
+ stream.next_out = reinterpret_cast<Bytef*>(&dst[dst_index]);
122
+ stream.avail_out = DST_CHUNK_SIZE;
123
+
124
+ // Compress
125
+ err = deflate(&stream, flush);
126
+ if (err == Z_STREAM_ERROR) {
127
+ deflateEnd(&stream);
128
+ throw std::runtime_error("zlib stream is invalid.");
129
+ }
130
+ // increment dst_index
131
+ dst_index += DST_CHUNK_SIZE - stream.avail_out;
132
+ } while (stream.avail_out == 0);
133
+ } while (src_index < src.size());
134
+
135
+ // Remove unused bytes
136
+ dst.resize(dst_index);
137
+ // Clear stream data
138
+ deflateEnd(&stream);
139
+ }
140
+
141
+ void compress_gzip(const std::string_view src, std::string& dst)
142
+ {
143
+ // Initialise the stream
144
+ z_stream stream = { 0 };
145
+ switch (deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY)) {
146
+ case Z_MEM_ERROR:
147
+ throw std::bad_alloc();
148
+ case Z_VERSION_ERROR:
149
+ throw std::runtime_error("Incompatible zlib library.");
150
+ case Z_STREAM_ERROR:
151
+ throw std::runtime_error("zlib stream is invalid.");
152
+ }
153
+
154
+ size_t src_index = 0;
155
+ size_t dst_index = dst.size();
156
+ int err;
157
+ int flush;
158
+
159
+ do {
160
+ stream.avail_in = static_cast<uInt>(std::min<size_t>(src.size() - src_index, MAX_AVAIL_IN));
161
+ stream.next_in = reinterpret_cast<z_const Bytef*>(&src[src_index]);
162
+ src_index += stream.avail_in;
163
+ flush = (src.size() == src_index) ? Z_FINISH : Z_NO_FLUSH;
164
+
165
+ do {
166
+ // allocate data after dst
167
+ dst.resize(dst_index + DST_CHUNK_SIZE);
168
+ // Assign the location to decompress into
169
+ stream.next_out = reinterpret_cast<Bytef*>(&dst[dst_index]);
170
+ stream.avail_out = DST_CHUNK_SIZE;
171
+
172
+ // Compress
173
+ err = deflate(&stream, flush);
174
+ if (err == Z_STREAM_ERROR) {
175
+ deflateEnd(&stream);
176
+ throw std::runtime_error("zlib stream is invalid.");
177
+ }
178
+ // increment dst_index
179
+ dst_index += DST_CHUNK_SIZE - stream.avail_out;
180
+ } while (stream.avail_out == 0);
181
+ } while (src_index < src.size());
182
+
183
+ // Remove unused bytes
184
+ dst.resize(dst_index);
185
+ // Clear stream data
186
+ deflateEnd(&stream);
187
+ }
188
+
189
+ } // namespace zlib
190
+ } // namespace Amulet
@@ -0,0 +1,35 @@
1
+ #pragma once
2
+
3
+ #include <stdexcept>
4
+ #include <string>
5
+ #include <string_view>
6
+
7
+ #include <amulet/zlib/export.hpp>
8
+
9
+ namespace Amulet {
10
+ namespace zlib {
11
+
12
+ class AMULET_ZLIB_EXPORT_EXCEPTION ZipBombException : public std::runtime_error {
13
+ public:
14
+ using std::runtime_error::runtime_error;
15
+ };
16
+
17
+ // Get the configured maximum decompressed size in bytes. (Default 100MB)
18
+ AMULET_ZLIB_EXPORT size_t get_max_decompression_size();
19
+
20
+ // Set the configured maximum decompressed size in bytes.
21
+ // If decompression requires more memory than this it will raise ZipBombException.
22
+ AMULET_ZLIB_EXPORT void set_max_decompression_size(size_t);
23
+
24
+ // Decompress zlib or gzip compressed data from src into dst.
25
+ // Throws ZipBombException if decompression requires more than the configured maximum decompression size.
26
+ AMULET_ZLIB_EXPORT void decompress_zlib_gzip(const std::string_view src, std::string& dst);
27
+
28
+ // Compress the data in src in zlib format and append to dst.
29
+ AMULET_ZLIB_EXPORT void compress_zlib(const std::string_view src, std::string& dst);
30
+
31
+ // Compress the data in src in gzip format and append to dst.
32
+ AMULET_ZLIB_EXPORT void compress_gzip(const std::string_view src, std::string& dst);
33
+
34
+ } // namespace zlib
35
+ } // namespace Amulet
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: amulet-zlib
3
+ Version: 1.0.0a0
4
+ Summary: A Python and C++ wrapper around zlib.
5
+ Author: James Clare
6
+ Project-URL: Homepage, https://www.amuletmc.com
7
+ Project-URL: Repository, https://github.com/Amulet-Team/Amulet-zlib
8
+ Project-URL: Issues, https://github.com/Amulet-Team/Amulet-zlib/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: amulet-compiler-target==1.0
15
+ Requires-Dist: amulet-compiler-version==3.0.0
16
+ Provides-Extra: docs
17
+ Requires-Dist: Sphinx>=1.7.4; extra == "docs"
18
+ Requires-Dist: sphinx-autodoc-typehints>=1.3.0; extra == "docs"
19
+ Requires-Dist: sphinx_rtd_theme>=0.3.1; extra == "docs"
20
+ Provides-Extra: dev
21
+ Requires-Dist: setuptools>=42; extra == "dev"
22
+ Requires-Dist: versioneer; extra == "dev"
23
+ Requires-Dist: packaging; extra == "dev"
24
+ Requires-Dist: wheel; extra == "dev"
25
+ Requires-Dist: pybind11==2.13.6; extra == "dev"
26
+ Requires-Dist: amulet_pybind11_extensions~=1.0; extra == "dev"
27
+ Requires-Dist: black>=22.3; extra == "dev"
28
+ Requires-Dist: mypy; extra == "dev"
29
+ Requires-Dist: types-pyinstaller; extra == "dev"
30
+ Requires-Dist: amulet-test-utils~=1.1; extra == "dev"
31
+ Dynamic: license-file
32
+ Dynamic: requires-dist
33
+
34
+ # Amulet-zlib
35
+
36
+ A Python and C++ wrapper around zlib.
@@ -0,0 +1,24 @@
1
+ CMakeLists.txt
2
+ LICENSE
3
+ MANIFEST.in
4
+ README.md
5
+ build_requires.py
6
+ pyproject.toml
7
+ requirements.py
8
+ setup.py
9
+ src/amulet/zlib/__init__.py
10
+ src/amulet/zlib/_amulet_zlib.py.cpp
11
+ src/amulet/zlib/_version.py
12
+ src/amulet/zlib/amulet_zlibConfig.cmake
13
+ src/amulet/zlib/export.hpp
14
+ src/amulet/zlib/py.typed
15
+ src/amulet/zlib/zlib.cpp
16
+ src/amulet/zlib/zlib.hpp
17
+ src/amulet/zlib/__pyinstaller/__init__.py
18
+ src/amulet/zlib/__pyinstaller/hook-amulet_zlib.py
19
+ src/amulet_zlib.egg-info/PKG-INFO
20
+ src/amulet_zlib.egg-info/SOURCES.txt
21
+ src/amulet_zlib.egg-info/dependency_links.txt
22
+ src/amulet_zlib.egg-info/entry_points.txt
23
+ src/amulet_zlib.egg-info/requires.txt
24
+ src/amulet_zlib.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [pyinstaller40]
2
+ hook-dirs = amulet.zlib.__pyinstaller:get_hook_dirs
@@ -0,0 +1,19 @@
1
+ amulet-compiler-target==1.0
2
+ amulet-compiler-version==3.0.0
3
+
4
+ [dev]
5
+ setuptools>=42
6
+ versioneer
7
+ packaging
8
+ wheel
9
+ pybind11==2.13.6
10
+ amulet_pybind11_extensions~=1.0
11
+ black>=22.3
12
+ mypy
13
+ types-pyinstaller
14
+ amulet-test-utils~=1.1
15
+
16
+ [docs]
17
+ Sphinx>=1.7.4
18
+ sphinx-autodoc-typehints>=1.3.0
19
+ sphinx_rtd_theme>=0.3.1