emery 0.0.3 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 629dad4de96ce6b80b94e883ac9dee5dff07c677d431727e83a7c379c229524b
4
- data.tar.gz: 3dc8b2cc93ff053470be638ca64659f02de7c7f07894427212c603b3f36a8ad0
3
+ metadata.gz: bda1937694f9f1e76788bdab5f20ff4d80ba41be117cf324850f36c73ee875d0
4
+ data.tar.gz: 50e1a054e8882b8c0f2d62b0a860a2ec9d286056f4b5c08e81f33bce76795b68
5
5
  SHA512:
6
- metadata.gz: fed3812431f78ab7bb66066c19c788babe478675a1108ef038c237a2e47734dce7e572b53d3d781430da4d72eb4e4c29ab36f0cf80721395d3d971acaa6be83d
7
- data.tar.gz: 9dfc4c611a1da41452861b565c7a4042a1ea8f685ebc79d87a6186fabc0cf96ba1e005a5c6e4617a50d22619799eb46e49c42238d348f6687d8b80cacd47f661
6
+ metadata.gz: d785c11bd404df22387441c72715ead3087a62bd7e01700e8204a5ad415519a00227ff0f01973688c6acd935aa6b37c68b64d1862eb09a27e7da1576334b1f0d
7
+ data.tar.gz: 8943ebbf92cd0e94a8ef479f893cda0bb6e9af7e11c8af4167130afbf12fbcd75e39b63c56c5ca0633d8562e29b33bf0590d7225c1a9403f2108f60ade0c485c
data/lib/emery.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'emery/tod'
2
1
  require 'emery/type'
3
2
  require 'emery/jsoner'
4
3
  require 'emery/enum'
@@ -39,6 +39,10 @@ module DataClass
39
39
  return self.class.new(new_params)
40
40
  end
41
41
 
42
+ def to_json
43
+ return Jsoner.serialize(self.class, self)
44
+ end
45
+
42
46
  def self.included(base)
43
47
  base.extend ClassMethods
44
48
  end
data/lib/emery/jsoner.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  require "json"
2
2
  require "date"
3
3
 
4
- require "emery/type"
5
-
6
4
  class JsonerError < StandardError
7
5
  end
8
6
 
@@ -16,6 +14,15 @@ module Jsoner
16
14
  end
17
15
  end
18
16
 
17
+ T::UntypedType.class_eval do
18
+ def jsoner_deserialize(json_value)
19
+ json_value
20
+ end
21
+ def jsoner_serialize(value)
22
+ value
23
+ end
24
+ end
25
+
19
26
  T::ArrayType.class_eval do
20
27
  def jsoner_deserialize(json_value)
21
28
  T.check_not_nil(self, json_value)
@@ -63,7 +70,7 @@ module Jsoner
63
70
  types.each do |type|
64
71
  begin
65
72
  return Jsoner.deserialize(type, json_value)
66
- rescue TypeError
73
+ rescue JsonerError
67
74
  end
68
75
  end
69
76
  raise JsonerError.new("Value '#{json_value.inspect.to_s}' can not be deserialized as any of #{@types.map { |t| t.to_s}.join(', ')}")
@@ -208,4 +215,4 @@ module Jsoner
208
215
  raise JsonerError.new(error.message)
209
216
  end
210
217
  end
211
- end
218
+ end
data/test/jsoner_test.rb CHANGED
@@ -33,10 +33,16 @@ class PlainTypesDeserialization < Test::Unit::TestCase
33
33
  end
34
34
  end
35
35
 
36
- def test_deserialize_boolean
36
+ def test_deserialize_true
37
37
  data = Jsoner.from_json(Boolean, 'true')
38
38
  T.check(Boolean, data)
39
- assert_equal true, data, "Boolean should be parsable from JSON"
39
+ assert_equal true, data, "Boolean true should be parsable from JSON"
40
+ end
41
+
42
+ def test_deserialize_false
43
+ data = Jsoner.from_json(Boolean, 'false')
44
+ T.check(Boolean, data)
45
+ assert_equal false, data, "Boolean false should be parsable from JSON"
40
46
  end
41
47
 
42
48
  def test_deserialize_boolean_fail
@@ -213,6 +219,28 @@ class HashSerialization < Test::Unit::TestCase
213
219
  end
214
220
  end
215
221
 
222
+ class UntypedDeserialization < Test::Unit::TestCase
223
+ def test_deserialize_hash
224
+ data = Jsoner.from_json(Untyped, '{"one":123,"two":"some string"}')
225
+ assert_equal ({"one" => 123, "two" => "some string"}), data
226
+ end
227
+
228
+ def test_deserialize_array
229
+ data = Jsoner.from_json(Untyped, '[123,"some string"]')
230
+ assert_equal [123, "some string"], data
231
+ end
232
+ end
233
+
234
+ class UntypedSerialization < Test::Unit::TestCase
235
+ def test_serialize_hash
236
+ assert_equal '{"one":123,"two":"some string"}', Jsoner.to_json(Untyped, {"one" => 123, "two" => "some string"})
237
+ end
238
+
239
+ def test_serialize_array
240
+ assert_equal '[123,"some string"]', Jsoner.to_json(Untyped, [123, "some string"])
241
+ end
242
+ end
243
+
216
244
  class AnyDeserialization < Test::Unit::TestCase
217
245
  def test_deserialize
218
246
  data = Jsoner.from_json(T.any(String, Integer), '"the string"')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Sapronov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-26 00:00:00.000000000 Z
11
+ date: 2021-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -34,12 +34,10 @@ files:
34
34
  - lib/emery/dataclass.rb
35
35
  - lib/emery/enum.rb
36
36
  - lib/emery/jsoner.rb
37
- - lib/emery/tod.rb
38
37
  - lib/emery/type.rb
39
38
  - test/dataclass_test.rb
40
39
  - test/enum_test.rb
41
40
  - test/jsoner_test.rb
42
- - test/tod_test.rb
43
41
  - test/type_test.rb
44
42
  homepage: https://github.com/vsapronov/emery
45
43
  licenses:
data/lib/emery/tod.rb DELETED
@@ -1,260 +0,0 @@
1
- =begin
2
-
3
- source: https://github.com/jackc/tod
4
-
5
- Copyright (c) 2010-2015 Jack Christensen
6
-
7
- Permission is hereby granted, free of charge, to any person obtaining
8
- a copy of this software and associated documentation files (the
9
- "Software"), to deal in the Software without restriction, including
10
- without limitation the rights to use, copy, modify, merge, publish,
11
- distribute, sublicense, and/or sell copies of the Software, and to
12
- permit persons to whom the Software is furnished to do so, subject to
13
- the following conditions:
14
-
15
- The above copyright notice and this permission notice shall be
16
- included in all copies or substantial portions of the Software.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
-
26
- =end
27
-
28
- class TimeOfDay
29
- include Comparable
30
-
31
- def self.jsoner_deserialize(json_value)
32
- TimeOfDay.parse(T.check(String, json_value))
33
- end
34
- def self.jsoner_serialize(value)
35
- T.check(TimeOfDay, value).to_s
36
- end
37
-
38
- attr_reader :hour, :minute, :second, :second_of_day
39
- alias_method :min, :minute
40
- alias_method :sec, :second
41
- alias_method :to_i, :second_of_day
42
-
43
- PARSE_24H_REGEX = /
44
- \A
45
- ([01]?\d|2[0-4])
46
- :?
47
- ([0-5]\d)?
48
- :?
49
- ([0-5]\d)?
50
- \z
51
- /x
52
-
53
- PARSE_12H_REGEX = /
54
- \A
55
- (0?\d|1[0-2])
56
- :?
57
- ([0-5]\d)?
58
- :?
59
- ([0-5]\d)?
60
- \s*
61
- ([ap])
62
- \.?
63
- \s*
64
- m?
65
- \.?
66
- \z
67
- /x
68
-
69
- WORDS = {
70
- "noon" => "12pm".freeze,
71
- "midnight" => "12am".freeze
72
- }
73
-
74
- NUM_SECONDS_IN_DAY = 86400
75
- NUM_SECONDS_IN_HOUR = 3600
76
- NUM_SECONDS_IN_MINUTE = 60
77
-
78
- FORMATS = {
79
- short: "%-l:%M %P".freeze,
80
- medium: "%-l:%M:%S %P".freeze,
81
- time: "%H:%M".freeze
82
- }
83
-
84
- def initialize(h, m=0, s=0)
85
- @hour = Integer(h)
86
- @minute = Integer(m)
87
- @second = Integer(s)
88
-
89
- raise ArgumentError, "hour must be between 0 and 24" unless (0..24).include?(@hour)
90
- if @hour == 24 && (@minute != 0 || @second != 0)
91
- raise ArgumentError, "hour can only be 24 when minute and second are 0"
92
- end
93
- raise ArgumentError, "minute must be between 0 and 59" unless (0..59).include?(@minute)
94
- raise ArgumentError, "second must be between 0 and 59" unless (0..59).include?(@second)
95
-
96
- @second_of_day = @hour * 60 * 60 + @minute * 60 + @second
97
-
98
- freeze # TimeOfDay instances are value objects
99
- end
100
-
101
- def <=>(other)
102
- return unless other.respond_to?(:second_of_day)
103
- @second_of_day <=> other.second_of_day
104
- end
105
-
106
- # Rounding to the given nearest number of seconds
107
- def round(round_sec = 1)
108
- down = self - (self.to_i % round_sec)
109
- up = down + round_sec
110
-
111
- difference_down = self - down
112
- difference_up = up - self
113
-
114
- if (difference_down < difference_up)
115
- return down
116
- else
117
- return up
118
- end
119
- end
120
-
121
- # Formats identically to Time#strftime
122
- def strftime(format_string)
123
- # Special case 2400 because strftime will load TimeOfDay into Time which
124
- # will convert 24 to 0
125
- format_string = format_string.gsub(/%H|%k/, '24') if @hour == 24
126
- Time.local(2000,1,1, @hour, @minute, @second).strftime(format_string)
127
- end
128
-
129
- def to_formatted_s(format = :default)
130
- if formatter = FORMATS[format]
131
- if formatter.respond_to?(:call)
132
- formatter.call(self).to_s
133
- else
134
- strftime(formatter)
135
- end
136
- else
137
- strftime "%H:%M:%S"
138
- end
139
- end
140
- alias_method :to_s, :to_formatted_s
141
-
142
- def value_for_database
143
- to_s
144
- end
145
-
146
- # Return a new TimeOfDay num_seconds greater than self. It will wrap around
147
- # at midnight.
148
- def +(num_seconds)
149
- TimeOfDay.from_second_of_day @second_of_day + num_seconds
150
- end
151
-
152
- # Return a new TimeOfDay num_seconds less than self. It will wrap around
153
- # at midnight.
154
- def -(other)
155
- if other.instance_of?(TimeOfDay)
156
- TimeOfDay.from_second_of_day @second_of_day - other.second_of_day
157
- else
158
- TimeOfDay.from_second_of_day @second_of_day - other
159
- end
160
- end
161
-
162
- # Returns a Time instance on date using self as the time of day
163
- # Optional time_zone will build time in that zone
164
- def on(date, time_zone=Tod::TimeOfDay.time_zone)
165
- time_zone.local date.year, date.month, date.day, @hour, @minute, @second
166
- end
167
-
168
- # Build a new TimeOfDay instance from second_of_day
169
- #
170
- # TimeOfDay.from_second_of_day(3600) == TimeOfDay.new(1) # => true
171
- def self.from_second_of_day(second_of_day)
172
- second_of_day = Integer(second_of_day)
173
- return new 24 if second_of_day == NUM_SECONDS_IN_DAY
174
- remaining_seconds = second_of_day % NUM_SECONDS_IN_DAY
175
- hour = remaining_seconds / NUM_SECONDS_IN_HOUR
176
- remaining_seconds -= hour * NUM_SECONDS_IN_HOUR
177
- minute = remaining_seconds / NUM_SECONDS_IN_MINUTE
178
- remaining_seconds -= minute * NUM_SECONDS_IN_MINUTE
179
- new hour, minute, remaining_seconds
180
- end
181
- class << self
182
- alias :from_i :from_second_of_day
183
- end
184
-
185
- # Build a TimeOfDay instance from string
186
- #
187
- # Strings only need to contain an hour. Minutes, seconds, AM or PM, and colons
188
- # are all optional.
189
- # TimeOfDay.parse "8" # => 08:00:00
190
- # TimeOfDay.parse "8am" # => 08:00:00
191
- # TimeOfDay.parse "8pm" # => 20:00:00
192
- # TimeOfDay.parse "8p" # => 20:00:00
193
- # TimeOfDay.parse "9:30" # => 09:30:00
194
- # TimeOfDay.parse "15:30" # => 15:30:00
195
- # TimeOfDay.parse "3:30pm" # => 15:30:00
196
- # TimeOfDay.parse "1230" # => 12:30:00
197
- # TimeOfDay.parse "3:25:58" # => 03:25:58
198
- # TimeOfDay.parse "515p" # => 17:15:00
199
- # TimeOfDay.parse "151253" # => 15:12:53
200
- # You can give a block, that is called with the input if the string is not parsable.
201
- # If no block is given an ArgumentError is raised if try_parse returns nil.
202
- def self.parse(tod_string)
203
- try_parse(tod_string) || (block_given? ? yield(tod_string) : raise(ArgumentError, "Invalid time of day string"))
204
- end
205
-
206
- # Same as parse(), but return nil if not parsable (instead of raising an error)
207
- # TimeOfDay.try_parse "8am" # => 08:00:00
208
- # TimeOfDay.try_parse "" # => nil
209
- # TimeOfDay.try_parse "abc" # => nil
210
- def self.try_parse(tod_string)
211
- tod_string = tod_string.to_s
212
- tod_string = tod_string.strip
213
- tod_string = tod_string.downcase
214
- tod_string = WORDS[tod_string] || tod_string
215
- if PARSE_24H_REGEX =~ tod_string || PARSE_12H_REGEX =~ tod_string
216
- hour, minute, second, a_or_p = $1.to_i, $2.to_i, $3.to_i, $4
217
- if hour == 12 && a_or_p == "a"
218
- hour = 0
219
- elsif hour < 12 && a_or_p == "p"
220
- hour += 12
221
- end
222
-
223
- new hour, minute, second
224
- else
225
- nil
226
- end
227
- end
228
-
229
- # Determine if a string is parsable into a TimeOfDay instance
230
- # TimeOfDay.parsable? "8am" # => true
231
- # TimeOfDay.parsable? "abc" # => false
232
- def self.parsable?(tod_string)
233
- !!try_parse(tod_string)
234
- end
235
-
236
- # If ActiveSupport TimeZone is available and set use current time zone else return Time
237
- def self.time_zone
238
- (Time.respond_to?(:zone) && Time.zone) || Time
239
- end
240
-
241
- def self.dump(time_of_day)
242
- time_of_day =
243
- if time_of_day.is_a? Hash
244
- # rails multiparam attribute
245
- # get hour, minute and second and construct new TimeOfDay object
246
- ::Tod::TimeOfDay.new(time_of_day[4], time_of_day[5], time_of_day[6])
247
- else
248
- # return nil, if input is not parsable
249
- Tod::TimeOfDay(time_of_day){}
250
- end
251
- time_of_day.to_s if time_of_day
252
- end
253
-
254
- def self.load(time)
255
- if time && !time.to_s.empty?
256
- return ::Tod::TimeOfDay.new(24) if time.respond_to?(:day) && time.day == 2 && time.hour == 0 && time.min == 0 && time.sec == 0
257
- ::Tod::TimeOfDay(time)
258
- end
259
- end
260
- end
data/test/tod_test.rb DELETED
@@ -1,36 +0,0 @@
1
- require "test/unit/runner/junitxml"
2
-
3
- require 'emery'
4
-
5
- class TypeCheckTimeOfDay < Test::Unit::TestCase
6
- def test_success
7
- assert_equal TimeOfDay.parse("10:40:50"), T.check(TimeOfDay, TimeOfDay.parse("10:40:50"))
8
- end
9
-
10
- def test_fail
11
- assert_raise TypeError do
12
- T.check(DateTime, TimeOfDay.parse("10:40:50"))
13
- end
14
- end
15
- end
16
-
17
- class TimeOfDayDeserialization < Test::Unit::TestCase
18
- def test_deserialize
19
- data = Jsoner.from_json(TimeOfDay, '"10:40:50"')
20
- T.check(TimeOfDay, data)
21
- assert_equal TimeOfDay.parse("10:40:50"), data
22
- end
23
-
24
- def test_deserialize_fail
25
- assert_raise JsonerError do
26
- Jsoner.from_json(TimeOfDay, '"abc"')
27
- end
28
- end
29
- end
30
-
31
- class TimeOfDaySerialization < Test::Unit::TestCase
32
- def test_serialize
33
- json_str = Jsoner.to_json(TimeOfDay, TimeOfDay.parse("10:40:50"))
34
- assert_equal '"10:40:50"', json_str
35
- end
36
- end