neography 0.0.18 → 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
@@ -158,6 +158,30 @@ To Use:
158
158
 
159
159
  Please see the specs for more examples.
160
160
 
161
+ Batch (in progress):
162
+
163
+ @neo.batch [:get_node, node1], [:get_node, node2] # Gets two nodes in a batch
164
+ @neo.batch [:create_node, {"name" => "Max"}],
165
+ [:create_node, {"name" => "Marc"}] # Creates two nodes in a batch
166
+ @neo.batch [:set_node_property, node1, {"name" => "Tom"}],
167
+ [:set_node_property, node2, {"name" => "Jerry"}] # Sets the property of two nodes
168
+ @neo.batch [:get_relationship, rel1],
169
+ [:get_relationship, rel2] # Gets two relationships in a batch
170
+ @neo.batch [:create_relationship, "friends",
171
+ node1, node2, {:since => "high school"}]
172
+ [:create_relationship, "friends",
173
+ node1, node3, {:since => "college"}] # Creates two relationships in a batch
174
+ @neo.batch [:create_node, {"name" => "Max"}],
175
+ [:create_node, {"name" => "Marc"}], # Creates two nodes and index them
176
+ [:add_node_to_index, "test_node_index", key, value, "{0}"]
177
+ [:add_node_to_index, "test_node_index", key, value, "{1}"]
178
+ [:create_relationship, "friends", # and create a relationship for those
179
+ "{0}", "{1}", {:since => "college"}] # newly created nodes
180
+ [:add_relationship_to_index,
181
+ "test_relationship_index", key, value, "{4}"] # and index the new relationship
182
+
183
+ See http://docs.neo4j.org/chunked/milestone/rest-api-batch-ops.html for Neo4j Batch operations documentation.
184
+
161
185
  Experimental:
162
186
 
163
187
  nodes = @neo.create_nodes(5) # Create 5 empty nodes
@@ -253,7 +253,6 @@ module Neography
253
253
 
254
254
  def add_node_to_index(index, key, value, id)
255
255
  options = { :body => ({:uri => self.configuration + "/node/#{get_id(id)}", :key => key, :value => value }).to_json, :headers => {'Content-Type' => 'application/json'} }
256
- #post("/index/node/#{index}/#{key}/#{value}", options)
257
256
  post("/index/node/#{index}", options)
258
257
  end
259
258
 
@@ -352,9 +351,43 @@ module Neography
352
351
  result = post("/ext/GremlinPlugin/graphdb/execute_script", options)
353
352
  result == "null" ? nil : result
354
353
  end
354
+
355
+ def batch(*args)
356
+ batch = []
357
+ Array(args).each_with_index do |c,i|
358
+ batch << {:id => i}.merge(get_batch(c))
359
+ end
360
+ options = { :body => batch.to_json, :headers => {'Content-Type' => 'application/json'} }
361
+ post("/batch", options)
362
+ end
355
363
 
356
364
  private
357
365
 
366
+ def get_batch(args)
367
+ case args[0]
368
+ when :get_node
369
+ {:method => "GET", :to => "/node/#{get_id(args[1])}"}
370
+ when :create_node
371
+ {:method => "POST", :to => "/node/", :body => args[1]}
372
+ when :set_node_property
373
+ {:method => "PUT", :to => "/node/#{get_id(args[1])}/properties/#{args[2].keys.first}", :body => args[2].values.first}
374
+ when :reset_node_properties
375
+ {:method => "PUT", :to => "/node/#{get_id(args[1])}/properties", :body => args[2]}
376
+ when :get_relationship
377
+ {:method => "GET", :to => "/relationship/#{get_id(args[1])}"}
378
+ when :create_relationship
379
+ {:method => "POST", :to => (args[2].is_a?(String) && args[2].start_with?("{") ? "" : "/node/") + "#{get_id(args[2])}/relationships", :body => {:to => (args[3].is_a?(String) && args[3].start_with?("{") ? "" : "/node/") + "#{get_id(args[3])}", :type => args[1], :data => args[4] } }
380
+ when :set_relationship_property
381
+ {:method => "PUT", :to => "/relationship/#{get_id(args[1])}/properties/#{args[2].keys.first}", :body => args[2].values.first}
382
+ when :reset_relationship_properties
383
+ {:method => "PUT", :to => "/relationship/#{get_id(args[1])}/properties", :body => args[2]}
384
+ when :add_node_to_index
385
+ {:method => "POST", :to => "/index/node/#{args[1]}", :body => {:uri => (args[4].is_a?(String) && args[4].start_with?("{") ? "" : "/node/") + "#{get_id(args[4])}", :key => args[2], :value => args[3] } }
386
+ when :add_relationship_to_index
387
+ {:method => "POST", :to => "/index/relationship/#{args[1]}", :body => {:uri => (args[4].is_a?(String) && args[4].start_with?("{") ? "" : "/relationship/") + "#{get_id(args[4])}", :key => args[2], :value => args[3] } }
388
+ end
389
+ end
390
+
358
391
  def evaluate_response(response)
359
392
  code = response.code
360
393
  body = response.body
@@ -1,3 +1,3 @@
1
1
  module Neography
2
- VERSION = "0.0.18"
2
+ VERSION = "0.0.19"
3
3
  end
@@ -7,73 +7,207 @@ describe Neography::Rest do
7
7
 
8
8
  describe "simple batch" do
9
9
  it "can get a single node" do
10
- pending
10
+ new_node = @neo.create_node
11
+ new_node[:id] = new_node["self"].split('/').last
12
+ batch_result = @neo.batch [:get_node, new_node]
13
+ batch_result.first.should_not be_nil
14
+ batch_result.first.should have_key("id")
15
+ batch_result.first.should have_key("body")
16
+ batch_result.first.should have_key("from")
17
+ batch_result.first["body"]["self"].split('/').last.should == new_node[:id]
11
18
  end
12
19
 
13
20
  it "can get multiple nodes" do
14
- pending
15
- end
21
+ node1 = @neo.create_node
22
+ node1[:id] = node1["self"].split('/').last
23
+ node2 = @neo.create_node
24
+ node2[:id] = node2["self"].split('/').last
16
25
 
17
- it "can create a single node" do
18
- pending
19
- end
26
+ batch_result = @neo.batch [:get_node, node1], [:get_node, node2]
27
+ batch_result.first.should_not be_nil
28
+ batch_result.first.should have_key("id")
29
+ batch_result.first.should have_key("body")
30
+ batch_result.first.should have_key("from")
31
+ batch_result.first["body"]["self"].split('/').last.should == node1[:id]
32
+ batch_result.last.should have_key("id")
33
+ batch_result.last.should have_key("body")
34
+ batch_result.last.should have_key("from")
35
+ batch_result.last["body"]["self"].split('/').last.should == node2[:id]
20
36
 
21
- it "can create multiple nodes" do
22
- pending
23
37
  end
24
38
 
25
- it "can update a single node" do
26
- pending
39
+ it "can create a single node" do
40
+ batch_result = @neo.batch [:create_node, {"name" => "Max"}]
41
+ batch_result.first["body"]["data"]["name"].should == "Max"
27
42
  end
28
43
 
29
- it "can update multiple nodes" do
30
- pending
44
+ it "can create multiple nodes" do
45
+ batch_result = @neo.batch [:create_node, {"name" => "Max"}], [:create_node, {"name" => "Marc"}]
46
+ batch_result.first["body"]["data"]["name"].should == "Max"
47
+ batch_result.last["body"]["data"]["name"].should == "Marc"
48
+ end
49
+
50
+ it "can update a property of a node" do
51
+ new_node = @neo.create_node("name" => "Max")
52
+ batch_result = @neo.batch [:set_node_property, new_node, {"name" => "Marc"}]
53
+ batch_result.first.should have_key("id")
54
+ batch_result.first.should have_key("from")
55
+ existing_node = @neo.get_node(new_node)
56
+ existing_node["data"]["name"].should == "Marc"
57
+ end
58
+
59
+ it "can update a property of multiple nodes" do
60
+ node1 = @neo.create_node("name" => "Max")
61
+ node2 = @neo.create_node("name" => "Marc")
62
+ batch_result = @neo.batch [:set_node_property, node1, {"name" => "Tom"}], [:set_node_property, node2, {"name" => "Jerry"}]
63
+ batch_result.first.should have_key("id")
64
+ batch_result.first.should have_key("from")
65
+ batch_result.last.should have_key("id")
66
+ batch_result.last.should have_key("from")
67
+ existing_node = @neo.get_node(node1)
68
+ existing_node["data"]["name"].should == "Tom"
69
+ existing_node = @neo.get_node(node2)
70
+ existing_node["data"]["name"].should == "Jerry"
71
+ end
72
+
73
+ it "can reset the properties of a node" do
74
+ new_node = @neo.create_node("name" => "Max", "weight" => 200)
75
+ batch_result = @neo.batch [:reset_node_properties, new_node, {"name" => "Marc"}]
76
+ batch_result.first.should have_key("id")
77
+ batch_result.first.should have_key("from")
78
+ existing_node = @neo.get_node(new_node)
79
+ existing_node["data"]["name"].should == "Marc"
80
+ existing_node["data"]["weight"].should be_nil
81
+ end
82
+
83
+ it "can reset the properties of multiple nodes" do
84
+ node1 = @neo.create_node("name" => "Max", "weight" => 200)
85
+ node2 = @neo.create_node("name" => "Marc", "weight" => 180)
86
+ batch_result = @neo.batch [:reset_node_properties, node1, {"name" => "Tom"}], [:reset_node_properties, node2, {"name" => "Jerry"}]
87
+ batch_result.first.should have_key("id")
88
+ batch_result.first.should have_key("from")
89
+ batch_result.last.should have_key("id")
90
+ batch_result.last.should have_key("from")
91
+ existing_node = @neo.get_node(node1)
92
+ existing_node["data"]["name"].should == "Tom"
93
+ existing_node["data"]["weight"].should be_nil
94
+ existing_node = @neo.get_node(node2)
95
+ existing_node["data"]["name"].should == "Jerry"
96
+ existing_node["data"]["weight"].should be_nil
31
97
  end
32
98
 
33
99
  it "can get a single relationship" do
34
- pending
100
+ node1 = @neo.create_node
101
+ node2 = @neo.create_node
102
+ new_relationship = @neo.create_relationship("friends", node1, node2)
103
+ batch_result = @neo.batch [:get_relationship, new_relationship]
104
+ batch_result.first["body"]["type"].should == "friends"
105
+ batch_result.first["body"]["start"].split('/').last.should == node1["self"].split('/').last
106
+ batch_result.first["body"]["end"].split('/').last.should == node2["self"].split('/').last
107
+ batch_result.first["body"]["self"].should == new_relationship["self"]
35
108
  end
36
109
 
37
- it "can get multiple relationships" do
38
- pending
39
- end
40
-
41
110
  it "can create a single relationship" do
42
- pending
43
- end
44
-
45
- it "can create multiple relationships" do
46
- pending
111
+ node1 = @neo.create_node
112
+ node2 = @neo.create_node
113
+ batch_result = @neo.batch [:create_relationship, "friends", node1, node2, {:since => "high school"}]
114
+ batch_result.first["body"]["type"].should == "friends"
115
+ batch_result.first["body"]["data"]["since"].should == "high school"
116
+ batch_result.first["body"]["start"].split('/').last.should == node1["self"].split('/').last
117
+ batch_result.first["body"]["end"].split('/').last.should == node2["self"].split('/').last
47
118
  end
48
119
 
49
120
  it "can update a single relationship" do
50
- pending
51
- end
52
-
53
- it "can update multiple relationships" do
54
- pending
121
+ node1 = @neo.create_node
122
+ node2 = @neo.create_node
123
+ new_relationship = @neo.create_relationship("friends", node1, node2, {:since => "high school"})
124
+ batch_result = @neo.batch [:set_relationship_property, new_relationship, {:since => "college"}]
125
+ batch_result.first.should have_key("id")
126
+ batch_result.first.should have_key("from")
127
+ existing_relationship = @neo.get_relationship(new_relationship)
128
+ existing_relationship["type"].should == "friends"
129
+ existing_relationship["data"]["since"].should == "college"
130
+ existing_relationship["start"].split('/').last.should == node1["self"].split('/').last
131
+ existing_relationship["end"].split('/').last.should == node2["self"].split('/').last
132
+ existing_relationship["self"].should == new_relationship["self"]
55
133
  end
56
134
 
57
135
  it "can add a node to an index" do
58
- pending
136
+ new_node = @neo.create_node
137
+ key = generate_text(6)
138
+ value = generate_text
139
+ new_index = @neo.get_node_index("test_node_index", key, value)
140
+ batch_result = @neo.batch [:add_node_to_index, "test_node_index", key, value, new_node]
141
+ batch_result.first.should have_key("id")
142
+ batch_result.first.should have_key("from")
143
+ existing_index = @neo.find_node_index("test_node_index", key, value)
144
+ existing_index.should_not be_nil
145
+ existing_index.first["self"].should == new_node["self"]
146
+ @neo.remove_node_from_index("test_node_index", key, value, new_node)
59
147
  end
60
148
  end
61
149
 
62
150
  describe "referenced batch" do
63
151
  it "can create a relationship from two newly created nodes" do
64
- pending
152
+ batch_result = @neo.batch [:create_node, {"name" => "Max"}], [:create_node, {"name" => "Marc"}], [:create_relationship, "friends", "{0}", "{1}", {:since => "high school"}]
153
+ batch_result.first["body"]["data"]["name"].should == "Max"
154
+ batch_result[1]["body"]["data"]["name"].should == "Marc"
155
+ batch_result.last["body"]["type"].should == "friends"
156
+ batch_result.last["body"]["data"]["since"].should == "high school"
157
+ batch_result.last["body"]["start"].split('/').last.should == batch_result.first["body"]["self"].split('/').last
158
+ batch_result.last["body"]["end"].split('/').last.should == batch_result[1]["body"]["self"].split('/').last
65
159
  end
66
160
 
67
161
  it "can create a relationship from an existing node and a newly created node" do
68
- pending
162
+ node1 = @neo.create_node("name" => "Max", "weight" => 200)
163
+ batch_result = @neo.batch [:create_node, {"name" => "Marc"}], [:create_relationship, "friends", "{0}", node1, {:since => "high school"}]
164
+ batch_result.first["body"]["data"]["name"].should == "Marc"
165
+ batch_result.last["body"]["type"].should == "friends"
166
+ batch_result.last["body"]["data"]["since"].should == "high school"
167
+ batch_result.last["body"]["start"].split('/').last.should == batch_result.first["body"]["self"].split('/').last
168
+ batch_result.last["body"]["end"].split('/').last.should == node1["self"].split('/').last
69
169
  end
70
170
 
71
171
  it "can add a newly created node to an index" do
72
- pending
172
+ key = generate_text(6)
173
+ value = generate_text
174
+ new_index = @neo.get_node_index("test_node_index", key, value)
175
+ batch_result = @neo.batch [:create_node, {"name" => "Max"}], [:add_node_to_index, "test_node_index", key, value, "{0}"]
176
+ batch_result.first.should have_key("id")
177
+ batch_result.first.should have_key("from")
178
+ existing_index = @neo.find_node_index("test_node_index", key, value)
179
+ existing_index.should_not be_nil
180
+ existing_index.first["self"].should == batch_result.first["body"]["self"]
181
+ @neo.remove_node_from_index("test_node_index", key, value, batch_result.first["body"]["self"].split('/').last)
73
182
  end
74
183
 
75
184
  it "can add a newly created relationship to an index" do
76
- pending
185
+ key = generate_text(6)
186
+ value = generate_text
187
+ node1 = @neo.create_node
188
+ node2 = @neo.create_node
189
+ batch_result = @neo.batch [:create_relationship, "friends", node1, node2, {:since => "high school"}], [:add_relationship_to_index, "test_relationship_index", key, value, "{0}"]
190
+ batch_result.first["body"]["type"].should == "friends"
191
+ batch_result.first["body"]["data"]["since"].should == "high school"
192
+ batch_result.first["body"]["start"].split('/').last.should == node1["self"].split('/').last
193
+ batch_result.first["body"]["end"].split('/').last.should == node2["self"].split('/').last
194
+ existing_index = @neo.find_relationship_index("test_relationship_index", key, value)
195
+ existing_index.should_not be_nil
196
+ existing_index.first["self"].should == batch_result.first["body"]["self"]
197
+
198
+ end
199
+
200
+ it "can kitchen sink" do
201
+ key = generate_text(6)
202
+ value = generate_text
203
+
204
+ batch_result = @neo.batch [:create_node, {"name" => "Max"}],
205
+ [:create_node, {"name" => "Marc"}],
206
+ [:add_node_to_index, "test_node_index", key, value, "{0}"]
207
+ [:add_node_to_index, "test_node_index", key, value, "{1}"]
208
+ [:create_relationship, "friends", "{0}", "{1}", {:since => "college"}]
209
+ [:add_relationship_to_index, "test_relationship_index", key, value, "{4}"]
210
+ batch_result.should_not be_nil
77
211
  end
78
212
  end
79
213
 
metadata CHANGED
@@ -1,135 +1,100 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: neography
3
- version: !ruby/object:Gem::Version
4
- hash: 59
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.19
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 18
10
- version: 0.0.18
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Max De Marzi
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-01-03 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-01-05 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rspec
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70481300 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
32
22
  type: :development
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: net-http-spy
36
23
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70481300
25
+ - !ruby/object:Gem::Dependency
26
+ name: net-http-spy
27
+ requirement: &70480860 !ruby/object:Gem::Requirement
38
28
  none: false
39
- requirements:
40
- - - "="
41
- - !ruby/object:Gem::Version
42
- hash: 21
43
- segments:
44
- - 0
45
- - 2
46
- - 1
29
+ requirements:
30
+ - - =
31
+ - !ruby/object:Gem::Version
47
32
  version: 0.2.1
48
33
  type: :development
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: rake
52
34
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *70480860
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &70480390 !ruby/object:Gem::Requirement
54
39
  none: false
55
- requirements:
40
+ requirements:
56
41
  - - ~>
57
- - !ruby/object:Gem::Version
58
- hash: 49
59
- segments:
60
- - 0
61
- - 8
62
- - 7
42
+ - !ruby/object:Gem::Version
63
43
  version: 0.8.7
64
44
  type: :development
65
- version_requirements: *id003
66
- - !ruby/object:Gem::Dependency
67
- name: httparty
68
45
  prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *70480390
47
+ - !ruby/object:Gem::Dependency
48
+ name: httparty
49
+ requirement: &70480000 !ruby/object:Gem::Requirement
70
50
  none: false
71
- requirements:
72
- - - "="
73
- - !ruby/object:Gem::Version
74
- hash: 19
75
- segments:
76
- - 0
77
- - 7
78
- - 8
51
+ requirements:
52
+ - - =
53
+ - !ruby/object:Gem::Version
79
54
  version: 0.7.8
80
55
  type: :runtime
81
- version_requirements: *id004
82
- - !ruby/object:Gem::Dependency
83
- name: json
84
56
  prerelease: false
85
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *70480000
58
+ - !ruby/object:Gem::Dependency
59
+ name: json
60
+ requirement: &70479670 !ruby/object:Gem::Requirement
86
61
  none: false
87
- requirements:
88
- - - ">="
89
- - !ruby/object:Gem::Version
90
- hash: 3
91
- segments:
92
- - 0
93
- version: "0"
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
94
66
  type: :runtime
95
- version_requirements: *id005
96
- - !ruby/object:Gem::Dependency
97
- name: os
98
67
  prerelease: false
99
- requirement: &id006 !ruby/object:Gem::Requirement
68
+ version_requirements: *70479670
69
+ - !ruby/object:Gem::Dependency
70
+ name: os
71
+ requirement: &70479300 !ruby/object:Gem::Requirement
100
72
  none: false
101
- requirements:
102
- - - ">="
103
- - !ruby/object:Gem::Version
104
- hash: 3
105
- segments:
106
- - 0
107
- version: "0"
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
108
77
  type: :runtime
109
- version_requirements: *id006
110
- - !ruby/object:Gem::Dependency
111
- name: rubyzip
112
78
  prerelease: false
113
- requirement: &id007 !ruby/object:Gem::Requirement
79
+ version_requirements: *70479300
80
+ - !ruby/object:Gem::Dependency
81
+ name: rubyzip
82
+ requirement: &70478950 !ruby/object:Gem::Requirement
114
83
  none: false
115
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- hash: 3
119
- segments:
120
- - 0
121
- version: "0"
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
122
88
  type: :runtime
123
- version_requirements: *id007
124
- description: A Ruby wrapper to the Neo4j Rest API see http://components.neo4j.org/neo4j-rest/ for more details.
89
+ prerelease: false
90
+ version_requirements: *70478950
91
+ description: A Ruby wrapper to the Neo4j Rest API see http://components.neo4j.org/neo4j-rest/
92
+ for more details.
125
93
  email: maxdemarzi@gmail.com
126
94
  executables: []
127
-
128
95
  extensions: []
129
-
130
96
  extra_rdoc_files: []
131
-
132
- files:
97
+ files:
133
98
  - .gitignore
134
99
  - .project
135
100
  - .travis.yml
@@ -184,36 +149,26 @@ files:
184
149
  - spec/spec_helper.rb
185
150
  homepage: http://rubygems.org/gems/neography
186
151
  licenses: []
187
-
188
152
  post_install_message:
189
153
  rdoc_options: []
190
-
191
- require_paths:
154
+ require_paths:
192
155
  - lib
193
- required_ruby_version: !ruby/object:Gem::Requirement
156
+ required_ruby_version: !ruby/object:Gem::Requirement
194
157
  none: false
195
- requirements:
196
- - - ">="
197
- - !ruby/object:Gem::Version
198
- hash: 3
199
- segments:
200
- - 0
201
- version: "0"
202
- required_rubygems_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ! '>='
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
203
163
  none: false
204
- requirements:
205
- - - ">="
206
- - !ruby/object:Gem::Version
207
- hash: 3
208
- segments:
209
- - 0
210
- version: "0"
164
+ requirements:
165
+ - - ! '>='
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
211
168
  requirements: []
212
-
213
169
  rubyforge_project: neography
214
- rubygems_version: 1.8.9
170
+ rubygems_version: 1.8.10
215
171
  signing_key:
216
172
  specification_version: 3
217
173
  summary: ruby wrapper to Neo4j Rest API
218
174
  test_files: []
219
-