Skip to content

About capability parity

Two libraries now answer to one name. That is the point of the unification, and it is also its sharpest risk. Once both are called idfkit, a reader who finds something in Python and not in JavaScript has no way to tell whether they have met a deliberate boundary or a defect, and the reasonable assumption is defect.

The parity ledger removes the guesswork. Every public capability of either library appears on it exactly once, with its availability in both languages, and every absence is described rather than left to be discovered. A written-down absence is documentation. An undocumented one is a bug report waiting to be filed against behaviour that is working as designed.

This page is the reader-facing view of that ledger. Everything below the generated marker comes from governance/parity.toml in the conformance repository, read at the immutable governance tag this release pins, so the page you are reading and the file both libraries' CI gates read cannot disagree. For the vocabulary side of the same governance, which name each concept carries in each language, see the naming map.

Three states, not two

A capability is complete, partial, or absent in each language.

The middle state is the one that earns its keep. A capability that exists in both languages and behaves differently is neither present nor absent, and calling it present is precisely the lie this ledger exists to prevent. Anything recorded as partial carries a description of what differs, because partial with nothing said about it is indistinguishable from complete.

Two kinds of absence

An absence alone tells you almost nothing. What you need to know is whether to wait or to plan around it, so every absent side is recorded as one of two kinds.

  • Not yet. The second language could have this and does not have it today. The entry names the issue tracking the port. Expect this to change.
  • Never. The capability is permanently single-language, and the entry says why. A permanent record is a stronger claim than a temporary one, so moving a capability out of never takes a constitutional amendment rather than an edit to the ledger.

On the page, a temporary gap is an amber notice naming a tracking issue and a permanent one is a plain notice naming a reason. In the table at the top, the same distinction reads as absent (not yet) against absent (never).

One entry per mechanism

Where the two libraries do something recognisably similar by fundamentally different means, that is two capabilities and not one.

Simulation is the case that forces the rule. Python drives a locally installed EnergyPlus through a subprocess; JavaScript runs a WebAssembly build in the browser. Recorded as a single simulation entry, whichever language the entry was written from would make the other read as deficient, and every page describing it would print a gap notice for a capability that is not missing. Visual output splits for the same reason: a static vector image drawn once is not a real-time rendered scene.

So local-simulation and browser-simulation appear separately, as do svg-visualisation and scene-rendering. Neither pair is ever collapsed. When you read one of them as Python-only or JavaScript-only, its partner entry is where the other language's answer lives.

The ids are load-bearing

Each capability's ledger id is a permanent public identifier, and it does three jobs at once. It is the anchor on this page, so a link to #local-simulation keeps resolving. It is the argument the parity() macro takes on every page that describes the capability, which is how availability reaches the point of use instead of living only here. And it is what the gates in both libraries match their exported surface against.

Ids get added and deprecated. They do not get renamed.

Generated from governance/parity.toml at governance-2026.9, the governance tag this release pins. Correct the ledger and regenerate; a correction made on this page would be overwritten, and it would never reach either library's CI gate.

Every capability at a glance

33 capabilities, counted by availability and then listed in full. Follow a capability to read what differs where the two libraries differ, and whether an absence is temporary or permanent.

Availability Python JavaScript
complete 28 12
partial 3 4
absent, not yet 0 13
absent, never 2 4
Capability Tier Python JavaScript
Reading IDF and epJSON 1 complete complete
Writing IDF and epJSON 1 partial partial
Documents, collections, and objects 1 complete complete
Reference graph 1 complete complete
Schema access and the version registry 1 complete complete
Model validation 1 complete complete
Describing an object type from the schema 1 complete partial
Building EnergyPlus documentation URLs 1 complete complete
Static types generated from the schema 1 partial complete
Diagnostics from a parse 1 partial complete
The weather station index 1 complete partial
Retrieving weather and design-day files 1 complete partial
Declaring the conformance level a release passes 1 complete complete
Geocoding a place name 1 complete complete
Formatting-preserving round-trip 2 complete absent (not yet)
Reading geometry from a model 2 complete absent (not yet)
Building and transforming geometry 2 complete absent (not yet)
Intersecting and matching surfaces 2 complete absent (not yet)
Generating zoned blocks from a footprint 2 complete absent (not yet)
Construction thermal properties 2 complete absent (not yet)
Schedule evaluation 2 complete absent (not yet)
Reading the output variable dictionary and selecting variables 2 complete absent (not yet)
Design days and ASHRAE sizing conditions 2 complete absent (not yet)
Forward-migrating a model between EnergyPlus versions 3 complete absent (not yet)
Command-line interface 3 complete absent (not yet)
Checking source against another EnergyPlus version's schema 3 complete absent (not yet)
Plotting simulation results 3 complete absent (not yet)
Running a locally installed EnergyPlus and reading its results permanent complete absent (never)
Running EnergyPlus in the browser permanent absent (never) complete
Rendering a model to a vector image permanent complete absent (never)
Rendering a three-dimensional scene permanent absent (never) complete
eppy compatibility surface permanent complete absent (never)
Caching retrieved weather files on disk permanent complete absent (never)

Tier 1: the shared core

Both libraries carry these, and both are expected to keep carrying them. A difference you meet inside this tier is either stated below or a bug, and there is no third possibility.

Reading IDF and epJSON

Python complete · JavaScript complete · Tier 1 · ledger id parse

Vocabulary this capability owns in the naming register
  • parse IDF from a string
  • parse epJSON from a string
  • read IDF from disk
  • read epJSON from disk
  • the parse error type
  • detect a document version
  • an epJSON document value
  • read IDF from disk, keeping diagnostics
  • detect an epJSON document version

Writing IDF and epJSON

Python partial · JavaScript partial · Tier 1 · ledger id write

What differs, and why

Both libraries write both formats, and every document either one writes is read back by the other and by EnergyPlus. What they do NOT do is produce the same bytes. One model written from Python and from JavaScript gives two files whose object headers match and whose every field line differs, and neither is more correct than the other, so the difference is recorded here rather than resolved by changing a writer both ecosystems have already published.

Measured, not asserted. 5ZoneAirCooled.idf from EnergyPlus 26.1.0, 359 objects, through load_idf/save_idf and through loadIdf/saveIdf, differs in seven ways:

  1. Python opens the file with !-Generator idfkit v<version> and !-Option SortedOrder. TypeScript writes no header.
  2. Python orders objects by type name, alphabetically, with Version pinned first, which is what its SortedOrder header declares. TypeScript groups objects by type in the order the types first appeared in the source, with Version pinned first.
  3. Python indents field lines two spaces. TypeScript indents four, and takes an indent option.
  4. Both align the !- comment at column 30. They therefore overflow at different values, and on overflow Python writes the comment flush against the comma while TypeScript keeps one space.
  5. Python renders a float with %g, so an integral value loses its decimal point: 30. in the source comes back as 30, and 0.0 as 0. TypeScript consults the schema and writes 30.0 and 0.0, because JavaScript has one number type and a real-valued field would otherwise be indistinguishable from an integer one on the way out.
  6. Python title-cases every word of the field-name comment, !- Number Of Vertices and !- View Factor To Ground. TypeScript keeps a list of minor words lowercase so the comment reads as EnergyPlus writes it, !- Number of Vertices and !- View Factor to Ground. Both drop the unit suffix the source carries, {deg} and the rest.
  7. Python numbers the comment on each repeat of an extensible group, !- Vertex X Coordinate 2. TypeScript repeats the unnumbered name on every repeat.

Blank lines differ with them: Python puts one between every pair of objects, TypeScript one between objects of the same type and two at each type boundary. On this file that is 4031 lines against 4125, for the same 359 objects.

partial on BOTH sides, because neither writer's controls contain the other's. Python's write_idf takes output_type, so "nocomment" and "compressed", and preserve_formatting; it offers no way to set the indent, the comment column, or the ordering. TypeScript's writeIdf takes comments, commentColumn, indent, and versionFirst; it has no compressed mode and no lossless mode, the second of which is lossless-round-trip rather than part of this entry.

What is proven, and by what. The corpus asserts that a document survives its OWN writer without structural loss: assertion 3 re-parses each library's IDF output and compares object types, names, field names, field values, and field order against the document it started from. It does not compare the text, and runners/compare.md forbids any comparator from ever doing so, because one JSON value has many JSON texts. So the seven differences above are outside every assertion the corpus runs, and recording them here is the only place a reader meets them. A reader who needs byte-identical output from both languages does not have it and is not going to: pass EnergyPlus the model, not a diff.

Vocabulary this capability owns in the naming register
  • serialize IDF to a string
  • serialize epJSON to a string
  • write IDF to disk
  • write epJSON to disk
  • serialize a document to an epJSON value
  • serialize one object

Documents, collections, and objects

Python complete · JavaScript complete · Tier 1 · ledger id document-model

Vocabulary this capability owns in the naming register
  • the document class
  • the collection class
  • the object class
  • an extensible group
  • create a new document
  • add an object
  • remove an object
  • rename an object
  • every object of a type
  • untyped collection access
  • one object, or nothing
  • one object, or an error
  • collection to a sequence
  • an object's type name
  • version

Reference graph

Python complete · JavaScript complete · Tier 1 · ledger id references

Vocabulary this capability owns in the naming register
  • the reference graph
  • objects referencing a name
  • a reference edge

Schema access and the version registry

Python complete · JavaScript complete · Tier 1 · ledger id schema-access

Vocabulary this capability owns in the naming register
  • load a schema for a version
  • the supported version list
  • resolve a version string
  • one version's schema
  • the difference between two schema versions
  • resolve the schema for a detected version
  • the process-wide schema source

Model validation

Python complete · JavaScript complete · Tier 1 · ledger id validation

Vocabulary this capability owns in the naming register
  • validate a document
  • validate an object
  • validation result
  • validation finding
  • validation severity

Describing an object type from the schema

Python complete · JavaScript partial · Tier 1 · ledger id introspection

What differs, and why

TypeScript never populates memo or note. Both are members of the two types, so the field set matches, but they are always undefined. Python fills memo for 845 of 858 object types and note for 6,212 of 12,712 fields in 26.1.0, both from epJSON keys that @idfkit/schemas drops on purpose to keep the bundle off the parse critical path. The @idfkit/schemas/docs subpath its own header comment promises does not exist. Describing a type is what a REPL, a notebook, and an LSP hover are for, so the prose is most of the value; this is partial rather than complete.

Two further differences, both small and both pinned by tests. enumValues omits the empty string that Python includes for 1,378 of its 2,293 enum-bearing fields, and omits the sentinel lists (Autosize, Autocalculate) Python recovers from an anyOf branch for 769 fields. Field ORDER differs for exactly two types in 26.1.0, ZoneProperty:UserViewFactors:BySurfaceName and ZoneTerminalUnitList, and for six more in 8.9.0 through 9.2.0, because the bundle sorts property keys for content-addressing and those types carry no positional field list to restore declaration order from.

Vocabulary this capability owns in the naming register
  • describe an object type
  • object description
  • field description

Building EnergyPlus documentation URLs

Python complete · JavaScript complete · Tier 1 · ledger id documentation-urls

Vocabulary this capability owns in the naming register
  • resolved documentation URL
  • documentation URL for an object type
  • I/O reference URL
  • engineering reference URL
  • documentation search URL

Static types generated from the schema

Python partial · JavaScript complete · Tier 1 · ledger id generated-object-types

What differs, and why

Coverage differs, and the difference is visible to anyone not on the newest release. The Python stub set is generated for one EnergyPlus version at a time and is currently shipped for 26.1.0 only, so a model loaded at 9.4 gets the 26.1 field names and choice lists from the editor. The TypeScript type maps are emitted per version and selected by the caller, who parameterises the document with the map for the version being read, so an older model is typed as that older model or is left untyped rather than mistyped.

Application differs too. Python's stubs apply implicitly to every document. TypeScript's are opt-in by construction: an unparameterised document stays untyped, which is what version-generic code needs.

Vocabulary this capability owns in the naming register
  • generated object types
  • a version type map

Diagnostics from a parse

Python partial · JavaScript complete · Tier 1 · ledger id parse-diagnostics

What differs, and why

Both libraries produce diagnostics for a malformed input; only one hands them back. Python raises IDFParseError carrying the diagnostics that stopped the parse, and reports the recoverable ones (skipped malformed objects, discarded formatting trees, surplus fields on a non-extensible type) through the logging module, where a caller who wants them must install a handler. TypeScript returns them: parseIdf and loadIdfWithDiagnostics both yield a ParseResult whose diagnostics array holds the non-fatal findings alongside the document.

This matters to the conformance corpus, whose diagnostics assertion compares what each side reports for a malformed case (contracts/conformance-corpus.md).

Vocabulary this capability owns in the naming register
  • a parse diagnostic
  • diagnostics from a parse

The weather station index

Python complete · JavaScript partial · Tier 1 · ledger id weather-index

What differs, and why

Installation differs, and the difference is deliberate. pip install idfkit installs weather and its station index unconditionally, because Python extras gate dependencies rather than files, so a Python reader has weather whether or not they wanted it. npm install idfkit installs neither: weather is an opt-in peer there, added with npm install @idfkit/weather. Both libraries ship their own index once installed and neither retrieves one to get started (FR-043, FR-075, research R11). A JavaScript reader who follows a weather page without installing that package gets a resolution error, not a smaller feature, which is why the packaging is recorded here as a stated difference rather than left as an undescribed detail.

Freshness handling differs. Python fires a throttled nudge from StationIndex.load(): at most once every 24 hours it probes the upstream KML files, warns when the bundled or cached index is behind, records the check under the cache directory, and can be turned off with IDFKIT_NO_WEATHER_UPDATE_CHECK. JavaScript has no such nudge and no timestamp to throttle against. It exposes checkForUpdates and refreshStationIndex for a caller who asks, and does nothing on its own, because the nudge is built on a writable cache directory and a browser-targeted package has none. The consequence for a reader is concrete: a stale index goes unmentioned in JavaScript until they check for themselves.

The installation difference above is the whole weather surface's, not the index's alone. It is stated here because the index is where a reader meets it first, and weather-download and weather-file-cache refer back to it rather than repeat it.

Vocabulary this capability owns in the naming register
  • the station index
  • search stations
  • a weather station
  • refresh the station index
  • a text search result
  • a proximity search result
  • which field a text search matched
  • the station wire record
  • the upstream index base URL
  • fetch a prebuilt station index
  • parse a KML station index
  • read station metadata from a download URL
  • great-circle distance between two points
  • the weather options-object types
  • the station index wire form
  • build an index from index data
  • the upstream index file list
  • the bundled station index
  • check the station index for updates

Retrieving weather and design-day files

Python complete · JavaScript partial · Tier 1 · ledger id weather-download

What differs, and why

Both libraries retrieve a station's ZIP archive from climate.onebuilding.org and unpack the EPW, DDY, and STAT members out of it. What they hand back differs, and it differs in the first line a reader writes. Python's WeatherDownloader.download returns a WeatherFiles whose epw, ddy, stat, and zip_path are Path objects, because the files are on disk by the time it returns and a path is what EnergyPlus is given. TypeScript's fetchWeatherFiles returns a WeatherFiles whose epw, ddy, and stat are the file TEXT, alongside a members map holding every archive member as bytes, because a browser has no disk and the text is what @idfkit/engine takes. Same name, different values, which the naming register records under the retrieved weather files: code written from one language's documentation is wrong at runtime against the other rather than merely awkward.

Three things exist on one side only, and each follows from that one fact rather than from a gap. Python's download(station, only={".epw"}) extracts a chosen subset and returns PartialWeatherFiles; selective extraction is a property of writing into a cache, and the JavaScript side decodes from memory whatever the archive held. TypeScript's FetchWeatherOptions carries fetch, rewriteUrl, and signal, because climate.onebuilding.org sends no Access-Control-Allow-Origin header and a page can reach it only through a proxy the caller supplies; Python runs under no same-origin policy and owns its own urllib requests. TypeScript splits retrieving from writing, so @idfkit/weather/node adds saveWeatherFiles and SavedWeatherFiles, where in Python the two are one operation.

Resolving a canonical EPW filename differs in one argument. Python's index parameter is optional and defaults to the bundled index, because it can always find one on disk. TypeScript's is required, because the caller had to obtain an index already and the function has nowhere to load one from.

typescript = "partial" records the missing selective extraction and nothing else. It is not a verdict on the on-disk cache: that is weather-file-cache, which is permanently absent by decision rather than missing.

Vocabulary this capability owns in the naming register
  • download a weather file
  • download a station's EPW file
  • download an EPW file by filename
  • download a station's archive
  • the retrieved weather files
  • read a ZIP archive
  • the injectable fetch
  • write weather files to disk
  • the written weather file paths

Declaring the conformance level a release passes

Python complete · JavaScript complete · Tier 1 · ledger id conformance-declaration

Vocabulary this capability owns in the naming register
  • declared conformance level

Geocoding a place name

Python complete · JavaScript complete · Tier 1 · ledger id geocoding

Vocabulary this capability owns in the naming register
  • geocode a place name
  • detect the current location
  • the geocoding rate limiter
  • a geocoding failure

Tier 2: portable, not ported yet

Capabilities the second language could have and does not have today. Every entry carries a tracking issue, because recording any of them as permanent would claim more than the code supports.

Formatting-preserving round-trip

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id lossless-round-trip

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#12.

Vocabulary this capability owns in the naming register
  • preserve formatting on a round-trip

Reading geometry from a model

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id geometry-extraction

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#13.

Vocabulary this capability owns in the naming register
  • three-dimensional vector
  • three-dimensional polygon
  • read a surface's coordinates
  • a zone's origin
  • a zone's rotation
  • transform relative coordinates to world coordinates
  • a surface's area
  • a surface's tilt
  • a surface's azimuth
  • a zone's floor area
  • a zone's volume

Building and transforming geometry

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id geometry-authoring

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#14.

Vocabulary this capability owns in the naming register
  • set the window to wall ratio
  • rotate a building
  • translate a building
  • scale a building
  • add a shading block
  • set default constructions

Intersecting and matching surfaces

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id surface-matching

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#15.

Vocabulary this capability owns in the naming register
  • intersect and match surfaces
  • a surface match report

Generating zoned blocks from a footprint

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id zoning

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#16.

Vocabulary this capability owns in the naming register
  • create a zoned block
  • a zone footprint
  • a zoning scheme
  • link blocks

Construction thermal properties

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id thermal-properties

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#17.

Vocabulary this capability owns in the naming register
  • construction thermal properties
  • a construction's U-value
  • a construction's R-value
  • a construction's solar heat gain coefficient
  • a construction's layers

Schedule evaluation

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id schedules

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#18.

Vocabulary this capability owns in the naming register
  • evaluate a schedule
  • a schedule's values for a year
  • a schedule as a series
  • create a constant schedule
  • create a compact schedule
  • extract special days
  • the holidays in a model

Reading the output variable dictionary and selecting variables

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id output-variable-selection

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#19.

Vocabulary this capability owns in the naming register
  • read the output variable dictionary
  • an output variable
  • an output meter
  • select output variables for a run

Design days and ASHRAE sizing conditions

Python complete · JavaScript absent (not yet) · Tier 2 · ledger id design-day-sizing

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#20.

Vocabulary this capability owns in the naming register
  • apply ASHRAE sizing conditions
  • the design day manager

Tier 3: tooling and Node-bound capabilities

Absent from JavaScript today and not permanently so. Each one is reachable in Node, which is why none of them is recorded as permanent.

Forward-migrating a model between EnergyPlus versions

Python complete · JavaScript absent (not yet) · Tier 3 · ledger id version-migration

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#21.

Vocabulary this capability owns in the naming register
  • migrate a model to a newer version
  • a migration report
  • a migration step

Command-line interface

Python complete · JavaScript absent (not yet) · Tier 3 · ledger id command-line

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#22.

Vocabulary this capability owns in the naming register
  • the command line entry point

Checking source against another EnergyPlus version's schema

Python complete · JavaScript absent (not yet) · Tier 3 · ledger id schema-compatibility-check

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#23.

Vocabulary this capability owns in the naming register
  • check source compatibility with a version
  • diff two schemas
  • a compatibility diagnostic

Plotting simulation results

Python complete · JavaScript absent (not yet) · Tier 3 · ledger id result-plotting

Not in JavaScript yet

A temporary gap, not a boundary. The port is tracked in idfkit-js#24.

Vocabulary this capability owns in the naming register
  • plot an energy balance
  • plot a temperature profile
  • plot comfort hours
  • a plotting backend

Permanently single-language

Pairs of capabilities that were never one capability. Neither library is missing anything here, which is why these entries sit apart from the gaps above: each pair is two different mechanisms serving two different runtimes.

Running a locally installed EnergyPlus and reading its results

Python complete · JavaScript absent (never) · Permanently single-language · ledger id local-simulation

Python only, permanently

Requires an EnergyPlus installation on the machine and a subprocess to drive it, then reads the eplusout files that run leaves on disk. Neither the installation nor the subprocess is available in a browser, which is the runtime the JavaScript library targets. JavaScript reaches EnergyPlus by the other mechanism instead: see browser-simulation, which is not a workaround for this entry but a different capability.

Vocabulary this capability owns in the naming register
  • the local simulation surface

Running EnergyPlus in the browser

Python absent (never) · JavaScript complete · Permanently single-language · ledger id browser-simulation

JavaScript only, permanently

Delivered by @idfkit/engine, installed separately and deliberately not part of the shared install name: not a subpath, not a dependency, not an optional peer (research R19). The WebAssembly build exists to reach a runtime Python does not target, so Python has no counterpart and is not getting one. @idfkit/engine-assets is roughly 51 MB and versions on the EnergyPlus release it carries, while the loader versions on its own API, which is a second reason the facade does not carry it.

This is not a gap in Python. Python runs EnergyPlus by the other mechanism: see local-simulation.

Rendering a model to a vector image

Python complete · JavaScript absent (never) · Permanently single-language · ledger id svg-visualisation

Python only, permanently

A Python-side capability with no JavaScript counterpart and no plan for one. The output is a static vector image produced for a notebook, a report, or a file on disk, which is a Python workflow. A JavaScript caller wanting to look at a model is already in a runtime that draws, and is served by the other mechanism: see scene-rendering. Recording the two as one visualization entry would make each language read as missing something the other has, which is exactly the failure FR-078 and FR-068 forbid.

Vocabulary this capability owns in the naming register
  • the vector image surface

Rendering a three-dimensional scene

Python absent (never) · JavaScript complete · Permanently single-language · ledger id scene-rendering

JavaScript only, permanently

Delivered by @idfkit/viewer, installed by its own name like the simulation engine, and NOT reachable through the shared install name: no subpath, no dependency, no export-map entry, and no reserved name in the naming register. A reader reaches it by installing it explicitly, and the documentation says so rather than implying the facade carries it.

Python has no counterpart and is not getting one. A real-time interactive scene needs a rendering context that a Python process does not have, and Python's static vector output is a different mechanism serving a different workflow: see svg-visualisation. Neither is a gap in the other.

eppy compatibility surface

Python complete · JavaScript absent (never) · Permanently single-language · ledger id eppy-compatibility

Python only, permanently

A Python ecosystem concern with no JavaScript counterpart. These methods exist solely so that code written against eppy keeps working after a move to idfkit; every one of them names an idfkit alternative in its own docstring. There is no eppy in JavaScript, so there is nothing to be compatible with. Listed explicitly so it is never ported by mistake.

Vocabulary this capability owns in the naming register
  • eppy compatibility surface

Caching retrieved weather files on disk

Python complete · JavaScript absent (never) · Permanently single-language · ledger id weather-file-cache

Python only, permanently

FR-031, stated as a decision rather than a backlog item: the on-disk cache for retrieved weather and design-day files is Python's, and JavaScript MUST NOT grow one. Moving this entry out of never needs a constitutional amendment, not an edit here.

What Python has. WeatherDownloader owns a cache directory, per platform by default and moved with cache_dir or IDFKIT_CACHE_DIR. download() looks in it first and reaches the network only on a miss or past max_age, so the second call for a station costs nothing; clear_cache empties it. Everything downstream follows: the record it returns is paths rather than text, zip_path addresses the archive it kept, and selective extraction through only= is meaningful because a suffix skipped this time may already be sitting there from an earlier call.

Why JavaScript will not have one. @idfkit/weather targets a browser, a worker, and an edge runtime as well as Node. Two of those have no directory it could own, and picking one in Node would make the package behave differently depending on where it runs, which is the one thing a portable package must not do. So it fetches every time and returns text the caller keeps. saveWeatherFiles in @idfkit/weather/node writes a retrieved bundle where the caller says, and that is a caller-directed write rather than a cache: it consults nothing on the way in and remembers nothing on the way out.

This is not a gap in JavaScript, and it is why several one-sided names exist on each side. The station index is shipped, not cached, in both languages (FR-043, FR-075), so nothing here changes how either library finds a station: that is weather-index. Retrieval itself is present in both languages: that is weather-download.

Vocabulary this capability owns in the naming register
  • the weather file cache