forked from SynaLinks/synalinks
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi_gen.py
More file actions
101 lines (82 loc) · 3.62 KB
/
api_gen.py
File metadata and controls
101 lines (82 loc) · 3.62 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
# Modified from: keras/api_gen.py
# Original authors: François Chollet et al. (Keras Team)
# License Apache 2.0: (c) 2025 Yoan Sallami (Synalinks Team)
"""Script to generate synalinks public API in `synalinks/api` directory.
Usage:
Run via `./shell/api_gen.sh`.
It generates API and formats user and generated APIs.
"""
import importlib
import os
import shutil
import namex
PACKAGE = "synalinks"
BUILD_DIR_NAME = "tmp_build_dir"
def ignore_files(_, filenames):
return [f for f in filenames if f.endswith("_test.py")]
def copy_source_to_build_directory(root_path):
# Copy sources (`synalinks/` directory and setup files) to build dir
build_dir = os.path.join(root_path, BUILD_DIR_NAME)
if os.path.exists(build_dir):
shutil.rmtree(build_dir)
os.mkdir(build_dir)
shutil.copytree(PACKAGE, os.path.join(build_dir, PACKAGE), ignore=ignore_files)
return build_dir
def export_version_string(api_init_fname):
with open(api_init_fname) as f:
contents = f.read()
with open(api_init_fname, "w") as f:
contents += "from synalinks.src.version import __version__\n"
f.write(contents)
def update_package_init(template_fname, dest_fname, api_module):
with open(template_fname) as template_file:
with open(dest_fname, "w") as dest_file:
for line in template_file:
if "# DO NOT EDIT." in line:
dest_file.write(line)
# Import all public symbols from `api/` and `__version__`.
for symbol in api_module.__dict__.keys():
if symbol.startswith("_") and symbol != "__version__":
continue
dest_file.write(f"from synalinks.api import {symbol}\n")
# Skip the previous autogenerated block.
for line in template_file:
if "# END DO NOT EDIT." in line:
break
dest_file.write(line)
def build():
# Backup the `synalinks/__init__.py` and restore it on error in api gen.
root_path = os.path.dirname(os.path.abspath(__file__))
code_api_dir = os.path.join(root_path, PACKAGE, "api")
code_init_fname = os.path.join(root_path, PACKAGE, "__init__.py")
# Create temp build dir
build_dir = copy_source_to_build_directory(root_path)
build_api_dir = os.path.join(build_dir, PACKAGE, "api")
build_init_fname = os.path.join(build_dir, PACKAGE, "__init__.py")
build_api_init_fname = os.path.join(build_api_dir, "__init__.py")
try:
os.chdir(build_dir)
# Generates `synalinks/api` directory.
if os.path.exists(build_api_dir):
shutil.rmtree(build_api_dir)
if os.path.exists(build_init_fname):
os.remove(build_init_fname)
os.makedirs(build_api_dir)
namex.generate_api_files(
"synalinks", code_directory="src", target_directory="api"
)
# Add __version__ to `api/`.
export_version_string(build_api_init_fname)
# Update toplevel init with all `api/` imports.
api_module = importlib.import_module(f"{BUILD_DIR_NAME}.synalinks.api")
update_package_init(code_init_fname, build_init_fname, api_module)
# Copy back the synalinks/api and synalinks/__init__.py from build directory
if os.path.exists(code_api_dir):
shutil.rmtree(code_api_dir)
shutil.copytree(build_api_dir, code_api_dir)
shutil.copy(build_init_fname, code_init_fname)
finally:
# Clean up: remove the build directory (no longer needed)
shutil.rmtree(build_dir)
if __name__ == "__main__":
build()