API Reference: exposure, wording & other issues
- Dominant language
- Python
- Stars
- 497
- Forks
- 77
- Avg merge
- 22h 37m
- Merged PRs (30d)
- 45
Description
The API Reference provides poor overall experience due to exposure, wording & other issues.
# Executive summary
## Status
The API reference is generated faithfully from the expose module structure, but the module structure itself is not well designed. The result is that the API reference is almost completely unusable. The only adaptation that is done to the module names is to convert them to sentence case, which is not enough to make the API reference usable, and only makes those names less readable and separated from the actual code modules. The module structure itself needs to be improved.
## Action items
- Revert from sentence-case mapping of module names to simply rendering raw names, so that the API reference becomes a pure representation of the public module structure with a one-to-one correspondence between the quality of each.
- Carefully curate the public module hierarchy.
- Use `__all__` throughout the hierarchy to be explicit.
- Eliminate unnecessary breadth through grouping (e.g. `session` parent module).
- Use progressive disclosure to avoid overwhelming the user with too many high-level items.
- Selectively improve module naming.
- Complete API annotations.
# Detailed proposal
## 1. What real usage tells us
From `src/ansys/fluent/core/__init__.py`, the tests, the examples under `examples/`, and the user guide under `doc/source/user_guide/`, the actually-consumed public surface is small:
| Public symbol | Source | Notes |
|---|---|---|
| `launch_fluent`, `connect_to_fluent`, `FluentMode`, `Dimension`, `Precision`, `UIMode`, `FluentWindowsGraphicsDriver`, `FluentLinuxGraphicsDriver` | `launcher.*` | Used everywhere in examples. |
| `FluentVersion` | `utils.fluent_version` | Used everywhere. |
| `examples.download_file` | `examples` subpackage | Used everywhere. |
| `config` (+ `PyFluentDeprecationWarning`, `PyFluentUserWarning`, other warnings/exceptions) | `module_config`, `pyfluent_warnings`, `exceptions` | `config` used constantly; warnings/exceptions rarely referenced directly. |
| `FileSession` | `file_session` | Offline usage. |
| `SolverEvent`, `MeshingEvent` | `streaming_services.events_streaming` | Event registration examples. |
| `SurfaceFieldDataRequest`, `ScalarFieldDataRequest`, `VectorFieldDataRequest`, `PathlinesFieldDataRequest`, `SolutionVariableInfo`, `SolutionVariableData` | `fields.field_data_interfaces` + services | Field-data requests. |
| `search` | `search` | Interactive helper. |
| `BaseSession as Fluent`, `MeshingSession`, `PureMeshingSession`, `SolverSession`, `SolverIcingSession`, `SolverLiteSession` | `session*` | Type references only — rarely instantiated directly. |
| `setup_for_fluent` | `utils.setup_for_fluent` | Occasional. |
Everything else in `__init__.py` (`batch_ops`, `parametric`, `session_utilities.*`, most of `utils.*`, `flobject.ExposureLevel`) is either an implementation detail, legacy, or has been incidentally re-exported.
## 2. Judgments per issue item
- **`error_message`, `utils`, `rpvars`, `workflow_new`, `flicing`, `flobject`, `api_upgrade`, `interceptors`, `health_check`, `batch_ops`, `monitor`, `scheme_eval`, `transcript`, `streaming`, `services/*` (gRPC wrappers)** — implementation. Remove from the public tree entirely (or bury under a single `internals`/`legacy` node not linked from the top).
- **`parametric`** — misleading name; local-study only. Move to `legacy` and/or rename to `local_parametric_study`.
- **`filereader`** → split, and rename the package to `file_reader` (module rename) or expose `case_file`/`data_file` directly with no parent grouping visible.
- **`pyfluent_warnings`** → merge into `exceptions`.
- **`field_data_interfaces`** → not a top-level entity; its classes should live alongside `LiveFieldData` under a single `fields` public module (`FieldData`, `FieldBatch`, request types, `SolutionVariableData`). Fix the `Batch`/`FieldBatch` inversion: rename `Batch` → e.g. `LiveFieldBatch` (a specialisation), keeping `FieldBatch` as the base.
- **`services`** node → delete. Promote user-facing pieces (`FieldData`, `SolutionVariableData`, `Events`, `Reduction`, `SchemeEval`, `TextInterface`) into topical groups (`fields`, `events`, `solver_extras`). Everything else stays internal.
- **`session_*` explosion** → collapse into a single `session` node with children: `MeshingSession`, `PureMeshingSession`, `SolverSession`, `SolverLiteSession`, `SolverIcingSession`, `FileSession`. Remove `session_utilities` from the top; if any of its symbols are truly public, promote them individually.
- **Solver `workflow` / `solver_workflow`** → hide (not directly instantiated). Keep only as linked reference material from the specific task classes, clearly labelled "not directly callable".
- **`tui`** node → rename display to `TUI`. Keep, but bury under `solver` and `meshing`.
- **`datamodel_se` / `datamodel_tui`** → rename to `datamodel` (SE is an implementation detail) and `TUI`.
- **Stop sentence-casing.** Render raw module names in the toctree so contents == import path.
## 3. Proposed public tree (rooted at `ansys.fluent.core`)
```
ansys.fluent.core
├── launcher (launch_fluent, connect_to_fluent, FluentMode,
│ Dimension, Precision, UIMode, graphics-driver enums)
├── config (config object + PyFluent* config classes)
├── session ← single grouping node (progressive disclosure)
│ ├── MeshingSession
│ ├── PureMeshingSession
│ ├── SolverSession
│ ├── SolverLiteSession
│ ├── SolverIcingSession
│ └── FileSession
├── meshing
│ ├── workflow (watertight, fault_tolerant, 2d, part_management…)
│ ├── datamodel (was datamodel_se)
│ └── TUI (was tui)
├── solver
│ ├── settings (autogenerated — untouched)
│ ├── TUI
│ └── preferences
├── fields (unified: field data + solution variables)
│ ├── FieldData / LiveFieldData
│ ├── FieldBatch, LiveFieldBatch (rename fixes the generalisation issue)
│ ├── SurfaceFieldDataRequest, ScalarFieldDataRequest,
│ │ VectorFieldDataRequest, PathlinesFieldDataRequest
│ ├── SolutionVariableData, SolutionVariableInfo
│ └── reduction
├── events (SolverEvent, MeshingEvent, EventsManager,
│ streaming variants collapsed here)
├── monitors (MonitorsManager + streaming)
├── transcript (Transcript + streaming — if kept public)
├── search
├── examples (download_file, path)
├── exceptions (all PyFluent* warnings + exceptions merged)
├── file_transfer (ContainerFileTransferStrategy, RemoteFileTransferStrategy)
├── version (FluentVersion, version_info)
└── legacy
├── parametric (local-study)
├── rpvars
├── scheme_eval
├── solver_workflow ("not directly callable" note)
└── deprecated_apis
```
Removed from the public API entirely (kept as private, `_`-prefixed, or documented as internal): `batch_ops`, `api_upgrade`, `interceptors`, `health_check`, `error_message`, `flobject` (except `ExposureLevel` if truly needed → move to `solver.settings`), `flicing` (rename to `icing` and move under `solver`), `journaling` internals, `fluent_connection`, `data_model_cache`, `docker/*`, `scheduler/*`, `launcher/*` internals (`pim_launcher`, `slurm_launcher`, `standalone_launcher`, `container_launcher`, `watchdog`, `error_handler`, `launcher_utils`, `process_launch_string`), `streaming_services/*` (folded into topical `events`, `monitors`, `transcript`, `fields`), all of `utils/*` except what is promoted (`FluentVersion`, `setup_for_fluent`).
## 4. Concrete action list
1. **Stop the sentence-case transform** in `doc/api_rstgen.py` / `doc_utils.get_display_name` — emit raw module names.
2. **Add `__all__`** to every module intended to be public; remove star-imports of implementation modules from `src/ansys/fluent/core/__init__.py` (drop `batch_ops`, `parametric`, `session_utilities`, `utils.*`, `ExposureLevel`, `events_streaming_v1`).
3. **Introduce grouping packages** (`session/`, `fields/`, `events/`, `legacy/`) that re-export the curated classes via their own `__all__`.
4. **Rename for correctness**:
- `Batch` → `LiveFieldBatch` (specialisation of `FieldBatch`).
- `flicing` → `icing` (under `solver`).
- Display labels only: `tui` → `TUI`, `datamodel_se` → `datamodel`, `api_upgrade` removed from the public tree.
5. **Move**: `rpvars`, `parametric`, `solver_workflow`, deprecated APIs → `legacy/`.
6. **Hide**: `services/*` gRPC wrappers, `streaming_services/*`, `fluent_connection`, `data_model_cache`, `journaling`, `logger`, `module_config` (expose only `config`), `workflow_new`, `error_message`.
7. **Merge** `pyfluent_warnings` into `exceptions`.
8. **Annotate** return types on all promoted methods (start with `LiveFieldData.new_batch() -> LiveFieldBatch`) so cross-links in the API reference resolve.
9. **Clearly label** `legacy.solver_workflow` in its module docstring as "reference-only; not directly callable".
This gives a one-to-one mapping between the raw module tree and the API reference contents, cures the "gobbledygook", brings key APIs (fields, events, sessions) to the top, and buries the service/implementation layer.
# Initial analysis
## Exposure
### No purpose in the public API
- **Error message**.
- **Utils**.
### Not needed in top-level contents
- **PyFluent warnings**. OK if other items hyperlink to them but too insignificant to sit at the top. Can bury them inside **Exceptions**.
- **Rpvars**. Move to **Legacy** section.
- **Workflow**. This object appears in the top-level contents. I suppose it has been left here inadvertently.
### Not working in top-level contents
- **Field data interfaces**. This appears **at the top** but it just contains a bunch of request types **without any usage context**. This is a prime **example of how the API reference is failing**. See **Buried key APIs** below for more on this.
### Buried key APIs
- **Services** groups together and essentially demotes a broad range of key APIs. Additionally, a lot of classes document only how they are implemented ("wraps some gRPC thing") rather than what they offer to users. Given that, it's impossible to tell which classes are actually user-facing and which (if any) are just part of some deeper implementation layer. Amongst many others, there is **LiveFieldData**. This fails to integrate whatsoever with the more prominent **Field data interfaces** documentation. For instance, `LiveFieldData.new_batch()` has **no return type hint**. It actually returns `Batch`. `Batch` inherits from `FieldBatch` which is in `field_data_interfaces`. Hence the link is broken and user never get to see the full picture. In fact, I can't find any docuemntation for either of these classes. **N.b**; Inheritance is **always a specialisation**. In this case though, we have `Batch` inheriting from `FieldBatch` - **a generalisation**!. This back to front naming is especially important for user-facing APIs - we must get these basics right. This paragraph talks a lot about field data, but that's just to provide one example, although it clearly has severe issues.
### Not meant to be exposed as directly callable
- **Solver workflows/Solver workflow** exposes commands that were not validated for direct use. **As such it should be made clear that they are not directly usable**. I suppose that these are indirectly useful for documenting how to use specific workflow task instances. I don't think they ever get instantiated in the client.
## Wording
### Not a word, so re-word or spilt up
- **Filereader**.
- **Flicing**.
### Awkward or non-natural language: re-word
- **Session base meshing** etc. This is back to front. Either invert, add punctuation, or have a single **Session** item in the tree. As it stands we even have **Session utilities** there as well that just repeats the other session types internally. I propose to have a single **Session** node in the contents that opens to each of the other items. Even **File session** could live here.
### Abbreviations not properly capitalised
- **Tui** -> **TUI**.
- Datamodel **se**.
- Datamodel **tui**.
- **Api** upgrade.
### Inaccurate naming
- **Parametric** is specific to _local_ studies (and was previously a separate package). Given that parametric is properly exposed in the settings API now, this name is misleading.
## Corollary (the important bit)
- **Wording**: The API Reference contents are anchored at `ansys.fluent.core`. What follows is pseudo-natural language (i.e. gobbledygook), but the wording is all autogenerated from the exposed module names. Unless the module names themselves are all beautifully named (they are definitely not) then this is not an option.
- **Module structure**: The above issue should be addressed fundamentally at the level of the PyFluent module structure so that both that AND the API reference are fixed simultaneously. Proposing a solid, properly named public module structure is a crucial next step here. What we have is very far from acceptable and that's what makes the API reference almost completely unusable.
- **Public API exposure and annotation** is incomplete, making many modules completely unapproachable via the API reference. Things are not visible and not visibly interconnected.
## Update
- Looking at the dev docs, things like field data are now brought to the top, but this doc is still incomplete - as noted above. Also, the underlying service layer peretuates in te API reference, which is an unnecessary distraction.
- Especially given improvements as noted above, which need to continue, and the fact that the contents list is **NOT** a list of topics, but a list of modules, we **MUST** stop transforming those module names. We must just show the needed modules - in their raw format.
Contributor guide
Assessment
This issue has not been assessed yet.