Skip to content

Releases: Dennis5882/MIDAS-API-NX-SDK

v0.14.0

Choose a tag to compare

@Dennis5882 Dennis5882 released this 26 Jul 08:15

Two releases' worth of work, published together. Read the breaking changes
first — one of them was destroying data.

⚠️ Breaking

DbResource.delete() was deleting the entire table

Node.delete([101]) removed every node, not node 101 — and with them every
element attached to those nodes. One call could empty a model. It has behaved
this way since the first commit, through 11 releases, and no mocked test could
have caught it: the request shape was exactly what the manual documents.

The manual's ID-keyed DELETE {endpoint} body is ignored by the server. The
undocumented per-id URL, DELETE {endpoint}/{id}, removes exactly one record.
delete() now uses it, issuing one request per id.

  • Return type changed: {id: response} instead of a single response body.
  • Deleting an id that doesn't exist is a harmless no-op, so no need to check first.
  • The old whole-table behaviour is still available, deliberately named:
    DbResource.delete_all().

If you have code that called delete() expecting a single record to go, it was
doing something much worse than you thought — and it needs no change now beyond
the return value.

Hyper-S (-M1) endpoints are Civil NX only

Hyper-S is the solver MIDASIT introduced with Civil NX. The SDK offered all 21
-M1 endpoints to Gen clients as well, where the best possible outcome was a
404 for the caller to interpret. Live testing: 13/13 implemented endpoints
answer under Civil NX 2026 and 404 under Gen NX 2026, as do all 8 unimplemented
stubs.

A Gen client now raises ProductMismatchError before issuing the request. Use
the new HYPER_S_ONLY constant in db/base.py — kept separate from
CIVIL_ONLY because Hyper-S is expected to reach Gen NX eventually, and that
day this should be one line to widen.

Fixed

  • doc.analyze() no longer reports a failed solve as success. The solver
    reports failure as {"message": "... Analysis failed."} — the same key a
    success uses for "... command complete", with no error object, so
    v0.12.0's client-level check could not see it. Every result table would
    otherwise come back empty with nothing pointing at the cause.

Added

  • DbResource.delete_all() — empty a table on purpose.
  • HYPER_S_ONLY in db/base.py.
  • scripts/live_readonly_sweep.py — GETs every endpoint the SDK wraps against
    a live session. Read-only, so it is safe against an open model.
  • scripts/live_crud_check.py — create → read → update → delete round trips,
    verifying the server echoes back what was written. This is what found the
    delete() bug.

Verification

Live-verified endpoints went from 10/390 to 295/390, across both products,
recorded per endpoint in docs/coverage.json. Gen and Civil each reproduced
their earlier sweep numbers exactly, on a real 710-node analyzed model rather
than a blank one.

Write paths now have round-trip coverage on 10 resources: Civil 10/10,
Gen 9/9
.

Live-server behaviour worth knowing

All of this is new in docs/live_verification_notes.md:

  • Every path in this API resolves on the machine running NX, which is often
    not the machine running your code. EXPORT_PATH, /doc/SAVEAS, /doc/OPEN,
    report and image paths all go there. A path that doesn't exist on that machine
    raises a modal dialog there and blocks the session, while the HTTP call
    still answers command complete. Build paths from
    verify_connection()["user"]; verify a write with /doc/OPEN, never
    os.path.exists().
  • /db/CONS's CONSTRAINT must be 7 characters. Six is rejected; eight is
    silently truncated to seven, giving you a support you never asked for.
  • /db/STLD ignores the "Assign" key and renumbers sequentially, while
    /db/NODE honours it. Code that writes a record and reads it back by the key
    it sent will miss for load cases.
  • Error bodies arrive under 201 as well as 200.
  • /doc/NEW and the *-ANAL design checks can kill the application, with a
    licence dialog that holds the licence until the process is restarted properly.
    Seven hypotheses were tested and eliminated — including reopening the exact
    model that crashed — so there is no precondition to check. Don't point them at
    a session holding work that isn't saved.

Compatibility

Python 3.9+, requests only. 637 tests, no live server needed.

v0.12.0

Choose a tag to compare

@Dennis5882 Dennis5882 released this 26 Jul 06:18

Fixed

  • HTTP 200 with an {"error": ...} body is no longer reported as success.
    Story tables requested before the story calculation has run, and design checks
    whose preconditions aren't met, report the refusal under a 2xx status. These now
    raise MidasResultError. Pass MidasClient(raise_on_result_error=False) to get
    the raw body back instead.
  • Non-JSON responses stay inside the SDK's exception hierarchy. A proxy or
    SSL-inspection appliance answering with HTML used to raise a raw
    JSONDecodeError past except MidasAPIError; it now maps to a typed error,
    keeping MidasAuthError for an intercepted 401.
  • DbResource.items() no longer raises AttributeError on empty tables.
    A zero-row response can come back as {"message": ""}; items() returns {}.
  • midas_nx.__version__ matches the installed distribution. It had reported
    0.10.0 since v0.11.0.

Added

  • post.base.unwrap_table() — finds the HEAD/DATA table in a /post/TABLE
    response by shape. The top-level key is not stable across sessions, so indexing
    by TABLE_NAME is unsafe.
  • MidasResultError, exported from midas_nx.

Compatibility

get_table()'s return value is unchanged. The one behaviour change is the
MidasResultError raise described above.

v0.11.2

Choose a tag to compare

@Dennis5882 Dennis5882 released this 25 Jul 14:23

Highlights

  • Clearer project description — the README and the PyPI summary now lead with what the SDK
    does (one package covering both Civil NX and Gen NX, typed against the documented schema)
    instead of opening with how it relates to other packages. Applied to the English, Korean,
    Traditional Chinese, and Simplified Chinese sections alike.
  • STORY_DRIFT_METHOD enum values corrected — v0.11.1 documented
    "Drift on the Center of Mass" (#10) and "Max. Drfit of All Vertical Elements" (#13),
    both transcribed from typos in the official docs. Sending either would be rejected; they are
    now the normalized "Drift at the Center of Mass" / "Max. Drift of All Vertical Elements".
  • Story Drift direction keys — the official docs spell these "X_DIR" in the Specifications
    table but "X-DIR" in the working request example. Both spellings are now declared (hyphen
    first) so neither trips a type-checker, with the fallback order documented.
  • Wall Force read warning — this table repeats its HEAD columns for top/bot, so the usual
    dict(zip(head, row)) idiom silently drops the top values. Slice by position instead
    (row[5:12] / row[12:19]).
  • *-ANAL design-check guidance revisedCC-ANAL/BC-ANAL/WC-ANAL ran clean 4/4 in
    live production use, so the blanket "never call this" rule is lifted. But the clean runs were
    on the same build that hung (Gen NX 2026 v2.1, build 06/23/2026), so this is not a vendor
    fix and the trigger is still unidentified — use a short timeout and read the *-TABLE back
    regardless. WD-ANAL was not re-tested and keeps its warning.

v0.11.1

Choose a tag to compare

@Dennis5882 Dennis5882 released this 25 Jul 07:03

Highlights

  • DCRM-WALL schema fix (breaking) — the per-wall-ID rebar spec moved from a flat object to a
    per-story ITEMS[] array (each item adding a required STORY name). This mirrors an official
    manual change; code written against the old flat shape will be rejected by the live server.
  • Wall Force — a previously-undocumented result table (post.result_1.get_wall_force_table()),
    giving per-story/per-level wall axial/shear/torsion/moment with top/bottom values side by side.
  • Story Table ADDITIONAL parameters — 10 of 17 Story Table types (Story Drift, Shear Force
    Ratio, Overturning Moment, Stability Coefficient, Torsional Irregularity/Amplification,
    Stiffness/Capacity/Weight Irregularity) gained typed support for their table-specific
    ADDITIONAL settings (angle, Beta value, extreme-point node selection, calculation method),
    plus STORY_NAMES/MODES filters where documented.
  • DCRM-BEAM / REBR doc correctionsMAIN_BAR_TOP/MAIN_BAR_BOT/SHEAR_BAR are now marked
    required (were optional), and REBR's rebar NUM documents a minimum of 4.

v0.11.0

Choose a tag to compare

@Dennis5882 Dennis5882 released this 21 Jul 15:53

Highlights

  • DbResource.items() — a convenience alternative to .get() that
    unwraps the response to {id: payload} with int keys, instead of the
    raw {ENDPOINT_KEY: {"1": {...}}} shape.
  • Friendlier error messagesMidasAuthError, MidasConnectionError,
    and MidasNotFoundError now append a (Hint: ...) suggestion pointing
    at the actual fix (MAPI key menu location, checking
    client.verify_connection(), etc.).
  • Getting-started guides for non-developersdocs/ko/quickstart.md,
    docs/en/quickstart.md, docs/zh-tw/quickstart.md: install Python, get
    a MAPI key, run a first script, in the SDK's three documented languages.
    The first script's material/section values were live-verified against
    real Gen NX and Civil NX sessions.
  • Maintenance tooling (internal, not shipped in the package):
    scripts/check_manual_drift.py + a weekly CI job detect when the
    sibling MIDAS-API manual repo changes and flag affected modules;
    scripts/check_drift.py diffs a live server's schema against this SDK's
    TypedDicts; scripts/gen_endpoint.py scaffolds new endpoint boilerplate
    from a manual chapter; scripts/live_smoke.py runs a real write ->
    analyze -> read round trip against a live session.
  • CI pipeline — push/PR now run pytest + ruff automatically.

No breaking changes; everything above is additive.

v0.10.0

Choose a tag to compare

@Dennis5882 Dennis5882 released this 19 Jul 11:37
chore: bump version to v0.10.0

Minor release: MidasClient.verify_connection() and DbResource.info() are
new backward-compatible functionality (not a bug fix), so this follows
semver as a minor bump rather than another v0.9.x patch (see a31cd52).
Also corrects PLAN.md's release-milestone table, which still listed the
already-published v0.9.1 as "ready to release."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

v0.9.1

Choose a tag to compare

@Dennis5882 Dennis5882 released this 19 Jul 06:28
chore: bump version to v0.9.1

Patch release: sync /ope/GSBG with the manual's 2026-07-14 schema update
(see ae1d89d). No other endpoint affected. Also corrects PLAN.md's
release-milestone table, which still listed the already-published v0.9.0
as "ready to release."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

v0.8.0

Choose a tag to compare

@Dennis5882 Dennis5882 released this 15 Jul 04:33
feat: implement 27_Design_SRC_AIKSRC2K (27/27 endpoints)

Completes Phase 5c and the full documented API surface (390/398 rows,
remaining 8 are undocumented Hyper-S stubs). Adds PUT_DELETE_METHODS
to db/base.py for DSRC's unique PUT/DELETE-only method set.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

v0.7.0

Choose a tag to compare

@Dennis5882 Dennis5882 released this 15 Jul 03:57
fix: address Phase 5b code-review findings

design_forces.py and checks.py were written by two independent
parallel background agents that couldn't see each other's work,
producing three field-for-field-identical TypedDict pairs. Verified
against the manual (WD-ANAL's and WC-ANAL's WALL_IDS/SELECTIONS
schemas are literally identical; BD-REPORT's and BC/CC/BRC-REPORT's
DETAIL_POSITIONS schemas are literally identical) and consolidated:

- design_forces.py's RcWallIdsSelector/RcWallDesignSelection (used by
  WD-*) are now also imported by checks.py (used by WC-*) instead of
  checks.py redeclaring them locally as WallIdsSelector/
  WallCheckSelection.
- design_forces.py's RcBeamDetailPositions, renamed
  RcReportDetailPositions to reflect that it's shared across BD-REPORT
  and BC/CC/BRC-REPORT, is now imported by checks.py instead of
  redeclaring a local RcDetailPositions.

(Note: this review pass was done by direct manual read of all 4 ch26
files rather than the usual parallel finder-agent /code-review, since
the Agent tool hit a session-limit outage mid-run.)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

v0.6.0

Choose a tag to compare

@Dennis5882 Dennis5882 released this 14 Jul 21:50
fix: address Phase 5a code-review findings

- db/design.py: reuse post/base.py's NodeElemsSelector for REBB/REBC/
  REBR's sub-section ELEMS selector instead of a byte-identical local
  SubSectionElems redeclaration.
- Flag two genuine manual-internal inconsistencies with clarifying
  comments (not bugs -- each endpoint's own section was transcribed
  correctly, but the two source documents disagree with each other or
  with themselves): DCO's SEIS_SYS "Buckling-Restrained Braced Frames"
  is hyphenated while SLRS's FRAME_TYPE spells the same seismic system
  without a hyphen; REBW's SUB_WALL_ID is labeled both "read only" and
  "Required" by the manual's own Parameters table, resolved by
  following the worked example (sent as required client input).

BraceMainBarSpec/ColumnMainBarSpec duplication and DREULT's two
single-field wrapper TypedDicts (raised by the same review pass) were
verified against the manual and left unchanged: REBR's manual section
explicitly states its MAIN_BAR is "similar to REBC but without
USE_CORNER/HOOK_TYPE", and DREULT's COMPONENTS/COLUMN_SECTION_SIZE are
genuinely nested single-key objects per the manual's own JSON Schema.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>