Skip to content

Commit 4fa63c0

Browse files
koubaaMohamed Koubaapre-commit-ci[bot]pyansys-ci-bot
authored
feat: get by subkeyword and add transform links (#735)
Co-authored-by: Mohamed Koubaa <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pyansys-ci-bot <[email protected]>
1 parent 148e571 commit 4fa63c0

File tree

18 files changed

+242
-38
lines changed

18 files changed

+242
-38
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
files: |
22
(?x)(
3+
^codegen/ |
34
^src/ansys/ |
45
^examples |
56
^.github/
67
)
78
exclude: |
89
(?x)^(
10+
codegen/kwd.json|
11+
codegen/additional-cards.json|
912
doc/source/|
1013
src/ansys/dyna/core/pre/Server/|
1114
src/ansys/dyna/core/pre/doc/|

codegen/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The class generator uses Jinja templates to generate three distinct things:
2929
The python classes are what users of PyDyna interact with directly. The import machinery produces
3030
`auto_keywords.py`, which contains a list of import statements that import classes from the
3131
Python files where they are defined. The keyword to type mapping produces a dictionary mapping the
32-
keyword name witht he python class that defines it.
32+
keyword name with the python class that defines it.
3333

3434
The primary specification for keywords is found in `kwd.json`. It contains basic definitions
3535
for most keywords, including their cards and fields (which are defined by offset, name, default

codegen/generate.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,9 @@
2929
import typing
3030

3131
from jinja2 import Environment, FileSystemLoader
32-
3332
import keyword_generation.data_model as data_model
3433
from keyword_generation.generators import generate_class, generate_entrypoints
35-
36-
from keyword_generation.utils import get_classname, get_this_folder, fix_keyword, handle_single_word_keyword
37-
34+
from keyword_generation.utils import fix_keyword, get_classname, get_this_folder, handle_single_word_keyword
3835

3936
SKIPPED_KEYWORDS = set(
4037
[
@@ -44,7 +41,7 @@
4441
"ELEMENT_SOLID (ten nodes format)",
4542
"ELEMENT_SOLID",
4643
"ELEMENT_SOLID_ORTHO (ten nodes format)",
47-
"ELEMENT_SOLID_ORTHO"
44+
"ELEMENT_SOLID_ORTHO",
4845
# issue #184 - this is not documented in the manual
4946
# "CONTROL_TIMESTEP",CONTROL_TIMESTEP is in the kwd.json now and should be generated issue #629
5047
]
@@ -253,7 +250,7 @@ def parse_args():
253250
"--output",
254251
"-o",
255252
default="",
256-
help="Output folder."
253+
help="Output folder.",
257254
# help="Output folder. Defaults to the location of generated code in pydyna."
258255
)
259256
parser.add_argument(

codegen/keyword_generation/generators/class_generator.py

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,24 @@
33
import typing
44

55
from jinja2 import Environment
6-
76
import keyword_generation.data_model as data_model
8-
9-
from keyword_generation.handlers.handler_base import KeywordHandler
7+
from keyword_generation.handlers.add_option import AddOptionHandler
8+
from keyword_generation.handlers.card_set import CardSetHandler
9+
from keyword_generation.handlers.conditional_card import ConditionalCardHandler
1010
from keyword_generation.handlers.external_card import ExternalCardHandler
11+
from keyword_generation.handlers.handler_base import KeywordHandler
12+
from keyword_generation.handlers.insert_card import InsertCardHandler
13+
from keyword_generation.handlers.override_field import OverrideFieldHandler
14+
from keyword_generation.handlers.override_subkeyword import OverrideSubkeywordHandler
15+
from keyword_generation.handlers.rename_property import RenamePropertyHandler
16+
from keyword_generation.handlers.reorder_card import ReorderCardHandler
17+
from keyword_generation.handlers.replace_card import ReplaceCardHandler
1118
from keyword_generation.handlers.series_card import SeriesCardHandler
1219
from keyword_generation.handlers.shared_field import SharedFieldHandler
20+
from keyword_generation.handlers.skip_card import SkipCardHandler
1321
from keyword_generation.handlers.table_card import TableCardHandler
1422
from keyword_generation.handlers.table_card_group import TableCardGroupHandler
15-
from keyword_generation.handlers.override_field import OverrideFieldHandler
16-
from keyword_generation.handlers.rename_property import RenamePropertyHandler
17-
from keyword_generation.handlers.conditional_card import ConditionalCardHandler
18-
from keyword_generation.handlers.add_option import AddOptionHandler
19-
from keyword_generation.handlers.override_subkeyword import OverrideSubkeywordHandler
20-
from keyword_generation.handlers.skip_card import SkipCardHandler
21-
from keyword_generation.handlers.insert_card import InsertCardHandler
22-
from keyword_generation.handlers.replace_card import ReplaceCardHandler
23-
from keyword_generation.handlers.card_set import CardSetHandler
24-
from keyword_generation.handlers.reorder_card import ReorderCardHandler
25-
26-
from keyword_generation.utils import fix_keyword, get_license_header, get_classname, handle_single_word_keyword
23+
from keyword_generation.utils import fix_keyword, get_classname, get_license_header, handle_single_word_keyword
2724

2825

2926
def _get_source_keyword(keyword, settings):
@@ -273,6 +270,51 @@ def _handle_keyword_data(kwd_data, settings):
273270
_after_handle(kwd_data)
274271

275272

273+
def _add_define_transform_link_data(link_data: typing.List[typing.Dict], link_fields: typing.List[str]):
274+
transform_link_data = {
275+
"classname": "DefineTransformation",
276+
"modulename": "define_transformation",
277+
"keyword_type": "DEFINE",
278+
"keyword_subtype": "TRANSFORMATION",
279+
"fields": link_fields,
280+
"linkid": "tranid",
281+
}
282+
link_data.append(transform_link_data)
283+
284+
285+
class LinkIdentity:
286+
DEFINE_TRANSFORMATION = 40
287+
288+
289+
def _get_links(kwd_data) -> typing.Optional[typing.Dict]:
290+
links = {LinkIdentity.DEFINE_TRANSFORMATION: []}
291+
has_link = False
292+
for card in kwd_data["cards"]:
293+
for field in _get_fields(card):
294+
if "link" not in field:
295+
continue
296+
link = field["link"]
297+
if link not in links.keys():
298+
continue
299+
has_link = True
300+
links[link].append(field["name"])
301+
if not has_link:
302+
return None
303+
return links
304+
305+
306+
def _add_links(kwd_data):
307+
"""Add "links", or properties that link one keyword to another."""
308+
links = _get_links(kwd_data)
309+
if links is None:
310+
return
311+
link_data = []
312+
for link_type, link_fields in links.items():
313+
if link_type == LinkIdentity.DEFINE_TRANSFORMATION:
314+
_add_define_transform_link_data(link_data, link_fields)
315+
kwd_data["links"] = link_data
316+
317+
276318
def _get_keyword_data(keyword_name, keyword, settings):
277319
"""Gets the keyword data dict from kwdm. Transforms it
278320
based on the generation settings that are passed in, if any,
@@ -288,6 +330,8 @@ def _get_keyword_data(keyword_name, keyword, settings):
288330

289331
# default transformations to a valid format we need for jinja
290332
_transform_data(kwd_data)
333+
334+
_add_links(kwd_data)
291335
return kwd_data
292336

293337

@@ -314,8 +358,12 @@ def generate_class(env: Environment, lib_path: str, item: typing.Dict) -> None:
314358
keyword = item["name"]
315359
fixed_keyword = fix_keyword(keyword)
316360
classname = item["options"].get("classname", get_classname(fixed_keyword))
317-
base_variable = _get_base_variable(classname, keyword, item["options"])
318-
jinja_variable = _get_jinja_variable(base_variable)
319-
filename = os.path.join(lib_path, "auto", fixed_keyword.lower() + ".py")
320-
with open(filename, "w", encoding="utf-8") as f:
321-
f.write(env.get_template("keyword.j2").render(**jinja_variable))
361+
try:
362+
base_variable = _get_base_variable(classname, keyword, item["options"])
363+
jinja_variable = _get_jinja_variable(base_variable)
364+
filename = os.path.join(lib_path, "auto", fixed_keyword.lower() + ".py")
365+
with open(filename, "w", encoding="utf-8") as f:
366+
f.write(env.get_template("keyword.j2").render(**jinja_variable))
367+
except Exception as e:
368+
print(f"Failure in generating {classname}")
369+
raise e

codegen/keyword_generation/generators/entrypoints_generator.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import typing
44

55
from jinja2 import Environment
6-
7-
from keyword_generation.utils import fix_keyword, get_license_header
6+
from keyword_generation.utils import get_license_header
87

98

109
def generate_entrypoints(env: Environment, lib_path: str, keywords_list: typing.List[typing.Dict]) -> None:

codegen/keyword_generation/handlers/card_set.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import copy
22
import typing
33

4-
from keyword_generation.data_model import get_card
54
import keyword_generation.data_model as gen
65
import keyword_generation.handlers.handler_base
76

codegen/keyword_generation/handlers/insert_card.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import typing
22

3-
from keyword_generation.data_model import get_card
43
import keyword_generation.data_model as gen
4+
from keyword_generation.data_model import get_card
55
import keyword_generation.handlers.handler_base
66

77

codegen/keyword_generation/handlers/table_card_group.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import typing
22

3-
import keyword_generation.handlers.handler_base
43
import keyword_generation.data_model as gen
4+
import keyword_generation.handlers.handler_base
55

66

77
class TableCardGroupHandler(keyword_generation.handlers.handler_base.KeywordHandler):

codegen/templates/keyword.j2

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec
3232
{% endif %}
3333
{% endif %}
3434
from ansys.dyna.core.lib.keyword_base import KeywordBase
35+
{% for link in keyword_data.links %}
36+
from ansys.dyna.core.keywords.keyword_classes.auto.{{link.modulename}} import {{link.classname}}
37+
{% endfor %}
3538

3639
{% if keyword_data.card_sets %}
3740
{% for card_set in keyword_data.card_sets.sets %}
@@ -141,4 +144,7 @@ class {{keyword_data.classname}}(KeywordBase):
141144
{% include 'keyword/option_card_properties.j2' %}
142145
{% endfor %}{# option in keyword_data.options #}
143146
{% endif %}{# keyword_data.options #}
147+
{% with links = keyword_data.links %}
148+
{% include 'keyword/links.j2' %}
149+
{% endwith %}
144150
{% include 'keyword/alias.j2' %}

codegen/templates/keyword/links.j2

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{% for link in links %}
2+
{% for field in link.fields %}
3+
@property
4+
def {{field}}_link(self) -> {{link.classname}}:
5+
if self.deck is None:
6+
return None
7+
for kwd in self.deck.get_kwds_by_full_type("{{link.keyword_type}}", "{{link.keyword_subtype}}"):
8+
if kwd.{{link.linkid}} == self.{{field}}:
9+
return kwd
10+
return None
11+
12+
@{{field}}_link.setter
13+
def {{field}}_link(self, value: {{link.classname}}) -> None:
14+
self.{{field}} = value.{{link.linkid}}
15+
16+
{% endfor %}{# field in link.fields #}
17+
{% endfor %}{# link in links #}

0 commit comments

Comments
 (0)