orthonym.validation.opsin_server#
Note
Internal API. Names and behaviour may change between releases.
Persistent OPSIN process — amortize the ~1.7s JVM startup across every call.
The validity gate (namer.py -> OpsinOracle) shells out java -jar opsin -r
-osmi once per distinct name; on a full gate that is ~2000 fresh JVM boots
(~1.7s each ≈ 50+ min of pure startup). OPSIN’s CLI reads names line-by-line
from stdin and emits exactly ONE line per input (the SMILES, or a BLANK line
when it rejects the name) and flushes each line interactively — so a single
long-lived JVM fed over a pipe gives one startup for the whole run.
Contract preserved verbatim for the caller (OpsinOracle._invoke_opsin):
invoke(name) -> (raw_smiles_or_None, ran)
(smiles, True)— OPSIN parsed the name;
(None, True)— OPSIN ran and DEFINITIVELY rejected it (blank line);
(None, False)— the parse could not be performed (server absent / dead / read timeout / protocol anomaly). The caller treats this as transient and MUST fall back (to a one-shotsubprocess.run), so correctness NEVER depends on this optimization — it only removes latency.
Safety: a per-read timeout + auto-restart means a hung/crashed JVM degrades to
(None, False) (caller falls back) rather than blocking the gate. A single
lock serializes access (the pipe is one ordered stream; the gate is
single-threaded per the historical [99Tc] ThreadPoolExecutor-hang lesson).
- class orthonym.validation.opsin_server.PersistentOpsin(jar, args=('-r', '-osmi'), read_timeout=15.0)#
Bases:
objectOne long-lived
java -jar opsin...process fed names over stdin.- close()#
- invoke(name)#
Feed one name; return (raw_smiles_or_None, ran). Never raises.
- orthonym.validation.opsin_server.get_persistent_opsin(jar, args=('-r', '-osmi'))#
Shared PersistentOpsin for
jar/args; None if no jar.