cppkh-interface 0.1.3__tar.gz → 0.2.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cppkh-interface
3
- Version: 0.1.3
3
+ Version: 0.2.1
4
4
  Summary: Dependency-free Python interface for cppkh with runtime C++ compilation.
5
5
  License-Expression: MIT
6
6
  Author: GGN_2015
@@ -22,7 +22,7 @@ Description-Content-Type: text/markdown
22
22
  `cppkh-interface` is a Python package for computing integer Khovanov homology
23
23
  with the C++ `cppkh` implementation.
24
24
 
25
- Version `0.1.3` has no runtime Python-package dependencies. Link crossing signs,
25
+ The package has no runtime Python-package dependencies. Link crossing signs,
26
26
  PD validation, R1 removal, and nugatory-crossing removal all use the bundled
27
27
  canonical `cppkh` C++ source and its SageMath-compatible orientation rules.
28
28
 
@@ -36,6 +36,23 @@ print(cppkh_interface.solve_khovanov(pd_code, de_r1=True, de_k8=True))
36
36
  print(cppkh_interface.solve_many_khovanov([pd_code, pd_code]))
37
37
  ```
38
38
 
39
+ For a multi-component oriented link, callers can compute several explicit
40
+ crossing-sign variants without changing the existing APIs:
41
+
42
+ ```python
43
+ from cppkh_interface import compute_signed_variants
44
+
45
+ hopf = [[2, 3, 1, 4], [4, 1, 3, 2]]
46
+ results = compute_signed_variants(hopf, [[-1, -1], [1, 1]])
47
+ assert len(results) == 2
48
+ ```
49
+
50
+ Each sign row must contain exactly one `-1` or `1` for every crossing. This
51
+ operation deliberately disables PD simplification because removing a crossing
52
+ would invalidate the positional sign mapping. `solve_khovanov` and
53
+ `solve_many_khovanov` retain their original signatures, inferred-sign behavior,
54
+ and simplification defaults.
55
+
39
56
  Unlike wrappers that ship a prebuilt DLL or shared object, this package ships
40
57
  the `cppkh` C++ source file in built distributions and compiles a local
41
58
  executable on first use using only Python's standard library. The compiled
@@ -1,68 +1,85 @@
1
- # cppkh-interface
2
-
3
- `cppkh-interface` is a Python package for computing integer Khovanov homology
4
- with the C++ `cppkh` implementation.
5
-
6
- Version `0.1.3` has no runtime Python-package dependencies. Link crossing signs,
7
- PD validation, R1 removal, and nugatory-crossing removal all use the bundled
8
- canonical `cppkh` C++ source and its SageMath-compatible orientation rules.
9
-
10
- The package is compatible with the main `javakh-interface` function:
11
-
12
- ```python
13
- import cppkh_interface
14
-
15
- pd_code = [[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]]
16
- print(cppkh_interface.solve_khovanov(pd_code, de_r1=True, de_k8=True))
1
+ # cppkh-interface
2
+
3
+ `cppkh-interface` is a Python package for computing integer Khovanov homology
4
+ with the C++ `cppkh` implementation.
5
+
6
+ The package has no runtime Python-package dependencies. Link crossing signs,
7
+ PD validation, R1 removal, and nugatory-crossing removal all use the bundled
8
+ canonical `cppkh` C++ source and its SageMath-compatible orientation rules.
9
+
10
+ The package is compatible with the main `javakh-interface` function:
11
+
12
+ ```python
13
+ import cppkh_interface
14
+
15
+ pd_code = [[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]]
16
+ print(cppkh_interface.solve_khovanov(pd_code, de_r1=True, de_k8=True))
17
17
  print(cppkh_interface.solve_many_khovanov([pd_code, pd_code]))
18
18
  ```
19
19
 
20
- Unlike wrappers that ship a prebuilt DLL or shared object, this package ships
21
- the `cppkh` C++ source file in built distributions and compiles a local
22
- executable on first use using only Python's standard library. The compiled
23
- executable is cached for later calls.
24
-
25
- In the repository checkout, the package does not keep a committed backup copy
26
- of the C++ source. The build backend copies `../../src/main.cpp` into the
27
- package data directory only while the PEP 517 build is running, then removes
28
- that temporary copy.
29
-
30
- ## Install
31
-
32
- ```sh
33
- pip install cppkh-interface
34
- ```
35
-
36
- A C++14 compiler must be available at runtime. The package looks at
37
- `CPPKH_INTERFACE_CXX`, then `CXX`, then searches `PATH` for `g++`, `clang++`, or
38
- `c++`. To select a compiler explicitly:
20
+ For a multi-component oriented link, callers can compute several explicit
21
+ crossing-sign variants without changing the existing APIs:
39
22
 
40
- ```sh
41
- CPPKH_INTERFACE_CXX=clang++ python your_script.py
42
- ```
43
-
44
- Windows PowerShell:
45
-
46
- ```powershell
47
- $env:CPPKH_INTERFACE_CXX = "C:\path\to\g++.exe"
48
- python your_script.py
49
- ```
50
-
51
- ## Build And Publish
52
-
53
- From this directory:
23
+ ```python
24
+ from cppkh_interface import compute_signed_variants
54
25
 
55
- ```sh
56
- python -m build
57
- poetry publish
26
+ hopf = [[2, 3, 1, 4], [4, 1, 3, 2]]
27
+ results = compute_signed_variants(hopf, [[-1, -1], [1, 1]])
28
+ assert len(results) == 2
58
29
  ```
59
30
 
60
- Do not use `poetry build` or `poetry publish --build`: Poetry's direct builder
61
- bypasses the source-synchronizing PEP 517 backend. Build first with
62
- `python -m build`, inspect/test the wheel, then publish the existing artifacts.
63
-
64
- For local testing:
65
-
66
- ```sh
67
- poetry run python -m cppkh_interface "[[1,5,2,4], [3,1,4,6], [5,3,6,2]]"
68
- ```
31
+ Each sign row must contain exactly one `-1` or `1` for every crossing. This
32
+ operation deliberately disables PD simplification because removing a crossing
33
+ would invalidate the positional sign mapping. `solve_khovanov` and
34
+ `solve_many_khovanov` retain their original signatures, inferred-sign behavior,
35
+ and simplification defaults.
36
+
37
+ Unlike wrappers that ship a prebuilt DLL or shared object, this package ships
38
+ the `cppkh` C++ source file in built distributions and compiles a local
39
+ executable on first use using only Python's standard library. The compiled
40
+ executable is cached for later calls.
41
+
42
+ In the repository checkout, the package does not keep a committed backup copy
43
+ of the C++ source. The build backend copies `../../src/main.cpp` into the
44
+ package data directory only while the PEP 517 build is running, then removes
45
+ that temporary copy.
46
+
47
+ ## Install
48
+
49
+ ```sh
50
+ pip install cppkh-interface
51
+ ```
52
+
53
+ A C++14 compiler must be available at runtime. The package looks at
54
+ `CPPKH_INTERFACE_CXX`, then `CXX`, then searches `PATH` for `g++`, `clang++`, or
55
+ `c++`. To select a compiler explicitly:
56
+
57
+ ```sh
58
+ CPPKH_INTERFACE_CXX=clang++ python your_script.py
59
+ ```
60
+
61
+ Windows PowerShell:
62
+
63
+ ```powershell
64
+ $env:CPPKH_INTERFACE_CXX = "C:\path\to\g++.exe"
65
+ python your_script.py
66
+ ```
67
+
68
+ ## Build And Publish
69
+
70
+ From this directory:
71
+
72
+ ```sh
73
+ python -m build
74
+ poetry publish
75
+ ```
76
+
77
+ Do not use `poetry build` or `poetry publish --build`: Poetry's direct builder
78
+ bypasses the source-synchronizing PEP 517 backend. Build first with
79
+ `python -m build`, inspect/test the wheel, then publish the existing artifacts.
80
+
81
+ For local testing:
82
+
83
+ ```sh
84
+ poetry run python -m cppkh_interface "[[1,5,2,4], [3,1,4,6], [5,3,6,2]]"
85
+ ```
@@ -1,207 +1,207 @@
1
- from __future__ import annotations
2
-
3
- import base64
4
- import hashlib
5
- import io
6
- import shutil
7
- import tarfile
8
- import tempfile
9
- import zipfile
10
- from pathlib import Path
11
-
12
- from poetry.core.masonry import api as poetry_api
13
-
14
-
15
- PROJECT_ROOT = Path(__file__).resolve().parents[1]
16
- REPO_ROOT = PROJECT_ROOT.parents[1]
17
- SOURCE = REPO_ROOT / "src" / "main.cpp"
18
- TARGET = PROJECT_ROOT / "cppkh_interface" / "data" / "src" / "main.cpp"
19
- WHEEL_SOURCE_NAME = "cppkh_interface/data/src/main.cpp"
20
-
21
-
22
- def _sync_cpp_source() -> None:
23
- if SOURCE.exists():
24
- TARGET.parent.mkdir(parents=True, exist_ok=True)
25
- shutil.copyfile(SOURCE, TARGET)
26
- return
27
- if TARGET.exists():
28
- return
29
- raise FileNotFoundError(
30
- "cppkh source file was not found. Expected either "
31
- f"{SOURCE} in the repository checkout or {TARGET} in the source tree."
32
- )
33
-
34
-
35
- def _clean_cpp_source() -> None:
36
- if TARGET.exists() and SOURCE.exists():
37
- TARGET.unlink()
38
-
39
-
40
- def _source_bytes() -> bytes:
41
- if TARGET.exists():
42
- return TARGET.read_bytes()
43
- if SOURCE.exists():
44
- return SOURCE.read_bytes()
45
- raise FileNotFoundError("cppkh source file was not available for packaging")
46
-
47
-
48
- def _wheel_hash_and_size(data: bytes) -> tuple[str, str]:
49
- digest = hashlib.sha256(data).digest()
50
- encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
51
- return f"sha256={encoded}", str(len(data))
52
-
53
-
54
- def _make_universal_wheel_metadata(data: bytes) -> bytes:
55
- text = data.decode("utf-8")
56
- lines = []
57
- tag_written = False
58
- root_written = False
59
- for line in text.splitlines():
60
- if line.startswith("Root-Is-Purelib:"):
61
- lines.append("Root-Is-Purelib: true")
62
- root_written = True
63
- elif line.startswith("Tag:"):
64
- if not tag_written:
65
- lines.append("Tag: py3-none-any")
66
- tag_written = True
67
- else:
68
- lines.append(line)
69
- if not root_written:
70
- lines.append("Root-Is-Purelib: true")
71
- if not tag_written:
72
- lines.append("Tag: py3-none-any")
73
- return ("\n".join(lines) + "\n").encode("utf-8")
74
-
75
-
76
- def _universal_wheel_path(wheel_path: Path, record_name: str) -> Path:
77
- dist_info = record_name.split("/", 1)[0]
78
- base = dist_info.removesuffix(".dist-info")
79
- return wheel_path.with_name(f"{base}-py3-none-any.whl")
80
-
81
-
82
- def _rewrite_wheel_with_source(wheel_path: Path) -> Path:
83
- source_data = _source_bytes()
84
- rows: list[tuple[str, str, str]] = []
85
-
86
- with zipfile.ZipFile(wheel_path, "r") as zin:
87
- record_name = next(
88
- (name for name in zin.namelist() if name.endswith(".dist-info/RECORD")),
89
- None,
90
- )
91
- if record_name is None:
92
- raise RuntimeError(f"wheel RECORD file not found in {wheel_path}")
93
- output_path = _universal_wheel_path(wheel_path, record_name)
94
- temp_path = output_path.with_name(output_path.name + ".tmp")
95
-
96
- with zipfile.ZipFile(temp_path, "w", compression=zipfile.ZIP_DEFLATED) as zout:
97
- wheel_metadata_name = record_name.removesuffix("RECORD") + "WHEEL"
98
-
99
- for item in zin.infolist():
100
- if item.filename in (WHEEL_SOURCE_NAME, record_name):
101
- continue
102
- data = zin.read(item.filename)
103
- if item.filename == wheel_metadata_name:
104
- data = _make_universal_wheel_metadata(data)
105
- zout.writestr(item, data)
106
- if not item.is_dir():
107
- digest, size = _wheel_hash_and_size(data)
108
- rows.append((item.filename, digest, size))
109
-
110
- source_info = zipfile.ZipInfo(WHEEL_SOURCE_NAME, date_time=(2016, 1, 1, 0, 0, 0))
111
- source_info.compress_type = zipfile.ZIP_DEFLATED
112
- zout.writestr(source_info, source_data)
113
- digest, size = _wheel_hash_and_size(source_data)
114
- rows.append((WHEEL_SOURCE_NAME, digest, size))
115
-
116
- rows.append((record_name, "", ""))
117
- record_text = "".join(f"{path},{digest},{size}\n" for path, digest, size in rows)
118
- record_info = zipfile.ZipInfo(record_name, date_time=(2016, 1, 1, 0, 0, 0))
119
- record_info.compress_type = zipfile.ZIP_DEFLATED
120
- zout.writestr(record_info, record_text.encode("utf-8"))
121
-
122
- temp_path.replace(output_path)
123
- if output_path != wheel_path and wheel_path.exists():
124
- wheel_path.unlink()
125
- return output_path
126
-
127
-
128
- def finalize_poetry_wheels() -> None:
129
- dist = PROJECT_ROOT / "dist"
130
- if not dist.exists():
131
- return
132
- for wheel_path in sorted(dist.glob("cppkh_interface-*.whl")):
133
- _rewrite_wheel_with_source(wheel_path)
134
-
135
-
136
- def _rewrite_sdist_with_source(sdist_path: Path) -> None:
137
- source_data = _source_bytes()
138
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".tar.gz")
139
- temp_path = Path(temp_file.name)
140
- temp_file.close()
141
-
142
- try:
143
- with tarfile.open(sdist_path, "r:gz") as tin, tarfile.open(temp_path, "w:gz") as tout:
144
- names = tin.getnames()
145
- if not names:
146
- raise RuntimeError(f"sdist is empty: {sdist_path}")
147
- root = names[0].split("/", 1)[0]
148
- source_name = f"{root}/{WHEEL_SOURCE_NAME}"
149
-
150
- for member in tin.getmembers():
151
- if member.name == source_name:
152
- continue
153
- if member.isfile():
154
- extracted = tin.extractfile(member)
155
- if extracted is None:
156
- raise RuntimeError(f"could not read {member.name} from {sdist_path}")
157
- with extracted:
158
- tout.addfile(member, extracted)
159
- else:
160
- tout.addfile(member)
161
-
162
- source_info = tarfile.TarInfo(source_name)
163
- source_info.size = len(source_data)
164
- source_info.mtime = 0
165
- source_info.mode = 0o644
166
- tout.addfile(source_info, io.BytesIO(source_data))
167
-
168
- temp_path.replace(sdist_path)
169
- finally:
170
- if temp_path.exists():
171
- temp_path.unlink()
172
-
173
-
174
- def get_requires_for_build_wheel(config_settings=None):
175
- return poetry_api.get_requires_for_build_wheel(config_settings)
176
-
177
-
178
- def get_requires_for_build_sdist(config_settings=None):
179
- return poetry_api.get_requires_for_build_sdist(config_settings)
180
-
181
-
182
- def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
183
- _sync_cpp_source()
184
- try:
185
- return poetry_api.prepare_metadata_for_build_wheel(metadata_directory, config_settings)
186
- finally:
187
- _clean_cpp_source()
188
-
189
-
190
- def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
191
- _sync_cpp_source()
192
- try:
193
- wheel_name = poetry_api.build_wheel(wheel_directory, config_settings, metadata_directory)
194
- final_path = _rewrite_wheel_with_source(Path(wheel_directory) / wheel_name)
195
- return final_path.name
196
- finally:
197
- _clean_cpp_source()
198
-
199
-
200
- def build_sdist(sdist_directory, config_settings=None):
201
- _sync_cpp_source()
202
- try:
203
- sdist_name = poetry_api.build_sdist(sdist_directory, config_settings)
204
- _rewrite_sdist_with_source(Path(sdist_directory) / sdist_name)
205
- return sdist_name
206
- finally:
207
- _clean_cpp_source()
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import hashlib
5
+ import io
6
+ import shutil
7
+ import tarfile
8
+ import tempfile
9
+ import zipfile
10
+ from pathlib import Path
11
+
12
+ from poetry.core.masonry import api as poetry_api
13
+
14
+
15
+ PROJECT_ROOT = Path(__file__).resolve().parents[1]
16
+ REPO_ROOT = PROJECT_ROOT.parents[1]
17
+ SOURCE = REPO_ROOT / "src" / "main.cpp"
18
+ TARGET = PROJECT_ROOT / "cppkh_interface" / "data" / "src" / "main.cpp"
19
+ WHEEL_SOURCE_NAME = "cppkh_interface/data/src/main.cpp"
20
+
21
+
22
+ def _sync_cpp_source() -> None:
23
+ if SOURCE.exists():
24
+ TARGET.parent.mkdir(parents=True, exist_ok=True)
25
+ shutil.copyfile(SOURCE, TARGET)
26
+ return
27
+ if TARGET.exists():
28
+ return
29
+ raise FileNotFoundError(
30
+ "cppkh source file was not found. Expected either "
31
+ f"{SOURCE} in the repository checkout or {TARGET} in the source tree."
32
+ )
33
+
34
+
35
+ def _clean_cpp_source() -> None:
36
+ if TARGET.exists() and SOURCE.exists():
37
+ TARGET.unlink()
38
+
39
+
40
+ def _source_bytes() -> bytes:
41
+ if TARGET.exists():
42
+ return TARGET.read_bytes()
43
+ if SOURCE.exists():
44
+ return SOURCE.read_bytes()
45
+ raise FileNotFoundError("cppkh source file was not available for packaging")
46
+
47
+
48
+ def _wheel_hash_and_size(data: bytes) -> tuple[str, str]:
49
+ digest = hashlib.sha256(data).digest()
50
+ encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
51
+ return f"sha256={encoded}", str(len(data))
52
+
53
+
54
+ def _make_universal_wheel_metadata(data: bytes) -> bytes:
55
+ text = data.decode("utf-8")
56
+ lines = []
57
+ tag_written = False
58
+ root_written = False
59
+ for line in text.splitlines():
60
+ if line.startswith("Root-Is-Purelib:"):
61
+ lines.append("Root-Is-Purelib: true")
62
+ root_written = True
63
+ elif line.startswith("Tag:"):
64
+ if not tag_written:
65
+ lines.append("Tag: py3-none-any")
66
+ tag_written = True
67
+ else:
68
+ lines.append(line)
69
+ if not root_written:
70
+ lines.append("Root-Is-Purelib: true")
71
+ if not tag_written:
72
+ lines.append("Tag: py3-none-any")
73
+ return ("\n".join(lines) + "\n").encode("utf-8")
74
+
75
+
76
+ def _universal_wheel_path(wheel_path: Path, record_name: str) -> Path:
77
+ dist_info = record_name.split("/", 1)[0]
78
+ base = dist_info.removesuffix(".dist-info")
79
+ return wheel_path.with_name(f"{base}-py3-none-any.whl")
80
+
81
+
82
+ def _rewrite_wheel_with_source(wheel_path: Path) -> Path:
83
+ source_data = _source_bytes()
84
+ rows: list[tuple[str, str, str]] = []
85
+
86
+ with zipfile.ZipFile(wheel_path, "r") as zin:
87
+ record_name = next(
88
+ (name for name in zin.namelist() if name.endswith(".dist-info/RECORD")),
89
+ None,
90
+ )
91
+ if record_name is None:
92
+ raise RuntimeError(f"wheel RECORD file not found in {wheel_path}")
93
+ output_path = _universal_wheel_path(wheel_path, record_name)
94
+ temp_path = output_path.with_name(output_path.name + ".tmp")
95
+
96
+ with zipfile.ZipFile(temp_path, "w", compression=zipfile.ZIP_DEFLATED) as zout:
97
+ wheel_metadata_name = record_name.removesuffix("RECORD") + "WHEEL"
98
+
99
+ for item in zin.infolist():
100
+ if item.filename in (WHEEL_SOURCE_NAME, record_name):
101
+ continue
102
+ data = zin.read(item.filename)
103
+ if item.filename == wheel_metadata_name:
104
+ data = _make_universal_wheel_metadata(data)
105
+ zout.writestr(item, data)
106
+ if not item.is_dir():
107
+ digest, size = _wheel_hash_and_size(data)
108
+ rows.append((item.filename, digest, size))
109
+
110
+ source_info = zipfile.ZipInfo(WHEEL_SOURCE_NAME, date_time=(2016, 1, 1, 0, 0, 0))
111
+ source_info.compress_type = zipfile.ZIP_DEFLATED
112
+ zout.writestr(source_info, source_data)
113
+ digest, size = _wheel_hash_and_size(source_data)
114
+ rows.append((WHEEL_SOURCE_NAME, digest, size))
115
+
116
+ rows.append((record_name, "", ""))
117
+ record_text = "".join(f"{path},{digest},{size}\n" for path, digest, size in rows)
118
+ record_info = zipfile.ZipInfo(record_name, date_time=(2016, 1, 1, 0, 0, 0))
119
+ record_info.compress_type = zipfile.ZIP_DEFLATED
120
+ zout.writestr(record_info, record_text.encode("utf-8"))
121
+
122
+ temp_path.replace(output_path)
123
+ if output_path != wheel_path and wheel_path.exists():
124
+ wheel_path.unlink()
125
+ return output_path
126
+
127
+
128
+ def finalize_poetry_wheels() -> None:
129
+ dist = PROJECT_ROOT / "dist"
130
+ if not dist.exists():
131
+ return
132
+ for wheel_path in sorted(dist.glob("cppkh_interface-*.whl")):
133
+ _rewrite_wheel_with_source(wheel_path)
134
+
135
+
136
+ def _rewrite_sdist_with_source(sdist_path: Path) -> None:
137
+ source_data = _source_bytes()
138
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".tar.gz")
139
+ temp_path = Path(temp_file.name)
140
+ temp_file.close()
141
+
142
+ try:
143
+ with tarfile.open(sdist_path, "r:gz") as tin, tarfile.open(temp_path, "w:gz") as tout:
144
+ names = tin.getnames()
145
+ if not names:
146
+ raise RuntimeError(f"sdist is empty: {sdist_path}")
147
+ root = names[0].split("/", 1)[0]
148
+ source_name = f"{root}/{WHEEL_SOURCE_NAME}"
149
+
150
+ for member in tin.getmembers():
151
+ if member.name == source_name:
152
+ continue
153
+ if member.isfile():
154
+ extracted = tin.extractfile(member)
155
+ if extracted is None:
156
+ raise RuntimeError(f"could not read {member.name} from {sdist_path}")
157
+ with extracted:
158
+ tout.addfile(member, extracted)
159
+ else:
160
+ tout.addfile(member)
161
+
162
+ source_info = tarfile.TarInfo(source_name)
163
+ source_info.size = len(source_data)
164
+ source_info.mtime = 0
165
+ source_info.mode = 0o644
166
+ tout.addfile(source_info, io.BytesIO(source_data))
167
+
168
+ temp_path.replace(sdist_path)
169
+ finally:
170
+ if temp_path.exists():
171
+ temp_path.unlink()
172
+
173
+
174
+ def get_requires_for_build_wheel(config_settings=None):
175
+ return poetry_api.get_requires_for_build_wheel(config_settings)
176
+
177
+
178
+ def get_requires_for_build_sdist(config_settings=None):
179
+ return poetry_api.get_requires_for_build_sdist(config_settings)
180
+
181
+
182
+ def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
183
+ _sync_cpp_source()
184
+ try:
185
+ return poetry_api.prepare_metadata_for_build_wheel(metadata_directory, config_settings)
186
+ finally:
187
+ _clean_cpp_source()
188
+
189
+
190
+ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
191
+ _sync_cpp_source()
192
+ try:
193
+ wheel_name = poetry_api.build_wheel(wheel_directory, config_settings, metadata_directory)
194
+ final_path = _rewrite_wheel_with_source(Path(wheel_directory) / wheel_name)
195
+ return final_path.name
196
+ finally:
197
+ _clean_cpp_source()
198
+
199
+
200
+ def build_sdist(sdist_directory, config_settings=None):
201
+ _sync_cpp_source()
202
+ try:
203
+ sdist_name = poetry_api.build_sdist(sdist_directory, config_settings)
204
+ _rewrite_sdist_with_source(Path(sdist_directory) / sdist_name)
205
+ return sdist_name
206
+ finally:
207
+ _clean_cpp_source()
@@ -1,25 +1,29 @@
1
- from .main import (
2
- CppkhInterfaceError,
3
- compile_cppkh,
4
- compute_many_pd,
5
- compute_pd,
6
- get_cppkh_executable,
7
- normalize_pd_code,
8
- normalize_pd_codes,
9
- simplify_pd,
10
- solve_many_khovanov,
11
- solve_khovanov,
12
- )
13
-
14
- __all__ = [
15
- "CppkhInterfaceError",
16
- "compile_cppkh",
17
- "compute_many_pd",
18
- "compute_pd",
19
- "get_cppkh_executable",
20
- "normalize_pd_code",
21
- "normalize_pd_codes",
22
- "simplify_pd",
23
- "solve_many_khovanov",
24
- "solve_khovanov",
25
- ]
1
+ from .main import (
2
+ CppkhInterfaceError,
3
+ compile_cppkh,
4
+ compile_cppkh_shared,
5
+ compute_signed_variants,
6
+ compute_many_pd,
7
+ compute_pd,
8
+ get_cppkh_executable,
9
+ normalize_pd_code,
10
+ normalize_pd_codes,
11
+ simplify_pd,
12
+ solve_many_khovanov,
13
+ solve_khovanov,
14
+ )
15
+
16
+ __all__ = [
17
+ "CppkhInterfaceError",
18
+ "compile_cppkh",
19
+ "compile_cppkh_shared",
20
+ "compute_signed_variants",
21
+ "compute_many_pd",
22
+ "compute_pd",
23
+ "get_cppkh_executable",
24
+ "normalize_pd_code",
25
+ "normalize_pd_codes",
26
+ "simplify_pd",
27
+ "solve_many_khovanov",
28
+ "solve_khovanov",
29
+ ]
@@ -1,4 +1,4 @@
1
- from .main import main
2
-
3
- if __name__ == "__main__":
4
- raise SystemExit(main())
1
+ from .main import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())