Skip to content

Commit da3f1da

Browse files
authored
Merge branch 'master' into rcanton/remove_result_props
2 parents d3703a8 + a175c71 commit da3f1da

File tree

294 files changed

+38406
-3962
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

294 files changed

+38406
-3962
lines changed

.ci/code_generation.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,36 @@
1111
core.set_default_server_context(core.AvailableServerContexts.premium)
1212
core.start_local_server(config=core.AvailableServerConfigs.LegacyGrpcServer)
1313

14+
files_to_keep = {
15+
"operator.mustache": "",
16+
"build.py": "",
17+
"specification.py": "",
18+
"translator.py": "",
19+
# Deprecated operator scripting names
20+
"result": [
21+
"gasket_deformation.py",
22+
"gasket_deformation_X.py",
23+
"gasket_deformation_XY.py",
24+
"gasket_deformation_XZ.py",
25+
],
26+
}
27+
1428
local_dir = Path(__file__).parent
1529
TARGET_PATH = local_dir.parent / "src" / "ansys" / "dpf" / "core" / "operators"
1630
files = TARGET_PATH.glob("*")
1731
for file_path in files:
18-
if file_path.stem == "specification":
19-
continue
20-
if file_path.stem == "translator":
21-
continue
22-
if file_path.name == "build.py":
32+
if file_path.is_file() and (file_path.name in files_to_keep):
2333
continue
24-
if file_path.name == "operator.mustache":
25-
continue
26-
try:
27-
if file_path.is_dir():
28-
shutil.rmtree(file_path)
34+
if file_path.is_dir():
35+
shutil.rmtree(file_path / "__pycache__", ignore_errors=True)
36+
if file_path.name in files_to_keep:
37+
sub_files = file_path.glob("*")
38+
for sub_file in sub_files:
39+
if sub_file.name not in files_to_keep[file_path.name]:
40+
sub_file.unlink()
2941
else:
30-
file_path.unlink()
31-
except:
32-
pass
42+
shutil.rmtree(file_path)
43+
else:
44+
file_path.unlink()
3345

3446
build.build_operators()

.ci/generate_operators_doc.py

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
import argparse
2+
from pathlib import Path
3+
4+
from jinja2 import Template
5+
6+
from ansys.dpf import core as dpf
7+
from ansys.dpf.core.changelog import Changelog
8+
from ansys.dpf.core.core import load_library
9+
from ansys.dpf.core.dpf_operator import available_operator_names
10+
11+
12+
def initialize_server(ansys_path=None, include_composites=False, include_sound=False):
13+
server = dpf.start_local_server(ansys_path=ansys_path)
14+
print(server.plugins)
15+
print(f"Ansys Path: {server.ansys_path}")
16+
print(f"Server Info: {server.info}")
17+
print(f"Server Context: {server.context}")
18+
print(f"Server Config: {server.config}")
19+
print(f"Server version: {dpf.global_server().version}")
20+
if include_composites:
21+
print("Loading Composites Plugin")
22+
load_library(
23+
Path(server.ansys_path)
24+
/ "dpf"
25+
/ "plugins"
26+
/ "dpf_composites"
27+
/ "composite_operators.dll"
28+
)
29+
if include_sound:
30+
print("Loading Acoustics Plugin")
31+
load_library(Path(server.ansys_path) / "Acoustics" / "SAS" / "ads" / "dpf_sound.dll")
32+
return server
33+
34+
35+
def fetch_doc_info(server, operator_name):
36+
spec = dpf.Operator.operator_specification(op_name=operator_name, server=server)
37+
input_info = []
38+
output_info = []
39+
configurations_info = []
40+
for input_pin in spec.inputs:
41+
input = spec.inputs[input_pin]
42+
input_info.append(
43+
{
44+
"pin_number": input_pin,
45+
"name": input.name,
46+
"types": [str(t) for t in input._type_names],
47+
"document": input.document,
48+
"optional": input.optional,
49+
}
50+
)
51+
for output_pin in spec.outputs:
52+
output = spec.outputs[output_pin]
53+
output_info.append(
54+
{
55+
"pin_number": output_pin,
56+
"name": output.name,
57+
"types": [str(t) for t in output._type_names],
58+
"document": output.document,
59+
"optional": output.optional,
60+
}
61+
)
62+
for configuration_key in spec.config_specification:
63+
configuration = spec.config_specification[configuration_key]
64+
configurations_info.append(
65+
{
66+
"name": configuration.name,
67+
"types": [str(t) for t in configuration.type_names],
68+
"document": configuration.document,
69+
"default_value": configuration.default_value_str,
70+
}
71+
)
72+
properties = spec.properties
73+
plugin = properties.pop("plugin", "N/A")
74+
75+
category = properties.pop("category", None)
76+
77+
scripting_name = properties.pop("scripting_name", None)
78+
if category and scripting_name:
79+
full_name = category + "." + scripting_name
80+
else:
81+
full_name = None
82+
83+
user_name = properties.pop("user_name", operator_name)
84+
85+
# Retrieve version and changelog using the Changelog class
86+
if hasattr(spec, "changelog") and isinstance(spec.changelog, dpf.GenericDataContainer):
87+
changelog_gdc = spec.changelog
88+
changelog = Changelog(gdc=changelog_gdc, server=server)
89+
last_version = changelog.last_version
90+
changelog_entries = [
91+
f"Version {str(version)}: {changelog[version]}" for version in changelog.versions
92+
]
93+
else:
94+
last_version = "0.0.0"
95+
changelog_entries = [f"Version {last_version}: Initial release."]
96+
97+
op_friendly_name = user_name
98+
if category:
99+
op_friendly_name = category + ":" + op_friendly_name
100+
101+
license = properties.pop("license", "None")
102+
103+
exposure = properties.pop("exposure", "private")
104+
scripting_info = {
105+
"category": category,
106+
"plugin": plugin,
107+
"scripting_name": scripting_name,
108+
"full_name": full_name,
109+
"internal_name": operator_name,
110+
"license": license,
111+
"version": str(last_version), # Include last version in scripting_info
112+
"changelog": changelog_entries, # Include all changelog entries
113+
}
114+
115+
return {
116+
"operator_name": op_friendly_name,
117+
"operator_description": spec.description,
118+
"inputs": input_info,
119+
"outputs": output_info,
120+
"configurations": configurations_info,
121+
"scripting_info": scripting_info,
122+
"exposure": exposure,
123+
}
124+
125+
126+
def get_plugin_operators(server, plugin_name):
127+
operators = available_operator_names(server)
128+
plugin_operators = []
129+
for operator_name in operators:
130+
spec = dpf.Operator.operator_specification(op_name=operator_name, server=server)
131+
if "plugin" in spec.properties and spec.properties["plugin"] == plugin_name:
132+
plugin_operators.append(operator_name)
133+
return plugin_operators
134+
135+
136+
def generate_operator_doc(server, operator_name, include_private):
137+
operator_info = fetch_doc_info(server, operator_name)
138+
scripting_name = operator_info["scripting_info"]["scripting_name"]
139+
category = operator_info["scripting_info"]["category"]
140+
if scripting_name:
141+
file_name = scripting_name
142+
else:
143+
file_name = operator_name
144+
if "::" in file_name:
145+
file_name = file_name.replace("::", "_")
146+
if not include_private and operator_info["exposure"] == "private":
147+
return
148+
script_path = Path(__file__)
149+
root_dir = script_path.parent.parent
150+
template_dir = Path(root_dir) / "doc" / "source" / "operators_doc" / "operator-specifications"
151+
category_dir = Path(template_dir) / category
152+
if category is not None:
153+
category_dir.mkdir(parents=True, exist_ok=True) # Ensure all parent directories are created
154+
file_dir = category_dir
155+
else:
156+
file_dir = template_dir
157+
with Path.open(Path(template_dir) / "operator_doc_template.md", "r") as file:
158+
template = Template(file.read())
159+
160+
output = template.render(operator_info)
161+
with Path.open(Path(file_dir) / f"{file_name}.md", "w") as file:
162+
file.write(output)
163+
164+
165+
def generate_toc_tree(docs_path):
166+
# Target the operator-specifications folder for iteration
167+
# operator_specs_path = docs_path / "operator-specifications"
168+
data = []
169+
for folder in docs_path.iterdir():
170+
if folder.is_dir(): # Ensure 'folder' is a directory
171+
category = folder.name
172+
operators = [] # Reset operators for each category
173+
for file in folder.iterdir():
174+
if (
175+
file.is_file() and file.suffix == ".md"
176+
): # Ensure 'file' is a file with .md extension
177+
file_name = file.name
178+
file_path = f"{category}/{file_name}"
179+
operator_name = file_name.replace("_", " ").replace(".md", "")
180+
operators.append({"operator_name": operator_name, "file_path": file_path})
181+
data.append({"category": category, "operators": operators})
182+
183+
# Render the Jinja2 template
184+
template_path = docs_path / "toc_template.j2"
185+
with Path.open(template_path, "r") as template_file:
186+
template = Template(template_file.read())
187+
output = template.render(data=data) # Pass 'data' as a named argument
188+
189+
# Write the rendered output to toc.yml at the operators_doc level
190+
# toc_path = docs_path / "toc.yml"
191+
with Path.open(docs_path / "toc.yml", "w") as file:
192+
file.write(output)
193+
194+
195+
def main():
196+
parser = argparse.ArgumentParser(description="Fetch available operators")
197+
parser.add_argument("--plugin", help="Filter operators by plugin")
198+
parser.add_argument(
199+
"--ansys_path", default=None, help="Path to Ansys DPF Server installation directory"
200+
)
201+
parser.add_argument("--include_private", action="store_true", help="Include private operators")
202+
parser.add_argument(
203+
"--include_composites", action="store_true", help="Include composites operators"
204+
)
205+
parser.add_argument("--include_sound", action="store_true", help="Include sound operators")
206+
args = parser.parse_args()
207+
desired_plugin = args.plugin
208+
209+
server = initialize_server(args.ansys_path, args.include_composites, args.include_sound)
210+
if desired_plugin is None:
211+
operators = available_operator_names(server)
212+
else:
213+
operators = get_plugin_operators(server, desired_plugin)
214+
for operator_name in operators:
215+
generate_operator_doc(server, operator_name, args.include_private)
216+
217+
docs_path = (
218+
Path(__file__).parent.parent
219+
/ "doc"
220+
/ "source"
221+
/ "operators_doc"
222+
/ "operator-specifications"
223+
)
224+
print(docs_path)
225+
generate_toc_tree(docs_path)
226+
227+
228+
if __name__ == "__main__":
229+
main()

0 commit comments

Comments
 (0)