-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.py
More file actions
171 lines (153 loc) · 6.04 KB
/
Copy pathsetup.py
File metadata and controls
171 lines (153 loc) · 6.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
"""
setup.py for docx_comment_parser Python extension.
This file is kept as a fallback for environments that cannot use scikit-build-core.
The recommended build path is:
pip install scikit-build-core pybind11
pip install . # uses pyproject.toml → scikit-build-core → CMake
For a manual setuptools build (no CMake required):
pip install pybind11
pip install . # setuptools falls back to this file
# or in-place:
python setup.py build_ext --inplace
Supported toolchains:
Linux / macOS : GCC or Clang (uses -std=c++17, -lz)
Windows MSVC : Visual Studio 2019+ (uses /std:c++17, vendored zlib)
Windows MinGW : MinGW-w64 via MSYS2 (uses -std=c++17, -lz)
"""
from setuptools import setup, Extension, find_packages
import sys
import os
import subprocess
ROOT = os.path.dirname(os.path.abspath(__file__))
def _is_mingw() -> bool:
"""Return True when building with MinGW-w64 GCC under Windows."""
if sys.platform != "win32":
return False
try:
out = subprocess.check_output(
["gcc", "--version"], stderr=subprocess.DEVNULL
).decode()
return "mingw" in out.lower() or "MINGW" in out
except (FileNotFoundError, subprocess.CalledProcessError):
return False
# ─── Locate pybind11 headers ──────────────────────────────────────────────────
try:
import pybind11
pybind11_include = pybind11.get_include()
except ImportError:
raise RuntimeError("pybind11 not found. Install with: pip install pybind11")
# ─── Platform / toolchain flags ──────────────────────────────────────────────
IS_MINGW = _is_mingw()
IS_MSVC = sys.platform == "win32" and not IS_MINGW
if IS_MSVC:
# MSVC (cl.exe) — Visual Studio 2019 or later.
# zlib is provided by the vendored single-header in vendor/zlib/zlib.h
# (activated by VENDOR_ZLIB_IMPLEMENTATION inside zip_reader.cpp), so no
# external -lz is needed.
extra_compile_args = [
"/std:c++17",
"/O2",
"/DNDEBUG",
"/EHsc", # enable C++ exception handling
"/DDOCX_BUILDING_DLL", # DOCX_API → __declspec(dllexport)
]
extra_link_args = []
elif IS_MINGW:
# MinGW-w64 GCC on Windows (MSYS2 / standalone).
# Notes:
# - DOCX_BUILDING_DLL is correct here because setup.py compiles ALL C++
# sources directly into the single .pyd extension (not a separate DLL),
# so the extension IS the thing that "builds" the symbols.
# - -lmswsock is intentionally omitted: it is not needed for this library
# and is absent from some MinGW-w64 installations, causing link failure.
# - -lws2_32 is likewise unnecessary (no socket code in this library).
extra_compile_args = [
"-std=c++17",
"-O2",
"-DNDEBUG",
"-DDOCX_BUILDING_DLL",
"-Wall",
]
extra_link_args = [
"-lz", # zlib1.dll — ships with every MinGW installation
]
else:
# Linux / macOS — GCC or Clang
extra_compile_args = [
"-std=c++17",
"-O3",
"-DNDEBUG",
"-fvisibility=hidden",
"-DDOCX_BUILDING_DLL",
]
extra_link_args = ["-lz"]
# ─── Source files ─────────────────────────────────────────────────────────────
# All C++ sources are compiled directly into the single Python extension — there
# is no separate docx_comment_parser.dll/so to distribute alongside the wheel.
sources = [
os.path.join(ROOT, "python", "python_bindings.cpp"),
os.path.join(ROOT, "src", "docx_parser.cpp"),
os.path.join(ROOT, "src", "batch_parser.cpp"),
os.path.join(ROOT, "src", "zip_reader.cpp"),
os.path.join(ROOT, "src", "xml_parser.cpp"),
]
# The extension is a submodule of the pure-Python package in src/, hence the
# dotted name: it is imported as docx_comment_parser._core and re-exported by
# docx_comment_parser/__init__.py.
ext = Extension(
"docx_comment_parser._core",
sources=sources,
include_dirs=[
os.path.join(ROOT, "include"),
os.path.join(ROOT, "vendor"), # vendored zlib.h for MSVC
pybind11_include,
],
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
language="c++",
)
setup(
name="docx-comment-parser",
version="1.3.0",
author="nick-developer",
description="Fast C++ library for extracting comment metadata from .docx files",
long_description=(
open(os.path.join(ROOT, "README.md"), encoding="utf-8").read()
if os.path.exists(os.path.join(ROOT, "README.md"))
else ""
),
long_description_content_type="text/markdown",
ext_modules=[ext],
# Pure-Python wrapper package (exporters, filters, CLI) lives in src/.
packages=find_packages(where="src"),
package_dir={"": "src"},
package_data={
"docx_comment_parser": ["py.typed", "*.pyi"],
# The HTML report inlines these at render time, so they must ship
# inside the wheel rather than being generated from source.
"docx_comment_parser.reporting": ["templates/*.j2", "assets/*"],
},
python_requires=">=3.9",
extras_require={
"pandas": ["pandas>=2.0"],
"polars": ["polars>=1.0"],
"cli": ["typer>=0.12", "rich>=13.0"],
"report": ["jinja2>=3.0"],
"all": [
"pandas>=2.0", "polars>=1.0", "typer>=0.12", "rich>=13.0",
"jinja2>=3.0",
],
},
entry_points={
"console_scripts": [
"docx-comments = docx_comment_parser.cli:main",
],
},
classifiers=[
"Programming Language :: Python :: 3",
"Programming Language :: C++",
"Operating System :: POSIX :: Linux",
"Operating System :: Microsoft :: Windows",
"Operating System :: MacOS",
],
)