ecircle 0.0.8 → 0.0.9
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.
- data/.yardopts +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +78 -49
- data/lib/ecircle/api.rb +29 -20
- data/lib/ecircle/helper.rb +13 -0
- data/lib/ecircle/version.rb +1 -1
- data/lib/ecircle/wrapped_response.rb +4 -0
- data/spec/{client_spec.rb → job_package_spec.rb} +5 -4
- metadata +76 -84
data/.yardopts
ADDED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -36,6 +36,7 @@ Since the asynchronous API is neither documented by ecircle nor intuitive at all
|
|
36
36
|
To do
|
37
37
|
-------------
|
38
38
|
|
39
|
+
* Fix TODOs in source code
|
39
40
|
* Implement missing API methods:
|
40
41
|
* createOrUpdateGroup
|
41
42
|
* deleteUser
|
@@ -43,16 +44,26 @@ To do
|
|
43
44
|
* lookupGroups
|
44
45
|
* Write specs
|
45
46
|
|
47
|
+
|
48
|
+
Installation
|
49
|
+
-------------
|
50
|
+
|
51
|
+
Either as a gem:
|
52
|
+
|
53
|
+
gem install ecircle
|
54
|
+
|
55
|
+
or via Bundler by adding it to your Gemfile.
|
56
|
+
|
57
|
+
|
46
58
|
Configuration
|
47
59
|
-------------
|
48
60
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
```
|
61
|
+
Ecircle.configure do |config|
|
62
|
+
config.user = 'your@user.com'
|
63
|
+
config.sync_realm = 'http://your.realm.com'
|
64
|
+
config.password = 'your_password'
|
65
|
+
end
|
66
|
+
|
56
67
|
|
57
68
|
The reason for the unusual configuration setting "sync_realm" is that there is also an asynchronous ecircle API with a different realm.
|
58
69
|
|
@@ -62,63 +73,81 @@ Logon
|
|
62
73
|
The ecircle gem does the session handling for you, there is no need to logon explicitly.
|
63
74
|
Session tokens will be re-used to keep the number of session related traffic to a minimum.
|
64
75
|
|
76
|
+
Response
|
77
|
+
-------------
|
78
|
+
|
79
|
+
The ecircle gem will always return a wrapped response. Except for when it doesn't because I didn't find the time which is
|
80
|
+
for create_or_update_user_by_email and logon (see examples below or the API doc).
|
81
|
+
|
82
|
+
The wrapped response object is just a neat abstraction to hide Ecircle's horrible, horrible error handling from you and provides several methods for doing so.
|
83
|
+
|
84
|
+
The most usefull (and self-explanatory) would be:
|
85
|
+
|
86
|
+
* success?
|
87
|
+
* error_message
|
88
|
+
* fault_code
|
89
|
+
* ecircle_id IF the API returns an ID an success, e.g. for create_member and create_or_update_user_by_email
|
90
|
+
* convenience methods which depend on your (failed request), e.g.:
|
91
|
+
* member_does_not_exist? (relevant for create_member requests)
|
92
|
+
* TODO Explain all convenience methods.
|
93
|
+
|
94
|
+
For details see [here](http://rubydoc.info/github/troessner/ecircle/master/Ecircle/WrappedResponse)
|
65
95
|
|
66
96
|
Examples
|
67
97
|
-------------
|
68
98
|
|
69
99
|
### Synchronous API
|
70
100
|
|
71
|
-
|
72
|
-
|
101
|
+
# Given you have called Ecircle.configure appropriatly...
|
102
|
+
|
103
|
+
# 1.) Create a user
|
104
|
+
uid = Ecircle.create_or_update_user_by_email 'your@email.com'
|
105
|
+
puts "Ecircle user ID: #{uid}"
|
73
106
|
|
74
|
-
#
|
75
|
-
|
76
|
-
puts "Ecircle
|
107
|
+
# 2.) Add this user as a member to a group - e.g. for newsletters
|
108
|
+
response = Ecircle.create_member uid, 'your_group_id'
|
109
|
+
puts "Ecircle member Id: #{response.ecircle_id}"
|
77
110
|
|
78
|
-
#
|
79
|
-
|
80
|
-
puts "Ecircle member Id: #{mid}"
|
111
|
+
# 3.) Delete member from group - e.g. when he unsubscribes
|
112
|
+
Ecircle.delete_member mid
|
81
113
|
|
82
|
-
#
|
83
|
-
Ecircle.
|
114
|
+
# 4.) Send the user a transactional email:
|
115
|
+
Ecircle.send_parametrized_single_message_to_user uid,
|
116
|
+
your_template_id_at_ecircle,
|
117
|
+
[ :name, :message ],
|
118
|
+
[ 'Tom', 'welcome!' ]
|
84
119
|
|
85
|
-
#
|
86
|
-
Ecircle.
|
87
|
-
your_template_id_at_ecircle,
|
88
|
-
[ :name, :message ],
|
89
|
-
[ 'Tom', 'welcome!' ]
|
120
|
+
# 5.) Delete the group
|
121
|
+
Ecircle.delete_group your_group_id
|
90
122
|
|
91
|
-
#
|
92
|
-
Ecircle.
|
123
|
+
# 6.) Log out
|
124
|
+
Ecircle.logout
|
93
125
|
|
94
|
-
# 6.) Log out
|
95
|
-
Ecircle.logout
|
96
126
|
|
97
|
-
```
|
98
127
|
### Asynchronous API
|
99
128
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
129
|
+
Note the async_realm in the configure block, this another realm as for the sync API.
|
130
|
+
|
131
|
+
Ecircle.configure do |config|
|
132
|
+
config.user = 'your@user.com'
|
133
|
+
config.async_realm = 'http://your.async.realm.com' # IMPORTANT - different realm.
|
134
|
+
config.password = 'your_password'
|
135
|
+
end
|
136
|
+
|
137
|
+
@options = {
|
138
|
+
:endpoint => 'http://your.domain/eC-MessageService',
|
139
|
+
:request_id => '1234',
|
140
|
+
:group_id => '5678',
|
141
|
+
:send_out_date => 70.minutes.from_now, # Must be at least one hour in the future!
|
142
|
+
:send_date_for_report => 140.minutes.from_now, # Must be at least one hour in the future *after* dispatching!
|
143
|
+
:report_email => 'your@report.de',
|
144
|
+
:report_email_name => 'Your name',
|
145
|
+
:subject => 'Newsletter',
|
146
|
+
:text => 'Newsletter text content',
|
147
|
+
:html => 'Newsletter html content'
|
148
|
+
}
|
149
|
+
|
150
|
+
Ecircle::JobPackage.send_async_message_to_group @options
|
122
151
|
|
123
152
|
Documentation
|
124
153
|
-------------
|
data/lib/ecircle/api.rb
CHANGED
@@ -59,7 +59,7 @@ module Ecircle
|
|
59
59
|
#
|
60
60
|
# @param [Integer] user_id ecircle user_id
|
61
61
|
# @param [Integer] group_id ecircle group_id
|
62
|
-
# @param [Boolean] invite send an invite
|
62
|
+
# @param [Boolean] invite send an additional invite mail
|
63
63
|
# @param [Boolean] send_message send a message by ecircle
|
64
64
|
# @return [WrappedResponse]
|
65
65
|
def create_member user_id, group_id, invite = false, send_message = false
|
@@ -75,23 +75,41 @@ module Ecircle
|
|
75
75
|
}
|
76
76
|
end
|
77
77
|
rescue Savon::SOAP::Fault => e
|
78
|
-
|
79
|
-
if wrapped_response.no_such_user? || wrapped_response.no_such_group_when_a_user_was_given
|
80
|
-
return wrapped_response
|
81
|
-
else
|
82
|
-
raise # Re-raise cause something else went wrong.
|
83
|
-
end
|
78
|
+
return WrappedResponse.new(e)
|
84
79
|
end
|
85
80
|
WrappedResponse.new(:success => true, :ecircle_id => @response.body[:create_member_response][:create_member_return].to_s)
|
86
81
|
end
|
87
82
|
end
|
88
83
|
|
84
|
+
# Create or update group
|
85
|
+
# see http://developer.ecircle-ag.com/apiwiki/wiki/SynchronousSoapAPI#section-SynchronousSoapAPI-GroupObjectExample
|
86
|
+
# for an example of the group xml
|
87
|
+
# @param [Hash] group_xml, in it's most simple form a { :name => 'your name', :description => 'desc', ':email => 'test@test.com' } is sufficient
|
88
|
+
# @return [WrappedResponse]
|
89
|
+
# Important note: `email` must be unique across all groups AND must be a subdomain of the system you registered at ecircle.
|
90
|
+
def create_or_update_group group_attributes
|
91
|
+
ensuring_logon do
|
92
|
+
begin
|
93
|
+
client.request :createOrUpdateGroup do
|
94
|
+
soap.body = {
|
95
|
+
:session => auth_token,
|
96
|
+
'wsdl:groupXml' => Helper.build_group_xml(group_attributes)
|
97
|
+
}
|
98
|
+
end
|
99
|
+
rescue Savon::SOAP::Fault => e
|
100
|
+
return WrappedResponse.new(e)
|
101
|
+
end
|
102
|
+
WrappedResponse.new(:success => true)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
89
106
|
# Create or update user by email
|
90
107
|
# see http://developer.ecircle-ag.com/apiwiki/wiki/SynchronousSoapAPI#section-SynchronousSoapAPI-UserObjectExample
|
91
108
|
# for an example of the user xml
|
92
109
|
# @param [Hash] user_xml, in it's most simple form a { :email => 'test@test.com' } is sufficient
|
93
110
|
# @return [Integer] the user id
|
94
111
|
# TODO Error handling is missing.
|
112
|
+
# TODO Return a wrapped response.
|
95
113
|
def create_or_update_user_by_email user_attributes
|
96
114
|
ensuring_logon do
|
97
115
|
@response = client.request :createOrUpdateUserByEmail do
|
@@ -119,12 +137,7 @@ module Ecircle
|
|
119
137
|
}
|
120
138
|
end
|
121
139
|
rescue Savon::SOAP::Fault => e
|
122
|
-
|
123
|
-
if wrapped_response.group_does_not_exist?
|
124
|
-
return wrapped_response
|
125
|
-
else
|
126
|
-
raise # Re-raise cause something else went wrong.
|
127
|
-
end
|
140
|
+
return WrappedResponse.new(e)
|
128
141
|
end
|
129
142
|
end
|
130
143
|
WrappedResponse.new(:success => true)
|
@@ -144,12 +157,7 @@ module Ecircle
|
|
144
157
|
}
|
145
158
|
end
|
146
159
|
rescue Savon::SOAP::Fault => e
|
147
|
-
|
148
|
-
if wrapped_response.member_does_not_exist?
|
149
|
-
return wrapped_response
|
150
|
-
else
|
151
|
-
raise # Re-raise cause something else went wrong.
|
152
|
-
end
|
160
|
+
return WrappedResponse.new(e)
|
153
161
|
end
|
154
162
|
end
|
155
163
|
WrappedResponse.new(:success => true)
|
@@ -178,6 +186,7 @@ module Ecircle
|
|
178
186
|
:session => auth_token,
|
179
187
|
}
|
180
188
|
end
|
189
|
+
WrappedResponse.new(:success => true)
|
181
190
|
end
|
182
191
|
|
183
192
|
# Send a parametrized single message to user - you need an existing ecircle template ID for this.
|
@@ -190,7 +199,7 @@ module Ecircle
|
|
190
199
|
def send_parametrized_single_message_to_user user_id, message_id, names = [], values = []
|
191
200
|
ensuring_logon do
|
192
201
|
begin
|
193
|
-
|
202
|
+
client.request :sendParametrizedSingleMessageToUser do
|
194
203
|
soap.body = {
|
195
204
|
:session => auth_token,
|
196
205
|
:singleMessageId => message_id,
|
data/lib/ecircle/helper.rb
CHANGED
@@ -15,5 +15,18 @@ module Ecircle
|
|
15
15
|
xml << "<#{name}>#{value}</#{name}>"
|
16
16
|
end+'</user>'
|
17
17
|
end
|
18
|
+
|
19
|
+
def build_group_xml attrs
|
20
|
+
# Important note: Actually I have no idea what ecircle wants here. This works for me. Just go with the flow.
|
21
|
+
xml = Builder::XmlMarkup.new
|
22
|
+
xml.tag! 'group', :xmlns => 'http://webservices.ecircle-ag.com/ecm', 'group-id' => 'new', 'preferred-channel' => 'email' do
|
23
|
+
xml.name attrs[:name]
|
24
|
+
xml.description attrs[:description]
|
25
|
+
xml.tag! 'email-channel' do
|
26
|
+
xml.email attrs[:email]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
xml.target!.gsub('"', "'").gsub('\\', '')
|
30
|
+
end
|
18
31
|
end
|
19
32
|
end
|
data/lib/ecircle/version.rb
CHANGED
@@ -9,6 +9,7 @@ describe Ecircle::JobPackage do
|
|
9
9
|
:send_out_date => date,
|
10
10
|
:send_date_for_report => date,
|
11
11
|
:report_email => 'report@dealvertise.de',
|
12
|
+
:report_email_name => 'Your name',
|
12
13
|
:location_name => 'Berlin',
|
13
14
|
:subject => 'Berlin newsletter',
|
14
15
|
:text => 'Newsletter text content',
|
@@ -28,14 +29,14 @@ describe Ecircle::JobPackage do
|
|
28
29
|
<send-report-address>
|
29
30
|
<email-address>
|
30
31
|
<email>#{@options[:report_email]}</email>
|
31
|
-
<name>
|
32
|
+
<name>Your name</name>
|
32
33
|
</email-address>
|
33
34
|
</send-report-address>
|
34
35
|
<status-report report-id="new" delete="false" user-tracking-details="false" link-tracking-details="false" bouncing-details="false">
|
35
36
|
<report-address>
|
36
37
|
<email-address>
|
37
38
|
<email>#{@options[:report_email]}</email>
|
38
|
-
<name>
|
39
|
+
<name>Your name</name>
|
39
40
|
</email-address>
|
40
41
|
</report-address>
|
41
42
|
<send-date>
|
@@ -51,13 +52,13 @@ describe Ecircle::JobPackage do
|
|
51
52
|
<success-report-address>
|
52
53
|
<email-address>
|
53
54
|
<email>#{@options[:report_email]}</email>
|
54
|
-
<name>
|
55
|
+
<name>Your name</name>
|
55
56
|
</email-address>
|
56
57
|
</success-report-address>
|
57
58
|
<failure-report-address>
|
58
59
|
<email-address>
|
59
60
|
<email>#{@options[:report_email]}</email>
|
60
|
-
<name>
|
61
|
+
<name>Your name</name>
|
61
62
|
</email-address>
|
62
63
|
</failure-report-address>
|
63
64
|
</control>
|
metadata
CHANGED
@@ -1,108 +1,104 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecircle
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.9
|
4
5
|
prerelease:
|
5
|
-
version: 0.0.8
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
-
|
7
|
+
authors:
|
8
|
+
- Timo Rößner
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-11-17 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
17
15
|
name: activesupport
|
18
|
-
requirement: &
|
16
|
+
requirement: &84616970 !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
24
22
|
type: :runtime
|
25
23
|
prerelease: false
|
26
|
-
version_requirements: *
|
27
|
-
- !ruby/object:Gem::Dependency
|
24
|
+
version_requirements: *84616970
|
25
|
+
- !ruby/object:Gem::Dependency
|
28
26
|
name: i18n
|
29
|
-
requirement: &
|
27
|
+
requirement: &84616320 !ruby/object:Gem::Requirement
|
30
28
|
none: false
|
31
|
-
requirements:
|
32
|
-
- -
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
35
33
|
type: :runtime
|
36
34
|
prerelease: false
|
37
|
-
version_requirements: *
|
38
|
-
- !ruby/object:Gem::Dependency
|
35
|
+
version_requirements: *84616320
|
36
|
+
- !ruby/object:Gem::Dependency
|
39
37
|
name: rake
|
40
|
-
requirement: &
|
38
|
+
requirement: &84615600 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version:
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
46
44
|
type: :runtime
|
47
45
|
prerelease: false
|
48
|
-
version_requirements: *
|
49
|
-
- !ruby/object:Gem::Dependency
|
46
|
+
version_requirements: *84615600
|
47
|
+
- !ruby/object:Gem::Dependency
|
50
48
|
name: savon
|
51
|
-
requirement: &
|
49
|
+
requirement: &84614520 !ruby/object:Gem::Requirement
|
52
50
|
none: false
|
53
|
-
requirements:
|
54
|
-
- -
|
55
|
-
- !ruby/object:Gem::Version
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
56
54
|
version: 0.9.7
|
57
55
|
type: :runtime
|
58
56
|
prerelease: false
|
59
|
-
version_requirements: *
|
60
|
-
- !ruby/object:Gem::Dependency
|
57
|
+
version_requirements: *84614520
|
58
|
+
- !ruby/object:Gem::Dependency
|
61
59
|
name: rspec
|
62
|
-
requirement: &
|
60
|
+
requirement: &84611650 !ruby/object:Gem::Requirement
|
63
61
|
none: false
|
64
|
-
requirements:
|
65
|
-
- -
|
66
|
-
- !ruby/object:Gem::Version
|
62
|
+
requirements:
|
63
|
+
- - =
|
64
|
+
- !ruby/object:Gem::Version
|
67
65
|
version: 2.6.0
|
68
66
|
type: :development
|
69
67
|
prerelease: false
|
70
|
-
version_requirements: *
|
71
|
-
- !ruby/object:Gem::Dependency
|
68
|
+
version_requirements: *84611650
|
69
|
+
- !ruby/object:Gem::Dependency
|
72
70
|
name: yard
|
73
|
-
requirement: &
|
71
|
+
requirement: &84610850 !ruby/object:Gem::Requirement
|
74
72
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
version:
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
79
77
|
type: :development
|
80
78
|
prerelease: false
|
81
|
-
version_requirements: *
|
82
|
-
- !ruby/object:Gem::Dependency
|
79
|
+
version_requirements: *84610850
|
80
|
+
- !ruby/object:Gem::Dependency
|
83
81
|
name: ruby-debug19
|
84
|
-
requirement: &
|
82
|
+
requirement: &84609900 !ruby/object:Gem::Requirement
|
85
83
|
none: false
|
86
|
-
requirements:
|
87
|
-
- -
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version:
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
90
88
|
type: :development
|
91
89
|
prerelease: false
|
92
|
-
version_requirements: *
|
90
|
+
version_requirements: *84609900
|
93
91
|
description: The ecircle gem aims to be a full-fledged client for all ecircle services.
|
94
|
-
email:
|
92
|
+
email:
|
95
93
|
- timo.roessner@googlemail.com
|
96
94
|
executables: []
|
97
|
-
|
98
95
|
extensions: []
|
99
|
-
|
100
96
|
extra_rdoc_files: []
|
101
|
-
|
102
|
-
files:
|
97
|
+
files:
|
103
98
|
- .gitignore
|
104
99
|
- .rvmrc
|
105
100
|
- .travis.yml
|
101
|
+
- .yardopts
|
106
102
|
- Gemfile
|
107
103
|
- Gemfile.lock
|
108
104
|
- README.md
|
@@ -115,41 +111,37 @@ files:
|
|
115
111
|
- lib/ecircle/job_package.rb
|
116
112
|
- lib/ecircle/version.rb
|
117
113
|
- lib/ecircle/wrapped_response.rb
|
118
|
-
- spec/
|
114
|
+
- spec/job_package_spec.rb
|
119
115
|
- spec/spec_helper.rb
|
120
|
-
|
121
|
-
homepage: ""
|
116
|
+
homepage: ''
|
122
117
|
licenses: []
|
123
|
-
|
124
118
|
post_install_message:
|
125
119
|
rdoc_options: []
|
126
|
-
|
127
|
-
require_paths:
|
120
|
+
require_paths:
|
128
121
|
- lib
|
129
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
123
|
none: false
|
131
|
-
requirements:
|
132
|
-
- -
|
133
|
-
- !ruby/object:Gem::Version
|
134
|
-
|
135
|
-
segments:
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
segments:
|
136
129
|
- 0
|
137
|
-
|
138
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
hash: 133028911
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
132
|
none: false
|
140
|
-
requirements:
|
141
|
-
- -
|
142
|
-
- !ruby/object:Gem::Version
|
143
|
-
|
144
|
-
segments:
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
segments:
|
145
138
|
- 0
|
146
|
-
|
139
|
+
hash: 133028911
|
147
140
|
requirements: []
|
148
|
-
|
149
141
|
rubyforge_project: ecircle
|
150
|
-
rubygems_version: 1.
|
142
|
+
rubygems_version: 1.8.10
|
151
143
|
signing_key:
|
152
144
|
specification_version: 3
|
153
145
|
summary: Ecircle gem
|
154
146
|
test_files: []
|
155
|
-
|
147
|
+
has_rdoc:
|