teak_util 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ed306a1c0d8b1bd16fad11431b1d0ed8506ff01fbb536c5db9e1562ec12c096
4
- data.tar.gz: 83ee0167f13ab63f51588a63f2f60246bde93032ad6798f8a78b29c0c7872470
3
+ metadata.gz: 0023eb85ea20bc79474e541424ce8b3fef9a1977d0604e78989b9a6a99ee712c
4
+ data.tar.gz: a8e891a6bc814694f72ddeba1bae0eb98168a91752e6a19462eb77180dc60947
5
5
  SHA512:
6
- metadata.gz: 2b6d30e4e71b5a4b386ea1a6327df0ae877b4c1975d3976e912d37e05b5a4a23c0222a0c5a892c9feb6e6d189a049e6d12da228fe4a23cd9bc634a8c6e576d3e
7
- data.tar.gz: 558b5223f4600b4e9405f545c8aea2de3c373c6cb4266546f8cd72beb6c44d238e4419df21b171c0caaae468e1b57758aaa2934db967a95c20d3b368deaf03a6
6
+ metadata.gz: d768f5de6e1f4d97b1446c4ccdff31b19f28ae1e4f31e7ea717065e84a22a277c1598803b3040753af9b3d06d207f75276437fea996feefe60816a01ce321c1d
7
+ data.tar.gz: 1bb68a45ec634666aff5aca0b0736e91b4e94f3819b0ccef9606249b711f34500f5a76b392f83195f11812607c214f709dd724f5923c089fa9f9c8d9f7d7f966
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ .claude/settings.local.json
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.4.0
2
+
3
+ ENHANCEMENTS:
4
+
5
+ * Added TeakUtil::DecimalJson (`wire` / `dump`) to write BigDecimal as an exact, bare
6
+ plain-notation JSON number through JSON.generate, ActiveSupport and Oj (compat).
7
+ Whole values become integers; NaN and Infinity raise.
8
+
1
9
  ## 0.3.0
2
10
 
3
11
  ENHANCEMENTS:
data/Gemfile CHANGED
@@ -15,3 +15,4 @@ gem 'simplecov', '~> 0.22.0'
15
15
  gem 'rspec_junit_formatter'
16
16
 
17
17
  gem "nokogiri", "~> 1.18"
18
+ gem "oj", "~> 3.16"
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- teak_util (0.3.0)
4
+ teak_util (0.4.0)
5
5
  aws-sdk-s3 (>= 1.102)
6
+ bigdecimal
6
7
  business_flow (>= 0.18.0)
7
8
  mime-types (>= 3)
8
9
  rubyzip (>= 2.3, < 4.0)
@@ -68,6 +69,8 @@ GEM
68
69
  nokogiri (1.18.10)
69
70
  mini_portile2 (~> 2.8.2)
70
71
  racc (~> 1.4)
72
+ oj (3.17.8)
73
+ bigdecimal (>= 3.0)
71
74
  racc (1.8.1)
72
75
  rake (13.3.0)
73
76
  rspec (3.13.1)
@@ -103,6 +106,7 @@ PLATFORMS
103
106
 
104
107
  DEPENDENCIES
105
108
  nokogiri (~> 1.18)
109
+ oj (~> 3.16)
106
110
  rake (~> 13.0)
107
111
  rspec (~> 3.0)
108
112
  rspec_junit_formatter
data/README.md CHANGED
@@ -30,6 +30,14 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
30
30
 
31
31
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
32
 
33
+ ### Worktrees
34
+
35
+ `script/worktree` defaults to a path sibling to this checkout. This repo's main
36
+ checkout doesn't live under `services/`, so pass an explicit path under
37
+ `services/` when creating a worktree — `services/.claude/rules/` (gates,
38
+ shared-trees, stating-evidence) only loads by walking up from there, and the
39
+ default path lands outside it.
40
+
33
41
  ## Contributing
34
42
 
35
43
  Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/teak_util.
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bigdecimal'
4
+ require 'json'
5
+
6
+ module TeakUtil
7
+ # Writes BigDecimal as an exact, bare JSON number. ActiveSupport and Oj (compat) both
8
+ # encode a BigDecimal as a quoted string, and Float isn't exact at nine decimal places
9
+ # next to a large integer part, so nothing in here goes through Float.
10
+ #
11
+ # TeakUtil::DecimalJson.dump({ 'qty' => BigDecimal('0.000000001') })
12
+ # # => '{"qty":0.000000001}'
13
+ #
14
+ # Whole values become Integers, so 5 and 5.0 sign and serialize identically. Fractional
15
+ # values become a Fractional, which JSON.generate, ActiveSupport's to_json and Oj
16
+ # (compat, use_to_json) all write as plain-notation digits, never "0.123e18" or quoted.
17
+ module DecimalJson
18
+ # A fractional decimal that every JSON encoder in the stack writes as a bare number.
19
+ # `as_json` returns self so ActiveSupport's recursive `as_json` leaves it alone, and
20
+ # `to_json` is what the JSON gem and Oj (compat) call to emit the raw digits.
21
+ # JSON output only: use the BigDecimal (`decimal`) for anything else.
22
+ class Fractional < Numeric
23
+ attr_reader :decimal
24
+
25
+ def initialize(decimal)
26
+ super()
27
+ @decimal = decimal
28
+ end
29
+
30
+ def to_s(*)
31
+ @decimal.to_s('F')
32
+ end
33
+
34
+ def to_json(*)
35
+ to_s
36
+ end
37
+
38
+ def as_json(*)
39
+ self
40
+ end
41
+ end
42
+
43
+ # Returns a copy of the Hash/Array tree with every BigDecimal replaced by something
44
+ # the encoders write as a bare number. Hash keys and non-BigDecimal values are left
45
+ # alone. Raises ArgumentError for NaN and Infinity, which have no JSON form.
46
+ def self.wire(value)
47
+ case value
48
+ when BigDecimal then wire_decimal(value)
49
+ when Hash then value.transform_values { |v| wire(v) }
50
+ when Array then value.map { |v| wire(v) }
51
+ else value
52
+ end
53
+ end
54
+
55
+ # JSON text for the tree, with BigDecimal values written as bare numbers.
56
+ def self.dump(value)
57
+ JSON.generate(wire(value))
58
+ end
59
+
60
+ def self.wire_decimal(decimal)
61
+ raise ArgumentError, "Decimal must be finite, got #{decimal}" unless decimal.finite?
62
+
63
+ decimal.frac.zero? ? decimal.to_i : Fractional.new(decimal)
64
+ end
65
+ private_class_method :wire_decimal
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TeakUtil
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/teak_util.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "teak_util/version"
4
+ require_relative "teak_util/decimal_json"
4
5
 
5
6
  module TeakUtil
6
7
  class Error < StandardError; end
data/teak_util.gemspec CHANGED
@@ -23,13 +23,14 @@ Gem::Specification.new do |spec|
23
23
  # Specify which files should be added to the gem when it is released.
24
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
25
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features|\.claude|script)/}) }
27
27
  end
28
28
  spec.bindir = "exe"
29
29
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ["lib"]
31
31
 
32
32
  spec.add_dependency "aws-sdk-s3", ">= 1.102"
33
+ spec.add_dependency "bigdecimal"
33
34
  spec.add_dependency "business_flow", ">= 0.18.0"
34
35
  spec.add_dependency "mime-types", ">= 3"
35
36
  spec.add_dependency "rubyzip", ">= 2.3", "< 4.0"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teak_util
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Scarborough
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '1.102'
26
+ - !ruby/object:Gem::Dependency
27
+ name: bigdecimal
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: business_flow
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -92,6 +106,7 @@ files:
92
106
  - bin/console
93
107
  - bin/setup
94
108
  - lib/teak_util.rb
109
+ - lib/teak_util/decimal_json.rb
95
110
  - lib/teak_util/storage/make_externally_available_file.rb
96
111
  - lib/teak_util/storage/s3.rb
97
112
  - lib/teak_util/test_database_name.rb