wowool-sdk-cpp 3.4.5__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.
- wowool_sdk_cpp-3.4.5/MANIFEST.in +14 -0
- wowool_sdk_cpp-3.4.5/PKG-INFO +33 -0
- wowool_sdk_cpp-3.4.5/common_setup.py +79 -0
- wowool_sdk_cpp-3.4.5/install_requires.txt +0 -0
- wowool_sdk_cpp-3.4.5/install_requires_wowool.txt +0 -0
- wowool_sdk_cpp-3.4.5/long_description.md +20 -0
- wowool_sdk_cpp-3.4.5/pre_setup.py +241 -0
- wowool_sdk_cpp-3.4.5/pyproject.toml +16 -0
- wowool_sdk_cpp-3.4.5/sdk_version.txt +1 -0
- wowool_sdk_cpp-3.4.5/setup.cfg +4 -0
- wowool_sdk_cpp-3.4.5/setup.py +508 -0
- wowool_sdk_cpp-3.4.5/version.txt +1 -0
- wowool_sdk_cpp-3.4.5/wowool/native/core/wowool_sdk.cpp +672 -0
- wowool_sdk_cpp-3.4.5/wowool/package/lib/wowool_plugin.py +22 -0
- wowool_sdk_cpp-3.4.5/wowool/package/lib/wowool_sdk.py +35 -0
- wowool_sdk_cpp-3.4.5/wowool/plugin/wowool_plugin.cpp +1432 -0
- wowool_sdk_cpp-3.4.5/wowool/plugin/wowool_plugin.hpp +157 -0
- wowool_sdk_cpp-3.4.5/wowool_sdk_cpp.egg-info/PKG-INFO +33 -0
- wowool_sdk_cpp-3.4.5/wowool_sdk_cpp.egg-info/SOURCES.txt +20 -0
- wowool_sdk_cpp-3.4.5/wowool_sdk_cpp.egg-info/dependency_links.txt +1 -0
- wowool_sdk_cpp-3.4.5/wowool_sdk_cpp.egg-info/not-zip-safe +1 -0
- wowool_sdk_cpp-3.4.5/wowool_sdk_cpp.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
include wowool/plugin/wowool_plugin.hpp
|
|
2
|
+
include sdk_version.txt
|
|
3
|
+
include version.txt
|
|
4
|
+
include install_requires.txt
|
|
5
|
+
include install_requires_wowool.txt
|
|
6
|
+
include pre_setup.py
|
|
7
|
+
include common_setup.py
|
|
8
|
+
global-exclude *.dylib
|
|
9
|
+
global-exclude *.so
|
|
10
|
+
global-exclude *.dll
|
|
11
|
+
exclude wowool/package/lib/wow
|
|
12
|
+
exclude wowool/package/lib/woc
|
|
13
|
+
exclude wowool/package/lib/afst
|
|
14
|
+
include long_description.md
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wowool-sdk-cpp
|
|
3
|
+
Version: 3.4.5
|
|
4
|
+
Summary: Wowool NLP Toolkit C++ SDK Python Bindings
|
|
5
|
+
Author: Wowool
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Dynamic: author
|
|
9
|
+
Dynamic: description
|
|
10
|
+
Dynamic: description-content-type
|
|
11
|
+
Dynamic: requires-python
|
|
12
|
+
Dynamic: summary
|
|
13
|
+
|
|
14
|
+
# The Wowool NLP CPP Bindings
|
|
15
|
+
|
|
16
|
+
## Introduction
|
|
17
|
+
|
|
18
|
+
This package contains the cpp bindings of the wowool-sdk and should not be install as a separated package, install the wowool-sdk instead which contains this package.
|
|
19
|
+
|
|
20
|
+
## License
|
|
21
|
+
|
|
22
|
+
In both cases you will need to acquirer a license file at https://www.wowool.com
|
|
23
|
+
|
|
24
|
+
### Non-Commercial
|
|
25
|
+
|
|
26
|
+
This library is licensed under the GNU AGPLv3 for non-commercial use.
|
|
27
|
+
For commercial use, a separate license must be purchased.
|
|
28
|
+
|
|
29
|
+
### Commercial license Terms
|
|
30
|
+
|
|
31
|
+
1. Grants the right to use this library in proprietary software.
|
|
32
|
+
2. Requires a valid license key
|
|
33
|
+
3. Redistribution in SaaS requires a commercial license.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def copy_with_lnk(src, dst):
|
|
7
|
+
dst = Path(dst)
|
|
8
|
+
src = Path(src)
|
|
9
|
+
|
|
10
|
+
if os.path.islink(src):
|
|
11
|
+
linkto = os.readlink(src)
|
|
12
|
+
|
|
13
|
+
# Remove existing destination if it exists
|
|
14
|
+
if os.path.lexists(dst):
|
|
15
|
+
os.unlink(dst)
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
# Try to determine if the link is relative or absolute
|
|
19
|
+
target_path = Path(linkto)
|
|
20
|
+
if not target_path.is_absolute():
|
|
21
|
+
# If relative, maintain the same relative path
|
|
22
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
23
|
+
dir_fd = os.open(dst.parent, os.O_RDONLY)
|
|
24
|
+
os.symlink(linkto, dst, dir_fd=dir_fd)
|
|
25
|
+
os.close(dir_fd)
|
|
26
|
+
if not os.path.islink(dst):
|
|
27
|
+
raise RuntimeError(f"Failed to create symlink {dst} -> {linkto}")
|
|
28
|
+
|
|
29
|
+
else:
|
|
30
|
+
# If absolute, we need to determine the new absolute path
|
|
31
|
+
# or just copy the file directly as a fallback
|
|
32
|
+
|
|
33
|
+
target_file = src.parent / linkto if not os.path.isabs(linkto) else Path(linkto)
|
|
34
|
+
if target_file.exists():
|
|
35
|
+
# Just copy the target file directly instead of creating a symlink
|
|
36
|
+
shutil.copy2(target_file, dst)
|
|
37
|
+
else:
|
|
38
|
+
# Create a symlink anyway, might work in some environments
|
|
39
|
+
os.symlink(linkto, dst)
|
|
40
|
+
|
|
41
|
+
except Exception as ex:
|
|
42
|
+
print(f"Error creating symlink: {ex}")
|
|
43
|
+
raise ex
|
|
44
|
+
else:
|
|
45
|
+
# Regular file copy
|
|
46
|
+
shutil.copy2(src, dst)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def copy_to_package_folder(site_packages: Path, wow_sdk_folder: Path, bin_folders: Path, inc_folders: Path, lib_folders: Path):
|
|
50
|
+
"""
|
|
51
|
+
Copy the files to the package folder
|
|
52
|
+
"""
|
|
53
|
+
print(f"[WOW] site_packages: {site_packages=}")
|
|
54
|
+
try:
|
|
55
|
+
wowool_package_lib = site_packages / "wowool" / "package" / "lib"
|
|
56
|
+
print(f"[WOW] wowool_package_lib: {wowool_package_lib=}")
|
|
57
|
+
wowool_package_lib.mkdir(parents=True, exist_ok=True)
|
|
58
|
+
|
|
59
|
+
for fn in bin_folders.glob("*"):
|
|
60
|
+
print(f"[WOW] bin: {fn.name}")
|
|
61
|
+
copy_with_lnk(fn, wowool_package_lib / fn.name)
|
|
62
|
+
|
|
63
|
+
for fn in lib_folders.glob("*"):
|
|
64
|
+
copy_with_lnk(fn, wowool_package_lib / fn.name)
|
|
65
|
+
|
|
66
|
+
print(f"[WOW] Folders : WOWOOL_STAGE: {wow_sdk_folder=} {inc_folders=} {lib_folders=}")
|
|
67
|
+
if lib_folders.exists() and inc_folders.exists():
|
|
68
|
+
os.environ["WOWOOL_STAGE"] = str(wow_sdk_folder)
|
|
69
|
+
# WOWOOL_STAGE = wow_sdk_folder
|
|
70
|
+
print("wowool.package folder:", wowool_package_lib)
|
|
71
|
+
else:
|
|
72
|
+
print(
|
|
73
|
+
"""[WOWOOL] You will need to set the WOWOOL_STAGE folder, to build the native package.
|
|
74
|
+
This should be in your environment ..../wowool/package"""
|
|
75
|
+
)
|
|
76
|
+
exit(-1)
|
|
77
|
+
except Exception as ex:
|
|
78
|
+
print(f"""[WOWOOL] {ex} Could not copy tile to stage folder""")
|
|
79
|
+
raise ex
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# The Wowool NLP CPP Bindings
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
This package contains the cpp bindings of the wowool-sdk and should not be install as a separated package, install the wowool-sdk instead which contains this package.
|
|
6
|
+
|
|
7
|
+
## License
|
|
8
|
+
|
|
9
|
+
In both cases you will need to acquirer a license file at https://www.wowool.com
|
|
10
|
+
|
|
11
|
+
### Non-Commercial
|
|
12
|
+
|
|
13
|
+
This library is licensed under the GNU AGPLv3 for non-commercial use.
|
|
14
|
+
For commercial use, a separate license must be purchased.
|
|
15
|
+
|
|
16
|
+
### Commercial license Terms
|
|
17
|
+
|
|
18
|
+
1. Grants the right to use this library in proprietary software.
|
|
19
|
+
2. Requires a valid license key
|
|
20
|
+
3. Redistribution in SaaS requires a commercial license.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import platform
|
|
5
|
+
from logging import getLogger
|
|
6
|
+
import subprocess
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
logger = getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
this_dir = Path(__file__).parent
|
|
12
|
+
fusion_root = None
|
|
13
|
+
fusion_root = this_dir
|
|
14
|
+
|
|
15
|
+
pi = platform.system()
|
|
16
|
+
tar_ext = "tar.gz" if pi != "Windows" else "zip"
|
|
17
|
+
app_ext = "" if pi != "Windows" else ".exe"
|
|
18
|
+
SO_EXT = ".so" if pi != "Windows" else ".pyd"
|
|
19
|
+
native_so_prefix = "lib" if pi != "Windows" else ""
|
|
20
|
+
if pi == "Windows":
|
|
21
|
+
NATIVE_SO_EXT = ".dll"
|
|
22
|
+
elif pi == "Darwin":
|
|
23
|
+
NATIVE_SO_EXT = ".dylib"
|
|
24
|
+
else:
|
|
25
|
+
NATIVE_SO_EXT = ".so"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_origin_keyword():
|
|
29
|
+
if platform.system() == "Darwin":
|
|
30
|
+
return "@loader_path"
|
|
31
|
+
elif platform.system() == "Linux":
|
|
32
|
+
return "$ORIGIN"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def call_subprocess(cmd_params):
|
|
36
|
+
cmd = " ".join(cmd_params)
|
|
37
|
+
try:
|
|
38
|
+
subprocess.run(cmd, shell=True, check=True)
|
|
39
|
+
except subprocess.CalledProcessError as ex:
|
|
40
|
+
logger.exception(f"Cannot run [{cmd}], {ex}")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_all_rpaths(filename):
|
|
44
|
+
if platform.system() == "Darwin":
|
|
45
|
+
cmd = ["otool", "-l", str(filename)]
|
|
46
|
+
if not filename.exists():
|
|
47
|
+
raise RuntimeError(f"File not there yet {filename}")
|
|
48
|
+
rpathlist = [line.strip() for line in subprocess.check_output(cmd).decode().split("\n")]
|
|
49
|
+
rpaths = []
|
|
50
|
+
pidx = -1
|
|
51
|
+
for idx, line in enumerate(rpathlist):
|
|
52
|
+
if line.startswith("cmd LC_RPATH"):
|
|
53
|
+
pidx = idx + 2
|
|
54
|
+
elif idx == pidx:
|
|
55
|
+
rpaths.append(line.split(" ")[1])
|
|
56
|
+
return rpaths
|
|
57
|
+
else:
|
|
58
|
+
assert False, "Not implemented for given platform."
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def remove_all_build_rpaths(filename):
|
|
62
|
+
if platform.system() == "Darwin":
|
|
63
|
+
build_paths = get_all_rpaths(filename)
|
|
64
|
+
for build_path in build_paths:
|
|
65
|
+
try:
|
|
66
|
+
cmd_params = ["install_name_tool", "-delete_rpath", str(build_path), str(filename)]
|
|
67
|
+
call_subprocess(cmd_params)
|
|
68
|
+
except Exception as ex:
|
|
69
|
+
logger.error(f"Failed to remove rpath {build_path} from {filename}: {ex}")
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
assert len(get_all_rpaths(filename)) == 0
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def remove_rpath(filename):
|
|
76
|
+
if platform.system() == "Darwin":
|
|
77
|
+
remove_all_build_rpaths(filename)
|
|
78
|
+
elif platform.system() == "Linux":
|
|
79
|
+
cmd_params = [
|
|
80
|
+
"patchelf",
|
|
81
|
+
"--remove-rpath",
|
|
82
|
+
str(filename),
|
|
83
|
+
]
|
|
84
|
+
call_subprocess(cmd_params)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def set_rpath_origin(filename):
|
|
88
|
+
if platform.system() == "Darwin":
|
|
89
|
+
cmd_params = ["install_name_tool", "-add_rpath", get_origin_keyword(), str(filename)]
|
|
90
|
+
call_subprocess(cmd_params)
|
|
91
|
+
elif platform.system() == "Linux":
|
|
92
|
+
cmd_params = [
|
|
93
|
+
"patchelf",
|
|
94
|
+
"--force-rpath",
|
|
95
|
+
"--set-rpath",
|
|
96
|
+
f"\\{get_origin_keyword()}",
|
|
97
|
+
str(filename),
|
|
98
|
+
]
|
|
99
|
+
call_subprocess(cmd_params)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def prep_build_setup(wow_stage: Path):
|
|
103
|
+
"""
|
|
104
|
+
Prepare the source folders
|
|
105
|
+
"""
|
|
106
|
+
logger.info(f"----------------- begin prepping {wow_stage}---------------------")
|
|
107
|
+
|
|
108
|
+
this_repo = Path(this_dir)
|
|
109
|
+
package_lxware_folder = this_repo / "wowool" / "package" / "lxware"
|
|
110
|
+
package_lib_folder = this_repo / "wowool" / "package" / "lib"
|
|
111
|
+
|
|
112
|
+
logger.debug(f"{this_repo}")
|
|
113
|
+
|
|
114
|
+
os.makedirs(package_lxware_folder, exist_ok=True)
|
|
115
|
+
|
|
116
|
+
stage_bin_folder = wow_stage / "bin"
|
|
117
|
+
stage_lib_folder = wow_stage / "lib"
|
|
118
|
+
|
|
119
|
+
icu_lib_folder = stage_lib_folder
|
|
120
|
+
|
|
121
|
+
tir_config_fn = wow_stage / "config.json"
|
|
122
|
+
if tir_config_fn.exists():
|
|
123
|
+
with open(tir_config_fn) as fh:
|
|
124
|
+
tir_config = json.load(fh)
|
|
125
|
+
TIR_VERSION = tir_config["version"]
|
|
126
|
+
|
|
127
|
+
sdk_version_fn = this_dir / "sdk_version.txt"
|
|
128
|
+
with open(sdk_version_fn) as fh:
|
|
129
|
+
current_sdk_version = fh.read().strip()
|
|
130
|
+
|
|
131
|
+
if current_sdk_version != TIR_VERSION:
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"""!!! The native python SDK requires version'{current_sdk_version}' of the cpp SDK, but found the version '{TIR_VERSION}' in {stage_lib_folder}\nChange {sdk_version_fn.stem}"""
|
|
134
|
+
)
|
|
135
|
+
else:
|
|
136
|
+
assert fusion_root
|
|
137
|
+
tir_version = this_dir / "sdk_version.txt"
|
|
138
|
+
if tir_version.exists():
|
|
139
|
+
with open(tir_version, "r") as fh:
|
|
140
|
+
TIR_VERSION = fh.read().strip()
|
|
141
|
+
else:
|
|
142
|
+
TIR_VERSION = os.environ["TIR_VERSION"]
|
|
143
|
+
|
|
144
|
+
# change the rpath for the end package to used $ORIGIN
|
|
145
|
+
pattern = f"*{NATIVE_SO_EXT}"
|
|
146
|
+
native_linux_pattern = f"*{NATIVE_SO_EXT}.{TIR_VERSION}"
|
|
147
|
+
|
|
148
|
+
platform_name = platform.system()
|
|
149
|
+
if "Windows" == platform_name:
|
|
150
|
+
icu_files = ["icudt.lib", "icuuc.lib"]
|
|
151
|
+
elif "Darwin" == platform_name:
|
|
152
|
+
icu_files = ["libicudata.dylib", "libicuuc.dylib"]
|
|
153
|
+
else:
|
|
154
|
+
icu_files = ["libicudata.so", "libicuuc.so"]
|
|
155
|
+
|
|
156
|
+
logger.info(f"{TIR_VERSION=} {package_lib_folder=} {native_linux_pattern=}")
|
|
157
|
+
|
|
158
|
+
package_lib_folder.mkdir(parents=True, exist_ok=True)
|
|
159
|
+
logger.info(f"copying native libs {stage_lib_folder} --> {package_lib_folder=} {package_lib_folder.exists()=}")
|
|
160
|
+
try:
|
|
161
|
+
for fn in stage_lib_folder.glob(native_linux_pattern):
|
|
162
|
+
target_fn = package_lib_folder / fn.name
|
|
163
|
+
logger.info(f"copy {fn} --> {target_fn}")
|
|
164
|
+
|
|
165
|
+
if fn.is_symlink():
|
|
166
|
+
logger.info(f"{fn} is symlink, skipping")
|
|
167
|
+
continue
|
|
168
|
+
shutil.copy2(fn, target_fn)
|
|
169
|
+
logger.info(f"[ok] copy {fn} --> {target_fn}")
|
|
170
|
+
# remove_rpath(target_fn)
|
|
171
|
+
# set_rpath_origin(target_fn)
|
|
172
|
+
except Exception as ex:
|
|
173
|
+
logger.error(f"Failed to copy native lib {ex}")
|
|
174
|
+
raise ex
|
|
175
|
+
|
|
176
|
+
logger.info(f"copying {stage_lib_folder=} to {package_lib_folder=} {package_lib_folder.exists()=}")
|
|
177
|
+
for fn in stage_lib_folder.glob(pattern):
|
|
178
|
+
target_fn = package_lib_folder / fn.name
|
|
179
|
+
if target_fn.name.startswith("_"):
|
|
180
|
+
continue
|
|
181
|
+
if fn.is_symlink():
|
|
182
|
+
# do not copy symlinks.
|
|
183
|
+
# shutil.copy2(fn, package_lib_folder / fn.name , follow_symlinks=False )
|
|
184
|
+
pass
|
|
185
|
+
else:
|
|
186
|
+
if target_fn.exists():
|
|
187
|
+
target_fn.unlink()
|
|
188
|
+
target_fn.parent.mkdir(parents=True, exist_ok=True)
|
|
189
|
+
logger.info(f"!!!!! COPY3 {fn} --> {target_fn}")
|
|
190
|
+
shutil.copy2(fn, target_fn)
|
|
191
|
+
|
|
192
|
+
# copy icu
|
|
193
|
+
logger.info("----------------- before ---------------------")
|
|
194
|
+
for fn in package_lib_folder.glob("**/*"):
|
|
195
|
+
logger.info(f"package: {fn}")
|
|
196
|
+
|
|
197
|
+
for fn in icu_files:
|
|
198
|
+
target_fn = package_lib_folder / fn
|
|
199
|
+
shutil.copy2(icu_lib_folder / fn, target_fn)
|
|
200
|
+
# remove_rpath(target_fn)
|
|
201
|
+
# set_rpath_origin(target_fn)
|
|
202
|
+
|
|
203
|
+
if "Windows" == platform_name:
|
|
204
|
+
# for windows we also need to copy the dll
|
|
205
|
+
bin_files = [[fn] for fn in stage_bin_folder.glob("*.dll")]
|
|
206
|
+
bin_files.append([stage_bin_folder / "wow.exe", "wow++.exe"])
|
|
207
|
+
bin_files.append([stage_bin_folder / "woc.exe", "woc++.exe"])
|
|
208
|
+
bin_files.append([stage_bin_folder / "afst.exe", "afst++.exe"])
|
|
209
|
+
else:
|
|
210
|
+
bin_files = []
|
|
211
|
+
bin_files.append([stage_bin_folder / "wow", "wow++"])
|
|
212
|
+
bin_files.append([stage_bin_folder / "woc", "woc++"])
|
|
213
|
+
bin_files.append([stage_bin_folder / "afst", "afst++"])
|
|
214
|
+
|
|
215
|
+
for fn in bin_files:
|
|
216
|
+
if len(fn) == 1:
|
|
217
|
+
target_fn = package_lib_folder / fn[0].name
|
|
218
|
+
else:
|
|
219
|
+
target_fn = package_lib_folder / fn[1]
|
|
220
|
+
|
|
221
|
+
shutil.copy2(fn[0], target_fn)
|
|
222
|
+
remove_rpath(target_fn)
|
|
223
|
+
logger.info(f"set_rpath_origin {target_fn}")
|
|
224
|
+
set_rpath_origin(target_fn)
|
|
225
|
+
logger.info("----------------- end prepping ---------------------")
|
|
226
|
+
for fn in package_lib_folder.glob("**/*"):
|
|
227
|
+
if "__pycache_" not in str(fn):
|
|
228
|
+
logger.info(f"package: {fn}")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def post_build_setup(stage: Path):
|
|
232
|
+
"""
|
|
233
|
+
Prepare the source folders
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
print("post_build ... ")
|
|
237
|
+
files = [fn for fn in stage.glob(f"lib/*{NATIVE_SO_EXT}")]
|
|
238
|
+
for fn in files:
|
|
239
|
+
print(f"post_build : remove rpaths {fn}")
|
|
240
|
+
remove_rpath(fn)
|
|
241
|
+
set_rpath_origin(fn)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[tool.black]
|
|
2
|
+
line-length = 140
|
|
3
|
+
|
|
4
|
+
[tool.pytest.ini_options]
|
|
5
|
+
pythonpath = [
|
|
6
|
+
"."
|
|
7
|
+
]
|
|
8
|
+
testpaths= [ "tests/wowool/native/core" ]
|
|
9
|
+
|
|
10
|
+
addopts = [
|
|
11
|
+
"--import-mode=importlib"
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[build-system]
|
|
15
|
+
requires = ["setuptools >= 65.5.0" , "requests"]
|
|
16
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.1.2
|