Skip to content

Commit 7371aae

Browse files
authored
Merge branch 'main' into feat/support-windows-based-containers
2 parents bcb90a2 + 613e220 commit 7371aae

File tree

62 files changed

+2495
-225
lines changed

Some content is hidden

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

62 files changed

+2495
-225
lines changed

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
- name: "Build the wheel"
8080
shell: pwsh
8181
run: |
82-
tox -e build-wheel
82+
tox -e build-wheel -- "any"
8383
8484
- name: "Expose the wheel"
8585
shell: bash

doc/source/_static/dpf_operators.html

Lines changed: 205 additions & 145 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ requires = ["setuptools>=61.0.0", "wheel"]
55
[project]
66
# Check https://setuptools.pypa.io/en/stable/userguide/quickstart.html for all available sections
77
name = "ansys-dpf-core"
8-
version = "0.14.2.dev0"
8+
version = "0.14.3.dev0"
99
description = "Data Processing Framework - Python Core "
1010
readme = "README.md"
1111
requires-python = ">=3.9, <4"

requirements/requirements_build.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
black==25.1.0
1+
black==25.9.0
22
build==1.3.0
33
chevron==0.14.0
44
pypandoc_binary==1.15

requirements/requirements_docs.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ansys-sphinx-theme[autoapi]==1.5.3
1+
ansys-sphinx-theme[autoapi]==1.6.3
22
enum-tools[sphinx]==0.13.0
33
graphviz==0.21
44
imageio==2.37.0
@@ -7,7 +7,7 @@ jupyter_sphinx==0.5.3
77
nbsphinx==0.9.5
88
pypandoc==1.15
99
pytest-sphinx==0.6.3
10-
pyvista==0.46.1
10+
pyvista==0.46.3
1111
sphinx==8.2.3
1212
sphinx-copybutton==0.5.2
1313
sphinx-gallery==0.19.0
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
importlib-metadata==8.7.0
2-
numpy==2.2.4
2+
numpy==2.3.4
33
packaging==25.0
4-
psutil==7.0.0
4+
psutil==7.1.1
55
tqdm==4.67.1

requirements/requirements_test.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
ansys-platform-instancemanagement==1.1.2
2-
coverage==7.10.6
2+
coverage==7.11.0
33
graphviz==0.21
44
imageio==2.37.0
55
imageio-ffmpeg==0.6.0
@@ -8,6 +8,6 @@ pypandoc_binary==1.15
88
pytest==8.4.2
99
pytest-cov==6.2.1
1010
pytest-order==1.3.0
11-
pytest-rerunfailures==16.0.1
12-
pyvista==0.46.1
11+
pytest-rerunfailures==16.1
12+
pyvista==0.46.3
1313
vtk==9.4.2

src/ansys/dpf/core/__init__.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,17 +109,16 @@
109109
from ansys.dpf.core.dpf_operator import available_operator_names
110110

111111

112-
from ansys.dpf.core.collection import CollectionFactory as _CollectionFactory
113112
from ansys.dpf.core.collection import Collection as _Collection
114113
from ansys.dpf.core.label_space import LabelSpace
115114

116115

117116
# register classes for collection types:
118-
CustomTypeFieldsCollection:type = _CollectionFactory(CustomTypeField)
119-
GenericDataContainersCollection:type = _CollectionFactory(GenericDataContainer)
120-
StringFieldsCollection:type = _CollectionFactory(StringField)
121-
OperatorsCollection: type = _CollectionFactory(Operator)
122-
AnyCollection:type = _Collection
117+
CustomTypeFieldsCollection = _Collection.collection_factory(CustomTypeField)
118+
GenericDataContainersCollection = _Collection.collection_factory(GenericDataContainer)
119+
StringFieldsCollection = _Collection.collection_factory(StringField)
120+
OperatorsCollection = _Collection.collection_factory(Operator)
121+
AnyCollection = _Collection
123122

124123
# for matplotlib
125124
# solves "QApplication: invalid style override passed, ignoring it."

src/ansys/dpf/core/collection.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,18 @@
2525

2626
from __future__ import annotations
2727

28+
from typing import Generic, Type, TypeVar
29+
2830
from ansys.dpf.core import errors, server as server_module
2931
from ansys.dpf.core.any import Any
30-
from ansys.dpf.core.collection_base import TYPE, CollectionBase
32+
from ansys.dpf.core.collection_base import CollectionBase
3133
from ansys.dpf.core.common import create_dpf_instance
3234

35+
TYPE = TypeVar("TYPE")
36+
3337

34-
class Collection(CollectionBase[TYPE]):
38+
# Explicit Generic[TYPE] helps some type checkers Collection as a generic.
39+
class Collection(CollectionBase[TYPE], Generic[TYPE]):
3540
"""Represents a collection of dpf objects organised by label spaces.
3641
3742
Parameters
@@ -120,16 +125,39 @@ def add_entry(self, label_space, entry):
120125
"""
121126
return super()._add_entry(label_space, Any.new_from(entry, server=self._server))
122127

128+
@classmethod
129+
def collection_factory(cls, subtype: TYPE) -> Type[Collection[TYPE]]:
130+
"""Create classes deriving from Collection at runtime for a given subtype.
123131
124-
def CollectionFactory(subtype, BaseClass=Collection):
125-
"""Create classes deriving from Collection at runtime for a given subtype."""
132+
This factory method dynamically creates a new class that inherits from Collection
133+
and is specialized for storing entries of the specified subtype.
126134
127-
def __init__(self, **kwargs):
128-
BaseClass.__init__(self, **kwargs)
135+
Parameters
136+
----------
137+
subtype : type
138+
Any recognized DPF type. For example, CustomTypeField, GenericDataContainer,
139+
StringField, Operator, etc. This type will be used as the entries_type for
140+
the new collection class.
129141
130-
new_class = type(
131-
str(subtype.__name__) + "sCollection",
132-
(BaseClass,),
133-
{"__init__": __init__, "entries_type": subtype},
134-
)
135-
return new_class
142+
Returns
143+
-------
144+
Type[Collection[TYPE]]
145+
A new class that inherits from Collection and is specialized for the given
146+
subtype. The class name will be "{subtype.__name__}sCollection".
147+
148+
Examples
149+
--------
150+
>>> from ansys.dpf.core.string_field import StringField
151+
>>> from ansys.dpf.core.collection import Collection
152+
>>> string_fields_collection = Collection.collection_factory(StringField)()
153+
>>> string_fields_collection.__class__.__name__
154+
'StringFieldsCollection'
155+
>>> string_fields_collection.entries_type.__name__
156+
'StringField'
157+
"""
158+
new_class = type(
159+
str(subtype.__name__) + "sCollection",
160+
(cls,),
161+
{"entries_type": subtype},
162+
)
163+
return new_class

src/ansys/dpf/core/documentation/generate_operators_doc.py

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ def extract_operator_description_update(content: str) -> str:
120120
The updated description to use for the operator.
121121
"""
122122
match = re.search(r"## Description\s*(.*?)\s*(?=## |\Z)", content, re.DOTALL)
123-
return match.group(0) + os.linesep if match else None
123+
description = match.group(0) + os.linesep if match else None
124+
# Handle unicode characters
125+
return description.encode("unicode-escape").decode()
124126

125127

126128
def replace_operator_description(original_documentation: str, new_description: str):
@@ -293,9 +295,11 @@ def fetch_doc_info(server: dpf.AnyServerType, operator_name: str) -> dict:
293295
"changelog": changelog_entries, # Include all changelog entries
294296
}
295297

298+
op_description = latex_to_dollars(spec.description)
299+
296300
return {
297301
"operator_name": op_friendly_name,
298-
"operator_description": spec.description,
302+
"operator_description": op_description,
299303
"inputs": input_info,
300304
"outputs": output_info,
301305
"configurations": configurations_info,
@@ -304,6 +308,19 @@ def fetch_doc_info(server: dpf.AnyServerType, operator_name: str) -> dict:
304308
}
305309

306310

311+
def latex_to_dollars(text: str) -> str:
312+
r"""Convert LaTeX math delimiters from \\[.\\] to $$.$$ and from \\(.\\) to $.$ in a given text.
313+
314+
Parameters
315+
----------
316+
text:
317+
The input text containing LaTeX math delimiters.
318+
"""
319+
return (
320+
text.replace(r"\\[", "$$").replace(r"\\]", "$$").replace(r"\\(", "$").replace(r"\\)", "$")
321+
)
322+
323+
307324
def get_plugin_operators(server: dpf.AnyServerType, plugin_name: str) -> list[str]:
308325
"""Get the list of operators for a given plugin.
309326
@@ -348,7 +365,7 @@ def generate_operator_doc(
348365
"""
349366
operator_info = fetch_doc_info(server, operator_name)
350367
scripting_name = operator_info["scripting_info"]["scripting_name"]
351-
category = operator_info["scripting_info"]["category"]
368+
category: str = operator_info["scripting_info"]["category"]
352369
if scripting_name:
353370
file_name = scripting_name
354371
else:
@@ -391,7 +408,10 @@ def update_toc_tree(docs_path: Path):
391408
operators = [] # Reset operators for each category
392409
for file in folder.iterdir():
393410
if (
394-
file.is_file() and file.suffix == ".md" and not file.name.endswith("_upd.md")
411+
file.is_file()
412+
and file.suffix == ".md"
413+
and not file.name.endswith("_upd.md")
414+
and not file.name.endswith("_category.md")
395415
): # Ensure 'file' is a file with .md extension
396416
file_name = file.name
397417
file_path = f"{category}/{file_name}"
@@ -419,6 +439,60 @@ def update_toc_tree(docs_path: Path):
419439
file.write(new_toc)
420440

421441

442+
def update_categories(docs_path: Path):
443+
"""Update the category index files for the operator specifications.
444+
445+
Parameters
446+
----------
447+
docs_path:
448+
Path to the root of the DPF documentation sources.
449+
450+
"""
451+
specs_path = docs_path / Path("operator-specifications")
452+
for folder in specs_path.iterdir():
453+
if folder.is_dir(): # Ensure 'folder' is a directory
454+
category = folder.name
455+
operators = [] # Reset operators for each category
456+
for file in folder.iterdir():
457+
if (
458+
file.is_file()
459+
and file.suffix == ".md"
460+
and not file.name.endswith("_upd.md")
461+
and not file.name.endswith("_category.md")
462+
): # Ensure 'file' is a file with .md extension
463+
file_name = file.name
464+
operator_name = file_name.replace("_", " ").replace(".md", "")
465+
operators.append({"operator_name": operator_name, "file_path": file_name})
466+
# Update category index file
467+
category_file_path = folder / f"{category}_category.md"
468+
with category_file_path.open(mode="w") as cat_file:
469+
cat_file.write(f"# {category.capitalize()} operators\n\n")
470+
for operator in operators:
471+
cat_file.write(f"- [{operator['operator_name']}]({operator['file_path']})\n")
472+
473+
474+
def update_operator_index(docs_path: Path):
475+
"""Update the main index file for all operator specifications.
476+
477+
Parameters
478+
----------
479+
docs_path:
480+
Path to the root of the DPF documentation sources.
481+
482+
"""
483+
specs_path = docs_path / Path("operator-specifications")
484+
index_file_path = specs_path / "operator-specifications.md"
485+
with index_file_path.open(mode="w") as index_file:
486+
index_file.write("# Operator Specifications\n\n")
487+
for folder in specs_path.iterdir():
488+
if folder.is_dir(): # Ensure 'folder' is a directory
489+
category = folder.name
490+
index_file.write(
491+
f"- [{category.capitalize()} operators]({category}/{category}_category.md)\n\n"
492+
)
493+
index_file.write("\n")
494+
495+
422496
def generate_operators_doc(
423497
output_path: Path,
424498
ansys_path: Path = None,
@@ -461,6 +535,10 @@ def generate_operators_doc(
461535
generate_operator_doc(server, operator_name, include_private, output_path)
462536
# Generate the toc tree
463537
update_toc_tree(output_path)
538+
# Generate the category index files
539+
update_categories(output_path)
540+
# Generate the main index file for all categories
541+
update_operator_index(output_path)
464542
# Use update files in output_path
465543
update_operator_descriptions(output_path)
466544

0 commit comments

Comments
 (0)