commonchemistry 0.1.0
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 +7 -0
- data/lib/commonchemistry/version.rb +3 -0
- data/lib/commonchemistry.rb +179 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 179b8b0132bd3294019e9e93e2e85a5ff0a23f3f12457734ea843f50efbe2f82
|
4
|
+
data.tar.gz: ae36ef95a8b3974b3b73e5cfd28e99fd4be1af47b4f5c7f6dea63c4da975f256
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eb82a95d20c50fac2400a7f5ff41c49b777fb95e52ca58d85b02eb24a320985ff6918b4b787bf171b49f5f3515bbcfff61bbb205f80e0654f7bdf3648af54ccd
|
7
|
+
data.tar.gz: 84e4dd2ab2d0ecd9edb57d9caa2e6737ebea4c7f9a1dc3abe4295c27b90ab717789fd8bc1d43ebd90e2a067cd1d3c34f990cb55ecca996e33729101563d8e3cb
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module CommonChemistry
|
5
|
+
# Base error class for CommonChemistry errors
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
# Error raised when a request is invalid (400, 404)
|
9
|
+
class InvalidRequestError < Error; end
|
10
|
+
|
11
|
+
# Error raised when the server returns an internal error (500)
|
12
|
+
class ServerError < Error; end
|
13
|
+
|
14
|
+
# Error raised for unexpected responses
|
15
|
+
class UnexpectedResponseError < Error; end
|
16
|
+
|
17
|
+
# Client class to interact with the Common Chemistry API
|
18
|
+
class Client
|
19
|
+
include HTTParty
|
20
|
+
base_uri 'https://commonchemistry.cas.org/api'
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
# TODO
|
24
|
+
end
|
25
|
+
|
26
|
+
# Searches for substances matching the query
|
27
|
+
#
|
28
|
+
# @param q [String] The search query
|
29
|
+
# @param offset [Integer, nil] The offset for pagination
|
30
|
+
# @param size [Integer, nil] The number of results to return
|
31
|
+
# @return [SearchResponse] The search results
|
32
|
+
# @raise [InvalidRequestError] if the request is invalid
|
33
|
+
# @raise [ServerError] if the server returns an error
|
34
|
+
# @raise [UnexpectedResponseError] for other errors
|
35
|
+
def search(q:, offset: nil, size: nil)
|
36
|
+
params = { q: q }
|
37
|
+
params[:offset] = offset if offset
|
38
|
+
params[:size] = size if size
|
39
|
+
|
40
|
+
response = self.class.get('/search', query: params)
|
41
|
+
handle_response(response) do
|
42
|
+
SearchResponse.new(response.parsed_response)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Retrieves detailed information about a substance
|
47
|
+
#
|
48
|
+
# @param cas_rn [String, nil] The CAS registry number
|
49
|
+
# @param uri [String, nil] The URI of the substance
|
50
|
+
# @return [DetailResult] The detailed substance information
|
51
|
+
# @raise [InvalidRequestError] if the request is invalid
|
52
|
+
# @raise [ServerError] if the server returns an error
|
53
|
+
# @raise [UnexpectedResponseError] for other errors
|
54
|
+
def detail(cas_rn: nil, uri: nil)
|
55
|
+
params = {}
|
56
|
+
params[:cas_rn] = cas_rn if cas_rn
|
57
|
+
params[:uri] = uri if uri
|
58
|
+
|
59
|
+
response = self.class.get('/detail', query: params)
|
60
|
+
handle_response(response) do
|
61
|
+
DetailResult.new(response.parsed_response)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Exports substance data
|
66
|
+
#
|
67
|
+
# @param uri [String] The URI of the substance
|
68
|
+
# @param return_as_attachment [Boolean] Whether to return as attachment
|
69
|
+
# @return [String] The exported data
|
70
|
+
# @raise [InvalidRequestError] if the request is invalid
|
71
|
+
# @raise [ServerError] if the server returns an error
|
72
|
+
# @raise [UnexpectedResponseError] for other errors
|
73
|
+
def export(uri:, return_as_attachment: false)
|
74
|
+
params = { uri: uri, returnAsAttachment: return_as_attachment }
|
75
|
+
response = self.class.get('/export', query: params)
|
76
|
+
handle_response(response) do
|
77
|
+
response.body # Since the response is text/plain
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def handle_response(response)
|
84
|
+
case response.code
|
85
|
+
when 200
|
86
|
+
yield
|
87
|
+
when 400, 404
|
88
|
+
raise InvalidRequestError, "Invalid Request (#{response.code})"
|
89
|
+
when 500
|
90
|
+
raise ServerError, "Internal Server Error (#{response.code})"
|
91
|
+
else
|
92
|
+
raise UnexpectedResponseError, "Unexpected response code: #{response.code}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Represents a search response from the API
|
98
|
+
class SearchResponse
|
99
|
+
attr_reader :count, :results
|
100
|
+
|
101
|
+
def initialize(data)
|
102
|
+
@count = data['count'].to_i
|
103
|
+
@results = (data['results'] || []).map { |result| SearchResult.new(result) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Represents an individual search result
|
108
|
+
class SearchResult
|
109
|
+
attr_reader :rn, :name, :image
|
110
|
+
|
111
|
+
def initialize(data)
|
112
|
+
@rn = data['rn']
|
113
|
+
@name = data['name']
|
114
|
+
@image = data['image']
|
115
|
+
end
|
116
|
+
|
117
|
+
# Saves the SVG image to a file
|
118
|
+
#
|
119
|
+
# @param filename [String] The filename to save the image as
|
120
|
+
def save_image(filename)
|
121
|
+
File.open(filename, 'w') { |file| file.write(@image) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Represents detailed information about a substance
|
126
|
+
class DetailResult
|
127
|
+
attr_reader :uri, :rn, :name, :image, :inchi, :inchi_key, :smile,
|
128
|
+
:canonical_smile, :molecular_formula, :molecular_mass,
|
129
|
+
:experimental_properties, :property_citations,
|
130
|
+
:synonyms, :replaced_rns
|
131
|
+
|
132
|
+
def initialize(data)
|
133
|
+
@uri = data['uri']
|
134
|
+
@rn = data['rn']
|
135
|
+
@name = data['name']
|
136
|
+
@image = data['image']
|
137
|
+
@inchi = data['inchi']
|
138
|
+
@inchi_key = data['inchiKey']
|
139
|
+
@smile = data['smile']
|
140
|
+
@canonical_smile = data['canonicalSmile']
|
141
|
+
@molecular_formula = data['molecularFormula']
|
142
|
+
@molecular_mass = data['molecularMass']
|
143
|
+
@experimental_properties = (data['experimentalProperties'] || []).map { |prop| ExperimentalProperty.new(prop) }
|
144
|
+
@property_citations = (data['propertyCitations'] || []).map { |citation| PropertyCitation.new(citation) }
|
145
|
+
@synonyms = data['synonyms'] || []
|
146
|
+
@replaced_rns = data['replacedRns'] || []
|
147
|
+
end
|
148
|
+
|
149
|
+
# Saves the SVG image to a file
|
150
|
+
#
|
151
|
+
# @param filename [String] The filename to save the image as
|
152
|
+
def save_image(filename)
|
153
|
+
File.open(filename, 'w') { |file| file.write(@image) }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Represents an experimental property of a substance
|
158
|
+
class ExperimentalProperty
|
159
|
+
attr_reader :name, :property, :source_number
|
160
|
+
|
161
|
+
def initialize(data)
|
162
|
+
@name = data['name']
|
163
|
+
@property = data['property']
|
164
|
+
@source_number = data['sourceNumber']
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Represents a property citation
|
169
|
+
class PropertyCitation
|
170
|
+
attr_reader :doc_uri, :source_number, :source
|
171
|
+
|
172
|
+
def initialize(data)
|
173
|
+
@doc_uri = data['docUri']
|
174
|
+
@source_number = data['sourceNumber']
|
175
|
+
@source = data['source']
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: commonchemistry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- coderobe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.22.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.22.0
|
27
|
+
description: commonchemistry api module
|
28
|
+
email:
|
29
|
+
- git@coderobe.net
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- lib/commonchemistry.rb
|
35
|
+
- lib/commonchemistry/version.rb
|
36
|
+
homepage: https://github.com/coderobe/ruby-commonchemistry
|
37
|
+
licenses: []
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubygems_version: 3.5.4
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: commonchemistry.cas.org api wrapper
|
58
|
+
test_files: []
|