asciichem 0.31.12 → 0.31.13

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02ee049d5ed6b808972e18f4ecf7bbf6723b39b8ba7a6342c38a06cd24b3673a
4
- data.tar.gz: d455c3156215f27e7509fa610769b573a6bb0e6592097f7c4c67357738095e1d
3
+ metadata.gz: 13b35ffffbfa3349f95961b56e7dae9e74d55a116554a76c1175f3f74e347183
4
+ data.tar.gz: ea78a952280a73728fbd27cff80af8e3eebf163e45b8428ece6171a588471b55
5
5
  SHA512:
6
- metadata.gz: e83e9ce16a0ed8a1b22491c1964d15fc906467c152a5afec383ce4774d073beb591d8011a481216033855abc76e7f3febd377437f8808a6c1620448e17c60539
7
- data.tar.gz: caeddc2cb2db07543e3ca9b49932a9ed2a0f68461f2f20eb7c6693914d9bf185b8c44cd7f27e5b2d107e0c9cf7ff704bf63a261180f5b6b112e0d2cc8326b28c
6
+ metadata.gz: 538a97d2151764c9c84026ecccf32380ca82393158ac56d85af050aceab459ca47eb23a7828fb48bb5ed9fbe8289b11d2a5583bd8bd8b96f40ee20002247d5d8
7
+ data.tar.gz: 6edff89d3e29935de3227db81ef9126d6d7ce46cf0c39d58343114522d88205de9d969d99f760e6bd8602bc71f85fd80310b8730684769c31ec9aa21fa8f0413
data/CHANGELOG.md CHANGED
@@ -3,6 +3,21 @@
3
3
  All notable changes to AsciiChem are documented here.
4
4
  This project follows [Semantic Versioning](https://semver.org/).
5
5
 
6
+ ## [0.31.13] - 2026-11-11
7
+
8
+ ### Fixed
9
+ - `Resolver.resolve_all` isolates source-level failures: a live probe
10
+ found the Common Chemistry API now answers 401 without an API key
11
+ (CAS key-gated the endpoint); with it registered by default, that
12
+ 401 raised through the multi-source fan-out and took the other
13
+ sources down with it. A source-level error now skips that source —
14
+ callers see what answered.
15
+
16
+ ### Changed
17
+ - The README documents the full capability surface: structures,
18
+ lint, local identity, resolution with provenance, citations, and
19
+ the command line.
20
+
6
21
  ## [0.31.12] - 2026-11-11
7
22
 
8
23
  ### Changed
data/README.adoc CHANGED
@@ -45,6 +45,91 @@ formula.to_mathml # => "<math>...</math>"
45
45
  formula.to_text # => "H_2O" (round trip)
46
46
  ----
47
47
 
48
+ The parsed model is the canonical form: MathML, HTML, LaTeX, text,
49
+ linear and 2D structural SVG, and CML are views over the same tree.
50
+
51
+ === Structures: SMILES and molfile in, AsciiChem out
52
+
53
+ [source,ruby]
54
+ ----
55
+ formula = AsciiChem.parse_smiles("CC(=O)Oc1ccccc1C(=O)O")
56
+ formula.to_structural_svg # 2D depiction, deterministic layout
57
+ formula.to_smiles # canonical aromatic SMILES
58
+ formula.to_text # AsciiChem text
59
+
60
+ formula = AsciiChem.parse_molfile(molfile_text) # V2000 in and out
61
+ ----
62
+
63
+ === Lint
64
+
65
+ [source,ruby]
66
+ ----
67
+ AsciiChem::Linter.run(formula) # chemistry diagnostics: balance,
68
+ # valence, charge, isotopes, rings,
69
+ # identifier consistency, ...
70
+ AsciiChem::Linter.errors?(formula) # => true/false
71
+ ----
72
+
73
+ === Local identity: InChI, AuxInfo, InChIKey
74
+
75
+ [source,ruby]
76
+ ----
77
+ require "asciichem/inchi"
78
+
79
+ # the native chemomer engine (byte-exact vs the IUPAC oracle;
80
+ # CHEMOMER_LIB points at the built cdylib) or the IUPAC binary:
81
+ AsciiChem::Inchi.engine = AsciiChem::Inchi::NativeEngine.new
82
+
83
+ identity = AsciiChem::Inchi.identity_for(molecule)
84
+ identity.inchi # "InChI=1S/C9H8O4/..."
85
+ identity.inchikey # "BSYNRYMUTXBXSQ-UHFFFAOYSA-N"
86
+ ----
87
+
88
+ === Resolution: identifiers to substance records
89
+
90
+ [source,ruby]
91
+ ----
92
+ require "asciichem/resolver"
93
+
94
+ substance = AsciiChem::Resolver.resolve(value: "50-78-2", convention: "cas")
95
+ substance.preferred_name # => "Aspirin"
96
+ substance.structure.to_smiles # from the source record
97
+ substance.identifiers.first.provenance.source # "common_chemistry"
98
+
99
+ # all shipped sources (PubChem, OPSIN, CAS Common Chemistry) resolve
100
+ # by default; attribution rides every record. Limit the set when a
101
+ # use must stay NC-free:
102
+ AsciiChem::Resolver.resolve(value: "50-78-2", convention: "cas",
103
+ sources: [:pubchem, :opsin])
104
+ ----
105
+
106
+ === Citations: dataset bibitems with provenance
107
+
108
+ [source,ruby]
109
+ ----
110
+ require "asciichem/citation"
111
+
112
+ molecule = AsciiChem.parse("CC(=O)OC1=CC=CC=C1C(=O)O @cas(\"50-78-2\") @cite(\"pubchem\")").nodes.first
113
+ AsciiChem::Citation.for_molecule(molecule)
114
+ # => [["pubchem", #<Relaton bibitem>]] - one dataset-type bibitem per
115
+ # (substance, source), anchored by InChIKey, with a provenance note
116
+ # (retrieved from, version, attribution).
117
+ ----
118
+
119
+ == Command line
120
+
121
+ [source,sh]
122
+ ----
123
+ asciichem convert -i "H_2O" -t mathml # also: --from smiles|molfile
124
+ asciichem identity -i aspirin.smiles --from smiles
125
+ asciichem resolve --cas 50-78-2 --source common_chemistry
126
+ asciichem validate -i 'H_2O @cas("50-78-2")'
127
+ asciichem cite --cas 50-78-2 -t model-json
128
+ asciichem lint -i "2H_2 + O_2 -> 2H_2O"
129
+ asciichem roundtrip -i "C_6H_12O_6"
130
+ asciichem parse-cml -i formula.xml
131
+ ----
132
+
48
133
  == Conformance
49
134
 
50
135
  The reference implementation of https://www.asciichem.org[the AsciiChem
@@ -43,16 +43,23 @@ module AsciiChem
43
43
  raise Error, "unknown resolver source #{name.inspect} (registered: #{adapters.keys.sort.join(', ')})"
44
44
  end
45
45
 
46
- # Resolves against every opt-in source, returning one Substance
47
- # per source that answers (nil entries dropped). Sources answer
48
- # in registration order.
46
+ # Resolves against every registered source (or the selected
47
+ # subset), returning one Substance per source that answers (nil
48
+ # entries dropped). Sources answer in registration order. A
49
+ # source-level failure (HTTP error, rejected request) skips that
50
+ # source — one dead or key-gated endpoint must not poison the
51
+ # others; callers see what answered.
49
52
  def resolve_all(value:, convention:, sources: nil, fetch: nil, cache: nil, refresh: false)
50
53
  selected = sources ? Array(sources).map { |s| self[s] } : adapters.values
51
54
  selected.filter_map do |adapter_class|
52
55
  adapter = adapter_class.new
53
56
  next unless adapter.supports?(convention)
54
57
 
55
- adapter.resolve(value: value, convention: convention, fetch: fetch, cache: cache, refresh: refresh)
58
+ begin
59
+ adapter.resolve(value: value, convention: convention, fetch: fetch, cache: cache, refresh: refresh)
60
+ rescue AsciiChem::Error
61
+ nil
62
+ end
56
63
  end
57
64
  end
58
65
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AsciiChem
4
- VERSION = "0.31.12"
4
+ VERSION = "0.31.13"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciichem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.31.12
4
+ version: 0.31.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.