env_parser 1.3.1 → 1.3.2

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -1
  3. data/.rubocop.yml +22 -35
  4. data/.ruby-version +1 -1
  5. data/Gemfile.lock +44 -42
  6. data/README.md +1 -1
  7. data/docs/EnvParser/AutoregisterFileNotFound.html +6 -6
  8. data/docs/EnvParser/Error.html +5 -6
  9. data/docs/EnvParser/TypeAlreadyDefinedError.html +5 -6
  10. data/docs/EnvParser/Types/BaseTypes.html +9 -7
  11. data/docs/EnvParser/Types/ChronologyTypes.html +7 -6
  12. data/docs/EnvParser/Types/InternetTypes.html +7 -6
  13. data/docs/EnvParser/Types.html +6 -6
  14. data/docs/EnvParser/UnknownTypeError.html +5 -6
  15. data/docs/EnvParser/UnparseableAutoregisterSpec.html +6 -6
  16. data/docs/EnvParser/ValueNotAllowedError.html +7 -6
  17. data/docs/EnvParser/ValueNotConvertibleError.html +5 -6
  18. data/docs/EnvParser.html +117 -121
  19. data/docs/_index.html +5 -7
  20. data/docs/file.README.html +241 -143
  21. data/docs/frames.html +1 -1
  22. data/docs/index.html +241 -143
  23. data/docs/method_list.html +1 -9
  24. data/docs/top-level-namespace.html +4 -82
  25. data/env_parser.gemspec +14 -14
  26. data/lib/env_parser/errors.rb +18 -18
  27. data/lib/env_parser/types/base_types.rb +69 -69
  28. data/lib/env_parser/types/chronology_types.rb +54 -54
  29. data/lib/env_parser/types/internet_types.rb +50 -50
  30. data/lib/env_parser/types.rb +2 -2
  31. data/lib/env_parser/version.rb +1 -1
  32. data/lib/env_parser.rb +205 -213
  33. data/spec/env_parser/types/base_types_spec.rb +98 -0
  34. data/spec/env_parser/types/chronology_types_spec.rb +49 -0
  35. data/spec/env_parser/types/internet_types_spec.rb +45 -0
  36. data/spec/env_parser_spec.rb +192 -0
  37. data/spec/spec_helper.rb +14 -0
  38. metadata +53 -48
  39. data/.travis.yml +0 -5
@@ -6,7 +6,7 @@
6
6
  <title>
7
7
  Top Level Namespace
8
8
 
9
- &mdash; Documentation by YARD 0.9.26
9
+ &mdash; Documentation by YARD 0.9.28
10
10
 
11
11
  </title>
12
12
 
@@ -95,92 +95,14 @@
95
95
 
96
96
 
97
97
 
98
-
99
- <h2>
100
- Instance Method Summary
101
- <small><a href="#" class="summary_toggle">collapse</a></small>
102
- </h2>
103
-
104
- <ul class="summary">
105
-
106
- <li class="public ">
107
- <span class="summary_signature">
108
-
109
- <a href="top-level-namespace.html#filename-instance_method" title="#filename (instance method)">#<strong>filename</strong> &#x21d2; Object </a>
110
-
111
-
112
-
113
- </span>
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
- <span class="summary_desc"><div class='inline'>
124
- <p>Load all files listed in “/lib/env_parser/types”.</p>
125
- </div></span>
126
-
127
- </li>
128
-
129
-
130
- </ul>
131
-
132
-
133
-
134
98
 
135
- <div id="instance_method_details" class="method_details_list">
136
- <h2>Instance Method Details</h2>
137
-
138
-
139
- <div class="method_details first">
140
- <h3 class="signature first" id="filename-instance_method">
141
-
142
- #<strong>filename</strong> &#x21d2; <tt>Object</tt>
143
-
144
-
145
-
146
-
147
-
148
- </h3><div class="docstring">
149
- <div class="discussion">
150
-
151
- <p>Load all files listed in “/lib/env_parser/types”.</p>
152
-
153
-
154
- </div>
155
- </div>
156
- <div class="tags">
157
-
158
-
159
- </div><table class="source_code">
160
- <tr>
161
- <td>
162
- <pre class="lines">
163
-
164
-
165
- 3</pre>
166
- </td>
167
- <td>
168
- <pre class="code"><span class="info file"># File 'lib/env_parser/types.rb', line 3</span>
169
-
170
- <span class='const'>Dir</span><span class='period'>.</span><span class='id identifier rubyid_glob'>glob</span><span class='lparen'>(</span><span class='const'>File</span><span class='period'>.</span><span class='id identifier rubyid_join'>join</span><span class='lparen'>(</span><span class='id identifier rubyid___dir__'>__dir__</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>types</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>*.rb</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_each'>each</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_filename'>filename</span><span class='op'>|</span> <span class='id identifier rubyid_require_relative'>require_relative</span> <span class='id identifier rubyid_filename'>filename</span> <span class='rbrace'>}</span></pre>
171
- </td>
172
- </tr>
173
- </table>
174
- </div>
175
-
176
- </div>
177
99
 
178
100
  </div>
179
101
 
180
102
  <div id="footer">
181
- Generated on Sat Jan 2 17:31:17 2021 by
182
- <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
183
- 0.9.26 (ruby-2.7.2).
103
+ Generated on Sun Dec 25 19:19:23 2022 by
104
+ <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
+ 0.9.28 (ruby-3.0.4).
184
106
  </div>
185
107
 
186
108
  </div>
data/env_parser.gemspec CHANGED
@@ -1,9 +1,10 @@
1
-
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'env_parser/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
6
+ spec.required_ruby_version = '~> 3.0'
7
+
7
8
  spec.name = 'env_parser'
8
9
  spec.version = EnvParser::VERSION
9
10
  spec.authors = ['Nestor Custodio']
@@ -13,21 +14,20 @@ Gem::Specification.new do |spec|
13
14
  spec.homepage = 'https://github.com/nestor-custodio/env_parser'
14
15
  spec.license = 'MIT'
15
16
 
16
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
- f.match(%r{^(test|spec|features)/})
18
- end
19
- spec.bindir = 'exe'
20
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |filename| filename.start_with? 'test/' }
18
+ spec.executables = []
21
19
  spec.require_paths = ['lib']
22
20
 
23
- spec.add_development_dependency 'bundler', '~> 2.0'
24
- spec.add_development_dependency 'rake'
25
- spec.add_development_dependency 'rspec', '~> 3.0'
26
- spec.add_development_dependency 'rspec_junit_formatter'
27
- spec.add_development_dependency 'rubocop', '1.7'
28
- spec.add_development_dependency 'yard'
21
+ spec.metadata['rubygems_mfa_required'] = 'true'
29
22
 
30
- spec.add_dependency 'activesupport', '>= 5.0.0'
23
+ spec.add_dependency 'activesupport', '>= 6.1.0'
31
24
  spec.add_dependency 'chronic'
32
25
  spec.add_dependency 'chronic_duration'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 2'
28
+ spec.add_development_dependency 'rake'
29
+ spec.add_development_dependency 'rspec', '~> 3'
30
+ spec.add_development_dependency 'rspec_junit_formatter'
31
+ spec.add_development_dependency 'rubocop'
32
+ spec.add_development_dependency 'yard'
33
33
  end
@@ -1,40 +1,40 @@
1
1
  class EnvParser
2
- ## Base error class for EnvParser.
3
- ##
2
+ # Base error class for EnvParser.
3
+ #
4
4
  class Error < ::StandardError
5
5
  end
6
6
 
7
- ## Error class used to indicate a type has already been defined.
8
- ##
7
+ # Error class used to indicate a type has already been defined.
8
+ #
9
9
  class TypeAlreadyDefinedError < Error
10
10
  end
11
11
 
12
- ## Error class used to indicate the requested "as" type has not been defined.
13
- ##
12
+ # Error class used to indicate the requested "as" type has not been defined.
13
+ #
14
14
  class UnknownTypeError < Error
15
15
  end
16
16
 
17
- ## Error class used to indicate value given is not convertible to the requested type.
18
- ##
17
+ # Error class used to indicate value given is not convertible to the requested type.
18
+ #
19
19
  class ValueNotConvertibleError < Error
20
20
  end
21
21
 
22
- ## Error class used to indicate parsed values that do not pass user-validation, either by not
23
- ## being part of the given "from_set" list, or by failing the "validated_by" Proc or yield-block
24
- ## check.
25
- ##
22
+ # Error class used to indicate parsed values that do not pass user-validation, either by not
23
+ # being part of the given "from_set" list, or by failing the "validated_by" Proc or yield-block
24
+ # check.
25
+ #
26
26
  class ValueNotAllowedError < Error
27
27
  end
28
28
 
29
- ## Error class used to indicate a missing auto-registration spec file (used by the "autoregister"
30
- ## feature).
31
- ##
29
+ # Error class used to indicate a missing auto-registration spec file (used by the "autoregister"
30
+ # feature).
31
+ #
32
32
  class AutoregisterFileNotFound < Error
33
33
  end
34
34
 
35
- ## Error class used to indicate an unparseable auto-registration spec (used by the "autoregister"
36
- ## feature).
37
- ##
35
+ # Error class used to indicate an unparseable auto-registration spec (used by the "autoregister"
36
+ # feature).
37
+ #
38
38
  class UnparseableAutoregisterSpec < Error
39
39
  end
40
40
  end
@@ -1,75 +1,75 @@
1
1
  require 'env_parser'
2
2
 
3
- ## The parent module for all EnvParser type definition modules.
4
- ## Exists only for documentation's sake.
5
- ##
3
+ # The parent module for all EnvParser type definition modules.
4
+ # Exists only for documentation's sake.
5
+ #
6
6
  module EnvParser::Types
7
- ## Defines types for primitive classes, adding the following:
8
- ##
9
- ## <table>
10
- ## <tbody>
11
- ## <tr>
12
- ## <th><code>:as</code> value</th>
13
- ## <th>type returned</th>
14
- ## <th>default</th>
15
- ## <th>notes</th>
16
- ## </tr>
17
- ## </tbody>
18
- ## <tbody>
19
- ## <tr>
20
- ## <td>:string</td>
21
- ## <td>String</td>
22
- ## <td><code>''</code></td>
23
- ## <td></td>
24
- ## </tr>
25
- ## <tr>
26
- ## <td>:symbol</td>
27
- ## <td>Symbol</td>
28
- ## <td><code>:''</code></td>
29
- ## <td></td>
30
- ## </tr>
31
- ## <tr>
32
- ## <td>:boolean</td>
33
- ## <td>TrueValue / FalseValue</td>
34
- ## <td><code>false</code></td>
35
- ## <td></td>
36
- ## </tr>
37
- ## <tr>
38
- ## <td>:int / :integer</td>
39
- ## <td>Integer</td>
40
- ## <td><code>0</code></td>
41
- ## <td></td>
42
- ## </tr>
43
- ## <tr>
44
- ## <td>:float / :decimal / :number</td>
45
- ## <td>Float</td>
46
- ## <td><code>0.0</code></td>
47
- ## <td></td>
48
- ## </tr>
49
- ## <tr>
50
- ## <td>:json</td>
51
- ## <td>&lt; depends on JSON given &gt;</td>
52
- ## <td><code>nil</code></td>
53
- ## <td></td>
54
- ## </tr>
55
- ## <tr>
56
- ## <td>:array</td>
57
- ## <td>Array</td>
58
- ## <td><code>[]</code></td>
59
- ## <td></td>
60
- ## </tr>
61
- ## <tr>
62
- ## <td>:hash</td>
63
- ## <td>Hash</td>
64
- ## <td><code>{}</code></td>
65
- ## <td></td>
66
- ## </tr>
67
- ## </tbody>
68
- ## </table>
69
- ##
70
- ## Note JSON is parsed using *quirks-mode* (meaning 'true', '25', and 'null' are all considered
71
- ## valid, parseable JSON).
72
- ##
7
+ # Defines types for primitive classes, adding the following:
8
+ #
9
+ # <table>
10
+ # <tbody>
11
+ # <tr>
12
+ # <th><code>:as</code> value</th>
13
+ # <th>type returned</th>
14
+ # <th>default</th>
15
+ # <th>notes</th>
16
+ # </tr>
17
+ # </tbody>
18
+ # <tbody>
19
+ # <tr>
20
+ # <td>:string</td>
21
+ # <td>String</td>
22
+ # <td><code>''</code></td>
23
+ # <td></td>
24
+ # </tr>
25
+ # <tr>
26
+ # <td>:symbol</td>
27
+ # <td>Symbol</td>
28
+ # <td><code>:''</code></td>
29
+ # <td></td>
30
+ # </tr>
31
+ # <tr>
32
+ # <td>:boolean</td>
33
+ # <td>TrueValue / FalseValue</td>
34
+ # <td><code>false</code></td>
35
+ # <td></td>
36
+ # </tr>
37
+ # <tr>
38
+ # <td>:int / :integer</td>
39
+ # <td>Integer</td>
40
+ # <td><code>0</code></td>
41
+ # <td></td>
42
+ # </tr>
43
+ # <tr>
44
+ # <td>:float / :decimal / :number</td>
45
+ # <td>Float</td>
46
+ # <td><code>0.0</code></td>
47
+ # <td></td>
48
+ # </tr>
49
+ # <tr>
50
+ # <td>:json</td>
51
+ # <td>&lt; depends on JSON given &gt;</td>
52
+ # <td><code>nil</code></td>
53
+ # <td></td>
54
+ # </tr>
55
+ # <tr>
56
+ # <td>:array</td>
57
+ # <td>Array</td>
58
+ # <td><code>[]</code></td>
59
+ # <td></td>
60
+ # </tr>
61
+ # <tr>
62
+ # <td>:hash</td>
63
+ # <td>Hash</td>
64
+ # <td><code>{}</code></td>
65
+ # <td></td>
66
+ # </tr>
67
+ # </tbody>
68
+ # </table>
69
+ #
70
+ # Note JSON is parsed using *quirks-mode* (meaning 'true', '25', and 'null' are all considered
71
+ # valid, parseable JSON).
72
+ #
73
73
  module BaseTypes
74
74
  EnvParser.define_type(:string, if_unset: '') do |value|
75
75
  value
@@ -1,56 +1,56 @@
1
1
  require 'env_parser'
2
2
 
3
- ## The parent module for all EnvParser type definition modules.
4
- ## Exists only for documentation's sake.
5
- ##
3
+ # The parent module for all EnvParser type definition modules.
4
+ # Exists only for documentation's sake.
5
+ #
6
6
  module EnvParser::Types
7
- ## Defines types for date/time-related values, adding the following:
8
- ##
9
- ## <table>
10
- ## <tbody>
11
- ## <tr>
12
- ## <th><code>:as</code> value</th>
13
- ## <th>type returned</th>
14
- ## <th>default</th>
15
- ## <th>notes</th>
16
- ## </tr>
17
- ## </tbody>
18
- ## <tbody>
19
- ## <tr>
20
- ## <td>:date</td>
21
- ## <td>Date</td>
22
- ## <td><code>nil</code></td>
23
- ## <td>
24
- ## A natural language or ISO8601-parseable date.
25
- ## <br />
26
- ## Actual interpretation of the value is handled by the *chronic* gem.
27
- ## </td>
28
- ## </tr>
29
- ## <tr>
30
- ## <td>:time / :datetime</td>
31
- ## <td>Time</td>
32
- ## <td><code>nil</code></td>
33
- ## <td>
34
- ## A natural language or ISO8601-parseable date and time.
35
- ## <br />
36
- ## Actual interpretation of the value is handled by the *chronic* gem.
37
- ## </td>
38
- ## </tr>
39
- ## <tr>
40
- ## <td>:duration</td>
41
- ## <td>Numeric</td>
42
- ## <td><code>nil</code></td>
43
- ## <td>
44
- ## A natural language or ISO8601-parseable period.
45
- ## <br />
46
- ## Value returned is the number of seconds in the given period.
47
- ## <br />
48
- ## Actual interpretation of the value is handled by the *chronic_duration* gem.
49
- ## </td>
50
- ## </tr>
51
- ## </tbody>
52
- ## </table>
53
- ##
7
+ # Defines types for date/time-related values, adding the following:
8
+ #
9
+ # <table>
10
+ # <tbody>
11
+ # <tr>
12
+ # <th><code>:as</code> value</th>
13
+ # <th>type returned</th>
14
+ # <th>default</th>
15
+ # <th>notes</th>
16
+ # </tr>
17
+ # </tbody>
18
+ # <tbody>
19
+ # <tr>
20
+ # <td>:date</td>
21
+ # <td>Date</td>
22
+ # <td><code>nil</code></td>
23
+ # <td>
24
+ # A natural language or ISO8601-parseable date.
25
+ # <br />
26
+ # Actual interpretation of the value is handled by the *chronic* gem.
27
+ # </td>
28
+ # </tr>
29
+ # <tr>
30
+ # <td>:time / :datetime</td>
31
+ # <td>Time</td>
32
+ # <td><code>nil</code></td>
33
+ # <td>
34
+ # A natural language or ISO8601-parseable date and time.
35
+ # <br />
36
+ # Actual interpretation of the value is handled by the *chronic* gem.
37
+ # </td>
38
+ # </tr>
39
+ # <tr>
40
+ # <td>:duration</td>
41
+ # <td>Numeric</td>
42
+ # <td><code>nil</code></td>
43
+ # <td>
44
+ # A natural language or ISO8601-parseable period.
45
+ # <br />
46
+ # Value returned is the number of seconds in the given period.
47
+ # <br />
48
+ # Actual interpretation of the value is handled by the *chronic_duration* gem.
49
+ # </td>
50
+ # </tr>
51
+ # </tbody>
52
+ # </table>
53
+ #
54
54
  module ChronologyTypes
55
55
  EnvParser.define_type(:date, if_unset: nil) do |value|
56
56
  require 'chronic'
@@ -85,10 +85,10 @@ module EnvParser::Types
85
85
  original_raise_setting = ChronicDuration.raise_exceptions
86
86
  ChronicDuration.raise_exceptions = true
87
87
 
88
- ## With `raise_exceptions` set, ChronicDuration will fail on the "P" and "T" in ISO8601
89
- ## periods, so we have to check for and remove them.
90
- ##
91
- iso_period = %r{^\s*P(?:[0-9.]Y)?(?:[0-9.]M)?(?:[0-9.]W)?(?:[0-9.]D)?(?:T(?:[0-9.]H)?(?:[0-9.]M)?(?:[0-9.]S)?)?\s*$} ## rubocop:disable Layout/LineLength
88
+ # With `raise_exceptions` set, ChronicDuration will fail on the "P" and "T" in ISO8601
89
+ # periods, so we have to check for and remove them.
90
+ #
91
+ iso_period = %r{^\s*P(?:[0-9.]Y)?(?:[0-9.]M)?(?:[0-9.]W)?(?:[0-9.]D)?(?:T(?:[0-9.]H)?(?:[0-9.]M)?(?:[0-9.]S)?)?\s*$}
92
92
  value = value.delete 'PT' if value =~ iso_period
93
93
 
94
94
  value = ChronicDuration.parse value, keep_zero: true
@@ -1,56 +1,56 @@
1
1
  require 'env_parser'
2
2
 
3
- ## The parent module for all EnvParser type definition modules.
4
- ## Exists only for documentation's sake.
5
- ##
3
+ # The parent module for all EnvParser type definition modules.
4
+ # Exists only for documentation's sake.
5
+ #
6
6
  module EnvParser::Types
7
- ## Defines types for internet-related values, adding the following:
8
- ##
9
- ## <table>
10
- ## <tbody>
11
- ## <tr>
12
- ## <th><code>:as</code> value</th>
13
- ## <th>type returned</th>
14
- ## <th>default</th>
15
- ## <th>notes</th>
16
- ## </tr>
17
- ## </tbody>
18
- ## <tbody>
19
- ## <tr>
20
- ## <td>:ipv4_address</td>
21
- ## <td>String</td>
22
- ## <td><code>nil</code></td>
23
- ## <td>
24
- ## An IPv4 address in 4-octet dot-decimal notation,
25
- ## <br />
26
- ## with no CIDR or subnet suffix (e.g. <code>'192.168.0.1'</code>).
27
- ## </td>
28
- ## </tr>
29
- ## <tr>
30
- ## <td>:ipv6_address</td>
31
- ## <td>String</td>
32
- ## <td><code>nil</code></td>
33
- ## <td>An IPv6 address, in RFC5952 format.</td>
34
- ## </tr>
35
- ## <tr>
36
- ## <td>:network_port / :port</td>
37
- ## <td>Integer</td>
38
- ## <td><code>nil</code></td>
39
- ## <td></td>
40
- ## </tr>
41
- ## <tr>
42
- ## <td>:email_address</td>
43
- ## <td>String</td>
44
- ## <td><code>nil</code></td>
45
- ## <td>
46
- ## A "simple" email address, containing only a username and a domain.
47
- ## <br />
48
- ## Note this does not guarantee RFC5322-conformity.
49
- ## </td>
50
- ## </tr>
51
- ## </tbody>
52
- ## </table>
53
- ##
7
+ # Defines types for internet-related values, adding the following:
8
+ #
9
+ # <table>
10
+ # <tbody>
11
+ # <tr>
12
+ # <th><code>:as</code> value</th>
13
+ # <th>type returned</th>
14
+ # <th>default</th>
15
+ # <th>notes</th>
16
+ # </tr>
17
+ # </tbody>
18
+ # <tbody>
19
+ # <tr>
20
+ # <td>:ipv4_address</td>
21
+ # <td>String</td>
22
+ # <td><code>nil</code></td>
23
+ # <td>
24
+ # An IPv4 address in 4-octet dot-decimal notation,
25
+ # <br />
26
+ # with no CIDR or subnet suffix (e.g. <code>'192.168.0.1'</code>).
27
+ # </td>
28
+ # </tr>
29
+ # <tr>
30
+ # <td>:ipv6_address</td>
31
+ # <td>String</td>
32
+ # <td><code>nil</code></td>
33
+ # <td>An IPv6 address, in RFC5952 format.</td>
34
+ # </tr>
35
+ # <tr>
36
+ # <td>:network_port / :port</td>
37
+ # <td>Integer</td>
38
+ # <td><code>nil</code></td>
39
+ # <td></td>
40
+ # </tr>
41
+ # <tr>
42
+ # <td>:email_address</td>
43
+ # <td>String</td>
44
+ # <td><code>nil</code></td>
45
+ # <td>
46
+ # A "simple" email address, containing only a username and a domain.
47
+ # <br />
48
+ # Note this does not guarantee RFC5322-conformity.
49
+ # </td>
50
+ # </tr>
51
+ # </tbody>
52
+ # </table>
53
+ #
54
54
  module InternetTypes
55
55
  EnvParser.define_type(:ipv4_address, if_unset: nil) do |value|
56
56
  begin
@@ -1,3 +1,3 @@
1
- ## Load all files listed in "/lib/env_parser/types".
2
- ##
1
+ # Load all files listed in "/lib/env_parser/types".
2
+ #
3
3
  Dir.glob(File.join(__dir__, 'types', '*.rb')).each { |filename| require_relative filename }
@@ -1,3 +1,3 @@
1
1
  class EnvParser
2
- VERSION = '1.3.1'.freeze
2
+ VERSION = '1.3.2'.freeze
3
3
  end