ISONGraph 1.3.0
Serialized output changes in this release. A graph written by 1.3.0 is not
byte-identical to one written by 1.2.0, and identifiers that 1.2.0 accepted
are now refused at construction. Both changes remove ways the old code lost
data silently; see Migrating below.
Changed — breaking
-
Every port now emits through its ISON parser's canonical writer. Each
port used to hand-roll its own ISON emitter beside the parser's, so ISON
syntax had two implementations per language that had to agree forever.
They did not: the id column was written unquoted, so a node id containing
a space produced output that would not reparse, and a string id like"1"
came back as the integer1.Blocks now sort by
kind.nameand columns sort within a block, soedges
precedesnodesand column order is the writer's rather than the caller's.
Strings that would otherwise reparse as numbers are quoted, which is what
makes the round trip lossless.# 1.2.0 # 1.3.0 nodes.person edges.KNOWS id name age since source target 1 Alice 30 2020 :person:1 :person:2 edges.KNOWS nodes.person source target since id age name :person:1 :person:2 2020 1 30 Alice -
Unrepresentable identifiers are refused at construction. Node types,
node ids and relation types may no longer be empty or contain whitespace,
:or|; types additionally may not contain"or\because they
become block names, which ISONL cannot quote. Property names are checked
against a wider set — they become ISON field names, where a leading#
turns the header into a comment and loses the whole block.An audit of hostile values across all three identifier positions found 18
of 24 combinations corrupting or crashing on round trip before this change. -
Node ids that differ only by type are refused. A reference carries no
type, so1and"1"both write as:p:1. A graph holding both was
addressable in memory and ambiguous on the wire; the second is now
rejected when the first exists. -
All six ports are on one version. Python, JS and TS were at 1.2.0;
Rust and C# at 1.0.0; C++ untagged.ISONGraph 1.3.0now means the same
code in every language. -
C++ requires ison-cpp >= 1.1.2.
ison_graph.hppincludes
ison_parser.hpprather than vendoring a copy, so an ISON fix arrives on
the next build instead of when someone re-cuts the copy. CMake takes
ISON_CPP_INCLUDE_DIRand fails configuration when the header is absent;
a header older than 1.1.2 is a compile error rather than a behavioural
difference.
Added
-
ison_graph.multigraph.MultiGraph(Python, experimental) — parallel
edges keyed by a stable integer, so the same relationship can be recorded
more than once between the same pair without inventing synthetic relation
types. Serialized output carries anison-graph-multigraph-v1marker, and
plainISONGraphrefuses to load it rather than silently dropping the
parallel edges. -
ison_graph.structural.ProtectedGraph(Python, experimental) —
refuses properties that shadow structural fields, hands properties out as
read-only views, and sealstype/id/rel_type/source/targetso an
object cannot report an identity the graph's indexes never used. -
convertersandschema-generatorpackages, with the crash bugs
found while testing them fixed.
Fixed
- Canonical serialization is genuinely insertion-order independent. Row
order previously depended on the order rows were added whenever the first
column tied. from_isonresolves references against the loaded nodes instead of
guessing that a numeric-looking id is an integer, which silently broke
graphs with string ids like"1".- Loaders take nodes before edges regardless of block order, which the
canonical writer changed. - Duplicate-edge imports no longer crash the CSV and GraphML converters.
- C++ tests assert with a macro that survives
NDEBUG. All 134 assertions
were compiled out under CMake's Release config, so the suite reported
every case as passing while checking nothing.
Migrating
- Regenerate stored
.isong/.isonlfiles from source data, or accept
that 1.3.0 output differs from 1.2.0. Content-addressed caches keyed on
the old bytes will miss once. - Check identifiers. If node ids or relation types contain whitespace,
:or|, they were already corrupting on round trip — map them to
graph-safe values at your boundary and translate back on the way out. - C++ users: put
ison_parser.hppon your include path.
Install
pip install ison-graph==1.3.0
cargo add ison-graph@1.3.0
npm install ison-graph-js@1.3.0 # or ison-graph-ts@1.3.0
dotnet add package IsonGraph --version 1.3.0C++ is header-only: copy ison-graph-cpp/include/ison_graph.hpp. It needs
ison-cpp >= 1.2.0 on the include path.
All six ports serialize identically; the shared fixture is 488 bytes ISON,
636 bytes ISONL.