statica-reporter 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- statica_reporter-0.1.0/.github/workflows/ci.yml +56 -0
- statica_reporter-0.1.0/.github/workflows/release.yml +105 -0
- statica_reporter-0.1.0/.gitignore +43 -0
- statica_reporter-0.1.0/.python-version +1 -0
- statica_reporter-0.1.0/PKG-INFO +338 -0
- statica_reporter-0.1.0/README.md +325 -0
- statica_reporter-0.1.0/docs/superpowers/specs/2026-06-15-statica-reporter-tui-design.md +209 -0
- statica_reporter-0.1.0/docs/superpowers/specs/2026-06-15-statica-reporter-tui-plan.md +70 -0
- statica_reporter-0.1.0/docs/superpowers/specs/2026-06-16-white-label-docx-merge-design.md +251 -0
- statica_reporter-0.1.0/pyproject.toml +34 -0
- statica_reporter-0.1.0/scripts/build_template.py +24 -0
- statica_reporter-0.1.0/statica_reporter/__init__.py +0 -0
- statica_reporter-0.1.0/statica_reporter/cli.py +96 -0
- statica_reporter-0.1.0/statica_reporter/core/__init__.py +0 -0
- statica_reporter-0.1.0/statica_reporter/core/analysis.py +53 -0
- statica_reporter-0.1.0/statica_reporter/core/bound_report.py +79 -0
- statica_reporter-0.1.0/statica_reporter/core/checks.py +67 -0
- statica_reporter-0.1.0/statica_reporter/core/client.py +266 -0
- statica_reporter-0.1.0/statica_reporter/core/default_template.py +85 -0
- statica_reporter-0.1.0/statica_reporter/core/docx_merge.py +347 -0
- statica_reporter-0.1.0/statica_reporter/core/exports.py +257 -0
- statica_reporter-0.1.0/statica_reporter/core/models.py +105 -0
- statica_reporter-0.1.0/statica_reporter/core/rendering.py +173 -0
- statica_reporter-0.1.0/statica_reporter/core/service.py +110 -0
- statica_reporter-0.1.0/statica_reporter/core/summary_docx.py +152 -0
- statica_reporter-0.1.0/statica_reporter/core/units.py +49 -0
- statica_reporter-0.1.0/statica_reporter/tui/__init__.py +0 -0
- statica_reporter-0.1.0/statica_reporter/tui/app.py +182 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/__init__.py +0 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/browse.py +223 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/export_config.py +128 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/path_prompt.py +80 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/progress.py +72 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/prompt.py +92 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/report_builder.py +130 -0
- statica_reporter-0.1.0/statica_reporter/tui/screens/service_setup.py +85 -0
- statica_reporter-0.1.0/statica_reporter/tui/state.py +80 -0
- statica_reporter-0.1.0/statica_reporter/tui/widgets/__init__.py +0 -0
- statica_reporter-0.1.0/statica_reporter/tui/widgets/detail_pane.py +77 -0
- statica_reporter-0.1.0/statica_reporter/tui/widgets/project_tree.py +78 -0
- statica_reporter-0.1.0/statica_reporter/tui/widgets/selection_list.py +31 -0
- statica_reporter-0.1.0/statica_reporter/tui/workspace_actions.py +28 -0
- statica_reporter-0.1.0/statica_reporter/workspace.py +117 -0
- statica_reporter-0.1.0/tests/__init__.py +0 -0
- statica_reporter-0.1.0/tests/test_bound_report.py +156 -0
- statica_reporter-0.1.0/tests/test_exports.py +103 -0
- statica_reporter-0.1.0/tests/test_summary_docx.py +45 -0
- statica_reporter-0.1.0/tests/test_tui_smoke.py +50 -0
- statica_reporter-0.1.0/tests/test_units_checks.py +93 -0
- statica_reporter-0.1.0/tests/test_workspace.py +43 -0
- statica_reporter-0.1.0/uv.lock +1137 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
# Cancel superseded runs on the same ref.
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint:
|
|
16
|
+
name: Lint (ruff)
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v5
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Ruff lint
|
|
27
|
+
run: uvx ruff check --output-format=github .
|
|
28
|
+
|
|
29
|
+
- name: Ruff format check
|
|
30
|
+
run: uvx ruff format --check .
|
|
31
|
+
|
|
32
|
+
build:
|
|
33
|
+
name: Build distribution
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
with:
|
|
38
|
+
# Full history + tags so hatch-vcs can resolve a version.
|
|
39
|
+
fetch-depth: 0
|
|
40
|
+
|
|
41
|
+
- name: Install uv
|
|
42
|
+
uses: astral-sh/setup-uv@v5
|
|
43
|
+
with:
|
|
44
|
+
enable-cache: true
|
|
45
|
+
|
|
46
|
+
- name: Build sdist and wheel
|
|
47
|
+
run: uv build
|
|
48
|
+
|
|
49
|
+
- name: Check metadata
|
|
50
|
+
run: uvx twine check dist/*
|
|
51
|
+
|
|
52
|
+
- name: Upload build artifacts
|
|
53
|
+
uses: actions/upload-artifact@v4
|
|
54
|
+
with:
|
|
55
|
+
name: dist
|
|
56
|
+
path: dist/
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publish to PyPI when a version tag is pushed (e.g. `v1.2.3`).
|
|
4
|
+
# The version is derived from the tag by hatch-vcs, so the tag is the single
|
|
5
|
+
# source of truth — no version bump commit is needed.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
tags:
|
|
9
|
+
- "v*"
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
name: Lint (ruff)
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v5
|
|
20
|
+
with:
|
|
21
|
+
enable-cache: true
|
|
22
|
+
|
|
23
|
+
- name: Ruff lint
|
|
24
|
+
run: uvx ruff check --output-format=github .
|
|
25
|
+
|
|
26
|
+
- name: Ruff format check
|
|
27
|
+
run: uvx ruff format --check .
|
|
28
|
+
|
|
29
|
+
build:
|
|
30
|
+
name: Build distribution
|
|
31
|
+
needs: lint
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
with:
|
|
36
|
+
# Full history + tags so hatch-vcs resolves the version from the tag.
|
|
37
|
+
fetch-depth: 0
|
|
38
|
+
|
|
39
|
+
- name: Install uv
|
|
40
|
+
uses: astral-sh/setup-uv@v5
|
|
41
|
+
with:
|
|
42
|
+
enable-cache: true
|
|
43
|
+
|
|
44
|
+
- name: Build sdist and wheel
|
|
45
|
+
run: uv build
|
|
46
|
+
|
|
47
|
+
- name: Verify the built version matches the tag
|
|
48
|
+
run: |
|
|
49
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
50
|
+
built=$(ls dist/*.whl | sed -E 's/.*statica_reporter-([^-]+)-.*/\1/')
|
|
51
|
+
echo "tag=$tag built=$built"
|
|
52
|
+
if [ "$tag" != "$built" ]; then
|
|
53
|
+
echo "::error::Built version '$built' does not match tag '$tag'." \
|
|
54
|
+
"Is the tag on a clean commit?"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
- name: Check metadata
|
|
59
|
+
run: uvx twine check dist/*
|
|
60
|
+
|
|
61
|
+
- name: Upload build artifacts
|
|
62
|
+
uses: actions/upload-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: dist
|
|
65
|
+
path: dist/
|
|
66
|
+
|
|
67
|
+
publish:
|
|
68
|
+
name: Publish to PyPI
|
|
69
|
+
needs: build
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
# Must match the trusted publisher configured on PyPI.
|
|
72
|
+
environment:
|
|
73
|
+
name: pypi
|
|
74
|
+
url: https://pypi.org/p/statica-reporter
|
|
75
|
+
permissions:
|
|
76
|
+
# Required for Trusted Publishing (OIDC) — no API token needed.
|
|
77
|
+
id-token: write
|
|
78
|
+
steps:
|
|
79
|
+
- name: Download build artifacts
|
|
80
|
+
uses: actions/download-artifact@v4
|
|
81
|
+
with:
|
|
82
|
+
name: dist
|
|
83
|
+
path: dist/
|
|
84
|
+
|
|
85
|
+
- name: Publish to PyPI
|
|
86
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
87
|
+
|
|
88
|
+
github-release:
|
|
89
|
+
name: Create GitHub release
|
|
90
|
+
needs: publish
|
|
91
|
+
runs-on: ubuntu-latest
|
|
92
|
+
permissions:
|
|
93
|
+
contents: write
|
|
94
|
+
steps:
|
|
95
|
+
- name: Download build artifacts
|
|
96
|
+
uses: actions/download-artifact@v4
|
|
97
|
+
with:
|
|
98
|
+
name: dist
|
|
99
|
+
path: dist/
|
|
100
|
+
|
|
101
|
+
- name: Create release
|
|
102
|
+
uses: softprops/action-gh-release@v2
|
|
103
|
+
with:
|
|
104
|
+
generate_release_notes: true
|
|
105
|
+
files: dist/*
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
|
|
5
|
+
# Virtual environments
|
|
6
|
+
.venv/
|
|
7
|
+
venv/
|
|
8
|
+
env/
|
|
9
|
+
ENV/
|
|
10
|
+
|
|
11
|
+
# Packaging
|
|
12
|
+
build/
|
|
13
|
+
dist/
|
|
14
|
+
*.egg-info/
|
|
15
|
+
.eggs/
|
|
16
|
+
|
|
17
|
+
# Tool caches
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
.coverage.*
|
|
23
|
+
htmlcov/
|
|
24
|
+
|
|
25
|
+
# Environment files
|
|
26
|
+
.env
|
|
27
|
+
.env.*
|
|
28
|
+
|
|
29
|
+
# IDEs and editors
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
|
|
35
|
+
# OS files
|
|
36
|
+
.DS_Store
|
|
37
|
+
Thumbs.db
|
|
38
|
+
|
|
39
|
+
# Project folders
|
|
40
|
+
inputs/
|
|
41
|
+
reports/
|
|
42
|
+
data/
|
|
43
|
+
renders/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: statica-reporter
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: TUI for batch IDEA StatiCa connection reporting and white-label export
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Requires-Dist: ideastatica-connection-api
|
|
7
|
+
Requires-Dist: kaleido>=1.3.0
|
|
8
|
+
Requires-Dist: lxml>=5.0.0
|
|
9
|
+
Requires-Dist: plotly>=6.8.0
|
|
10
|
+
Requires-Dist: python-docx>=1.1.2
|
|
11
|
+
Requires-Dist: textual>=1.0.0
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# statica-reporter
|
|
15
|
+
|
|
16
|
+
A terminal UI (TUI) for batch IDEA StatiCa connection reporting. Browse multiple
|
|
17
|
+
`.ideaCon` projects and their connections in a tree, glance at per-connection
|
|
18
|
+
details, build an ordered report selection, and export in four formats.
|
|
19
|
+
|
|
20
|
+
## Run
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# TUI (interactive)
|
|
24
|
+
uvx --from . statica-reporter # before publishing
|
|
25
|
+
# uvx statica-reporter # once published to PyPI
|
|
26
|
+
|
|
27
|
+
# Headless batch (preserves the original main.py workflow)
|
|
28
|
+
uvx --from . statica-reporter-batch --input-dir inputs --output-dir out --json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Requires a running IDEA StatiCa Connection REST service. The TUI attaches to one
|
|
32
|
+
at `http://localhost:5000` by default; if none is reachable it offers to start a
|
|
33
|
+
detected local installation (or accept a custom URL).
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- **Browse**: tree of projects → connections with status glyphs; lazy two-pane
|
|
38
|
+
detail (status + per-category checks, design forces, geometry counts). Press
|
|
39
|
+
`Enter` to fetch, `c` to run CBFEM analysis.
|
|
40
|
+
- **Report builder**: move connections from an *Available* tree into an ordered
|
|
41
|
+
*Selected* list (`Space`/`Enter` add, `A` add all, `J`/`K` reorder, `d` remove).
|
|
42
|
+
- **Export** (combined by default, optional split-per-connection):
|
|
43
|
+
1. StatiCa **PDF** (native multi-connection report, grouped per project)
|
|
44
|
+
2. Connection **summary docx** (one table: ID, isometric view, forces, checks)
|
|
45
|
+
3. **JSON** data dump (raw results)
|
|
46
|
+
4. **Bound white-label docx** — all selected reports concatenated and run through
|
|
47
|
+
Pandoc with a blank reference document, so headings/tables map to stock Word
|
|
48
|
+
styles and inherit a company template on paste (with TOC + bookmarks).
|
|
49
|
+
- **Workspaces**: save/open named workspaces (added projects, selection, output
|
|
50
|
+
dir, export prefs) under `%APPDATA%/statica-reporter/workspaces`.
|
|
51
|
+
|
|
52
|
+
## Architecture
|
|
53
|
+
|
|
54
|
+
- `statica_reporter/core/` — UI-free engine (service, client, analysis, exports,
|
|
55
|
+
rendering, summary_docx, bound_report). Fully unit-tested without a live service.
|
|
56
|
+
- `statica_reporter/tui/` — Textual app, screens, widgets.
|
|
57
|
+
- `statica_reporter/cli.py` — headless batch entry point.
|
|
58
|
+
- `statica_reporter/workspace.py` — named workspace persistence.
|
|
59
|
+
|
|
60
|
+
Run the tests with `uv run pytest`.
|
|
61
|
+
|
|
62
|
+
> The legacy root-level `main.py` and `report_generator.py` are superseded by the
|
|
63
|
+
> package (migrated into `core/`); they remain only for reference and can be removed.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## IDEA StatiCa Connection API — Developer Reference
|
|
68
|
+
|
|
69
|
+
This document captures everything learned from working against the live API (server v26.0.1.2450, Python client v26.0.0.3314) so future development doesn't have to rediscover it.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Setup
|
|
74
|
+
|
|
75
|
+
### Install the client
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv add ideastatica-connection-api
|
|
79
|
+
# or: pip install ideastatica-connection-api
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Prerequisites
|
|
83
|
+
|
|
84
|
+
The API requires a running IDEA StatiCa REST service. In this project the server is already running at `http://localhost:5000`. Docs for the running instance are available at `http://localhost:5000/api`.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Connecting
|
|
89
|
+
|
|
90
|
+
Use `ConnectionApiServiceAttacher` as a context manager. It handles session lifecycle automatically (client registration and cleanup on exit).
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import ideastatica_connection_api.connection_api_service_attacher as connection_api_service_attacher
|
|
94
|
+
|
|
95
|
+
BASE_URL = "http://localhost:5000"
|
|
96
|
+
|
|
97
|
+
with connection_api_service_attacher.ConnectionApiServiceAttacher(BASE_URL).create_api_client() as api_client:
|
|
98
|
+
# all work happens here
|
|
99
|
+
pass
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The `api_client` object exposes every API group as an attribute:
|
|
103
|
+
|
|
104
|
+
| Attribute | Purpose |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `api_client.project` | Open, close, query projects |
|
|
107
|
+
| `api_client.connection` | Query and modify connections |
|
|
108
|
+
| `api_client.calculation` | Run analysis, fetch results |
|
|
109
|
+
| `api_client.report` | Export PDF / Word / HTML |
|
|
110
|
+
| `api_client.load_effect` | Manage load cases |
|
|
111
|
+
| `api_client.material` | Steel, bolt, weld, concrete materials |
|
|
112
|
+
| `api_client.member` | Connection members |
|
|
113
|
+
| `api_client.operation` | Connection operations (welds, bolts, etc.) |
|
|
114
|
+
| `api_client.parameter` | Parametric values |
|
|
115
|
+
| `api_client.template` | Connection templates |
|
|
116
|
+
| `api_client.settings` | Project settings |
|
|
117
|
+
| `api_client.export` | IOM / IFC export |
|
|
118
|
+
| `api_client.presentation` | 3D scene data |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Core workflow
|
|
123
|
+
|
|
124
|
+
### 1. Open a project
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
api_client.project.open_project_from_filepath(r"C:\path\to\file.ideaCon")
|
|
128
|
+
project_id = api_client.project.active_project_id # str UUID, set automatically
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 2. List connections
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
project_data = api_client.project.get_project_data(project_id)
|
|
135
|
+
# project_data.connections -> list of ConConnection
|
|
136
|
+
for conn in project_data.connections:
|
|
137
|
+
print(conn.id, conn.name) # id is an int
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 3. Check if a connection is already analyzed
|
|
141
|
+
|
|
142
|
+
There is no explicit "status" field. Check by calling `get_results` and inspecting `check_res_summary`:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
results = api_client.calculation.get_results(project_id, [conn_id])
|
|
146
|
+
already_analyzed = (
|
|
147
|
+
results
|
|
148
|
+
and results[0]
|
|
149
|
+
and results[0].check_res_summary is not None
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`ConnectionCheckRes` fields: `check_res_summary`, `check_res_plate`, `check_res_weld`, `check_res_bolt`, `check_res_anchor`, `check_res_concrete_block`, `buckling_results`, `name`, `connection_id`, `id`, `messages`.
|
|
154
|
+
|
|
155
|
+
### 4. Run analysis
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
summaries = api_client.calculation.calculate(project_id, [conn_id])
|
|
159
|
+
# returns List[ConResultSummary]
|
|
160
|
+
# ConResultSummary fields: id, passed, result_summary
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`calculate` accepts a plain `List[int]` of connection IDs — pass multiple IDs to batch.
|
|
164
|
+
|
|
165
|
+
> **Note:** The official documentation shows a `ConCalculationParameter` object, but this class does not exist in the installed Python client. Pass a plain list directly.
|
|
166
|
+
|
|
167
|
+
### 5. Fetch raw JSON results
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
raw_list = api_client.calculation.get_raw_json_results(project_id, [conn_id])
|
|
171
|
+
# returns List[str], one JSON string per connection ID
|
|
172
|
+
import json
|
|
173
|
+
data = json.loads(raw_list[0])
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Top-level keys in the returned object: `codeType`, `plates`, `platesDeformation`, `bolts`, `welds`, `anchors`, `concreteBlock`, `bucklingResults`, and others depending on connection type.
|
|
177
|
+
|
|
178
|
+
### 6. Fetch structured results
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
results = api_client.calculation.get_results(project_id, [conn_id])
|
|
182
|
+
# returns List[ConnectionCheckRes]
|
|
183
|
+
summary = results[0].check_res_summary # ConResultSummary
|
|
184
|
+
plates = results[0].check_res_plate # list of CheckResPlate
|
|
185
|
+
welds = results[0].check_res_weld # list of CheckResWeld
|
|
186
|
+
bolts = results[0].check_res_bolt # list of CheckResBolt
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 7. Export reports
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
# PDF — returns bytes, write manually
|
|
193
|
+
pdf_bytes = api_client.report.generate_pdf(project_id, conn_id) # conn_id is int
|
|
194
|
+
with open("report.pdf", "wb") as f:
|
|
195
|
+
f.write(pdf_bytes)
|
|
196
|
+
|
|
197
|
+
# Word
|
|
198
|
+
docx_bytes = api_client.report.generate_word(project_id, conn_id)
|
|
199
|
+
|
|
200
|
+
# HTML zip
|
|
201
|
+
zip_bytes = api_client.report.generate_html_zip(project_id, conn_id)
|
|
202
|
+
|
|
203
|
+
# Batch PDF (all connections at once)
|
|
204
|
+
# Note: "mutliple" is a typo in the API itself — use it exactly as shown
|
|
205
|
+
pdf_bytes = api_client.report.generate_pdf_for_mutliple(project_id, [conn_id_1, conn_id_2])
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
> **Note:** The return type annotation says `None` for `generate_pdf` — this is wrong. It returns `bytes`.
|
|
209
|
+
|
|
210
|
+
### 8. Close the project
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
api_client.project.close_project(project_id)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Always close when done. Unclosed projects remain in the server's memory.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Units
|
|
221
|
+
|
|
222
|
+
The API **never returns unit labels**. There are no unit-related classes, settings, or fields anywhere in the package. All raw numeric values are in **SI units**, regardless of the project's design code (American, Eurocode, etc.):
|
|
223
|
+
|
|
224
|
+
| Quantity | Unit |
|
|
225
|
+
| --- | --- |
|
|
226
|
+
| Length / dimension | m |
|
|
227
|
+
| Stress / pressure / strength | Pa |
|
|
228
|
+
| Force | N |
|
|
229
|
+
| Moment | N·m |
|
|
230
|
+
|
|
231
|
+
Example cross-check from a real result (`codeType: "american"`, material A992):
|
|
232
|
+
|
|
233
|
+
- `thickness: 0.04` → 40 mm plate ✓
|
|
234
|
+
- `materialFy: 344_740_000` → 344.7 MPa ≈ 50 ksi ✓
|
|
235
|
+
- `materialModulusOfElasticity: 200_000_000_000` → 200 GPa ✓
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Settings
|
|
240
|
+
|
|
241
|
+
`get_settings` returns a flat `Dict[str, object]` keyed by slash-separated paths:
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
settings = api_client.settings.get_settings(project_id)
|
|
245
|
+
# e.g. settings["calculationCommon/Checks/Shared/LimitPlasticStrain"] -> 0.05
|
|
246
|
+
|
|
247
|
+
# Search by keyword
|
|
248
|
+
settings = api_client.settings.get_settings(project_id, search="mesh")
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Update a setting:
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
api_client.settings.update_settings(project_id, {
|
|
255
|
+
"calculationCommon/Checks/Shared/LimitPlasticStrain": 0.03
|
|
256
|
+
})
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Other useful APIs
|
|
262
|
+
|
|
263
|
+
### Load effects
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
load_effects = api_client.load_effect.get_load_effects(project_id, conn_id)
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Materials
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
steels = api_client.material.get_steel_materials(project_id)
|
|
273
|
+
bolts = api_client.material.get_bolt_grade_materials(project_id)
|
|
274
|
+
sections = api_client.material.get_cross_sections(project_id)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Export to IOM/IFC
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
iom_xml = api_client.export.export_iom(project_id, conn_id)
|
|
281
|
+
ifc_data = api_client.export.export_ifc(project_id, conn_id)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 3D scene data
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
scene_json = api_client.presentation.get_data_scene3_d_text(project_id, conn_id)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Complete working example
|
|
293
|
+
|
|
294
|
+
This is the pattern used in `main.py`:
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
import glob, json, os
|
|
298
|
+
import ideastatica_connection_api.connection_api_service_attacher as connection_api_service_attacher
|
|
299
|
+
|
|
300
|
+
BASE_URL = "http://localhost:5000"
|
|
301
|
+
|
|
302
|
+
with connection_api_service_attacher.ConnectionApiServiceAttacher(BASE_URL).create_api_client() as api_client:
|
|
303
|
+
api_client.project.open_project_from_filepath(r"inputs\myfile.ideaCon")
|
|
304
|
+
project_id = api_client.project.active_project_id
|
|
305
|
+
|
|
306
|
+
project_data = api_client.project.get_project_data(project_id)
|
|
307
|
+
|
|
308
|
+
for conn in project_data.connections:
|
|
309
|
+
conn_id = conn.id # int
|
|
310
|
+
|
|
311
|
+
# Skip calculation if already done
|
|
312
|
+
results = api_client.calculation.get_results(project_id, [conn_id])
|
|
313
|
+
if not (results and results[0] and results[0].check_res_summary is not None):
|
|
314
|
+
api_client.calculation.calculate(project_id, [conn_id])
|
|
315
|
+
|
|
316
|
+
# PDF report
|
|
317
|
+
pdf_bytes = api_client.report.generate_pdf(project_id, conn_id)
|
|
318
|
+
with open(f"reports/{conn.name}.pdf", "wb") as f:
|
|
319
|
+
f.write(pdf_bytes)
|
|
320
|
+
|
|
321
|
+
# Raw JSON data
|
|
322
|
+
raw = api_client.calculation.get_raw_json_results(project_id, [conn_id])
|
|
323
|
+
parsed = json.loads(raw[0])
|
|
324
|
+
with open(f"data/{conn.name}.json", "w") as f:
|
|
325
|
+
json.dump(parsed, f, indent=2)
|
|
326
|
+
|
|
327
|
+
api_client.project.close_project(project_id)
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Gotchas
|
|
333
|
+
|
|
334
|
+
- **`ConCalculationParameter` does not exist** in the installed client. Pass `List[int]` directly to `calculate` and `get_raw_json_results`.
|
|
335
|
+
- **`generate_pdf` return type is annotated as `None`** but actually returns `bytes`. Open the file in `"wb"` mode.
|
|
336
|
+
- **All values are SI** — convert to display units in your own layer if needed.
|
|
337
|
+
- **Always close projects** — the server holds them in memory until explicitly closed or the session ends.
|
|
338
|
+
- **`active_project_id` is set automatically** after `open_project_from_filepath`. You do not need to parse the return value.
|