From cde394ed8b80a1897d0fe6d1dc3edf66dc0e5b76 Mon Sep 17 00:00:00 2001 From: Dalen Ward Date: Sat, 13 May 2023 13:54:50 -0600 Subject: [PATCH 1/6] add gems --- .gitignore | 2 ++ manifest.yml | 6 +++++ money.gemspec | 2 ++ rbs_collection.lock.yaml | 58 ++++++++++++++++++++++++++++++++++++++++ rbs_collection.yaml | 20 ++++++++++++++ 5 files changed, 88 insertions(+) create mode 100644 manifest.yml create mode 100644 rbs_collection.lock.yaml create mode 100644 rbs_collection.yaml diff --git a/.gitignore b/.gitignore index 09ec4ac3e9..aec7be89ab 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ doc/ # Spec artifacts /coverage +.gem_rbs_collection +.idea diff --git a/manifest.yml b/manifest.yml new file mode 100644 index 0000000000..4f635ae7a6 --- /dev/null +++ b/manifest.yml @@ -0,0 +1,6 @@ +# manifest.yaml + +dependencies: + # If your gem depends on pathname but the gemspec doesn't include pathname, + # you need to write the following. + # - name: pathname \ No newline at end of file diff --git a/money.gemspec b/money.gemspec index 4edaa800a9..6dd191b36f 100644 --- a/money.gemspec +++ b/money.gemspec @@ -21,6 +21,8 @@ Gem::Specification.new do |s| s.add_development_dependency "rspec", "~> 3.4" s.add_development_dependency "yard", "~> 0.9.11" s.add_development_dependency "kramdown", "~> 2.3" + s.add_development_dependency "rbs" if RUBY_VERSION >= "2.7.0" + s.add_development_dependency "typeprof" if RUBY_VERSION >= "2.7.0" s.files = `git ls-files -z -- config/* lib/* CHANGELOG.md LICENSE money.gemspec README.md`.split("\x0") s.require_paths = ["lib"] diff --git a/rbs_collection.lock.yaml b/rbs_collection.lock.yaml new file mode 100644 index 0000000000..7f8648345b --- /dev/null +++ b/rbs_collection.lock.yaml @@ -0,0 +1,58 @@ +--- +sources: +- type: git + name: ruby/gem_rbs_collection + revision: d0d7aeed98fa74427b30b336fc402ea86d526f35 + remote: https://github.com/ruby/gem_rbs_collection.git + repo_dir: gems +path: ".gem_rbs_collection" +gems: +- name: cgi + version: '0' + source: + type: stdlib +- name: concurrent-ruby + version: '1.1' + source: + type: git + name: ruby/gem_rbs_collection + revision: d0d7aeed98fa74427b30b336fc402ea86d526f35 + remote: https://github.com/ruby/gem_rbs_collection.git + repo_dir: gems +- name: i18n + version: '1.10' + source: + type: git + name: ruby/gem_rbs_collection + revision: d0d7aeed98fa74427b30b336fc402ea86d526f35 + remote: https://github.com/ruby/gem_rbs_collection.git + repo_dir: gems +- name: logger + version: '0' + source: + type: stdlib +- name: monitor + version: '0' + source: + type: stdlib +- name: optparse + version: '0' + source: + type: stdlib +- name: tempfile + version: '0' + source: + type: stdlib +- name: uri + version: '0' + source: + type: stdlib +- name: yard + version: '0.9' + source: + type: git + name: ruby/gem_rbs_collection + revision: d0d7aeed98fa74427b30b336fc402ea86d526f35 + remote: https://github.com/ruby/gem_rbs_collection.git + repo_dir: gems +gemfile_lock_path: Gemfile.lock diff --git a/rbs_collection.yaml b/rbs_collection.yaml new file mode 100644 index 0000000000..0016e57f2d --- /dev/null +++ b/rbs_collection.yaml @@ -0,0 +1,20 @@ +# Download sources +sources: + - type: git + name: ruby/gem_rbs_collection + remote: https://github.com/ruby/gem_rbs_collection.git + revision: main + repo_dir: gems + +# You can specify local directories as sources also. +# - type: local +# path: path/to/your/local/repository + +# A directory to install the downloaded RBSs +path: .gem_rbs_collection + +gems: + # Skip loading rbs gem's RBS. + # It's unnecessary if you don't use rbs as a library. + - name: rbs + ignore: true From 761a21ba7e80ca3b2070f9be135e932ee948ab14 Mon Sep 17 00:00:00 2001 From: Dalen Ward Date: Sat, 13 May 2023 13:55:01 -0600 Subject: [PATCH 2/6] money and currency --- sig/lib/money/currency.rbs | 309 +++++++++++++++++++++ sig/lib/money/money.rbs | 540 +++++++++++++++++++++++++++++++++++++ 2 files changed, 849 insertions(+) create mode 100644 sig/lib/money/currency.rbs create mode 100644 sig/lib/money/money.rbs diff --git a/sig/lib/money/currency.rbs b/sig/lib/money/currency.rbs new file mode 100644 index 0000000000..ed85c8279f --- /dev/null +++ b/sig/lib/money/currency.rbs @@ -0,0 +1,309 @@ +class Money + # Represents a specific currency unit. + # + # @see https://en.wikipedia.org/wiki/Currency + # @see http://iso4217.net/ + class Currency + include Comparable + + extend Enumerable + + extend Money::Currency::Heuristics + + # Thrown when a Currency has been registered without all the attributes + # which are required for the current action. + class MissingAttributeError < StandardError + def initialize: (untyped method, untyped currency, untyped attribute) -> void + end + + # Thrown when an unknown currency is requested. + class UnknownCurrency < ArgumentError + end + + def self.new: (untyped id) -> untyped + + def self._instances: () -> untyped + + # Lookup a currency with given +id+ an returns a +Currency+ instance on + # success, +nil+ otherwise. + # + # @param [String, Symbol, #to_s] id Used to look into +table+ and + # retrieve the applicable attributes. + # + # @return [Money::Currency] + # + # @example + # Money::Currency.find(:eur) #=> # + # Money::Currency.find(:foo) #=> nil + def self.find: ((string | Symbol) id) -> Currency + + # Lookup a currency with given +num+ as an ISO 4217 numeric and returns an + # +Currency+ instance on success, +nil+ otherwise. + # + # @param [#to_s] num used to look into +table+ in +iso_numeric+ and find + # the right currency id. + # + # @return [Money::Currency] + # + # @example + # Money::Currency.find_by_iso_numeric(978) #=> # + # Money::Currency.find_by_iso_numeric(51) #=> # + # Money::Currency.find_by_iso_numeric('001') #=> nil + def self.find_by_iso_numeric: ((string | Numeric) num) -> Currency + + # Wraps the object in a +Currency+ unless it's already a +Currency+ + # object. + # + # @param [Object] object The object to attempt and wrap as a +Currency+ + # object. + # + # @return [Money::Currency] + # + # @example + # c1 = Money::Currency.new(:usd) + # Money::Currency.wrap(nil) #=> nil + # Money::Currency.wrap(c1) #=> # + # Money::Currency.wrap("usd") #=> # + def self.wrap: (Object object) -> (nil | Currency) + + # List of known currencies. + # + # == monetary unit + # The standard unit of value of a currency, as the dollar in the United States or the peso in Mexico. + # https://www.answers.com/topic/monetary-unit + # == fractional monetary unit, subunit + # A monetary unit that is valued at a fraction (usually one hundredth) of the basic monetary unit + # https://www.answers.com/topic/fractional-monetary-unit-subunit + # + # See https://en.wikipedia.org/wiki/List_of_circulating_currencies and + # http://search.cpan.org/~tnguyen/Locale-Currency-Format-1.28/Format.pm + def self.table: () -> untyped + + # List the currencies imported and registered + # @return [Array] + # + # @example + # Money::Currency.all() + # [#, 'CAD', 'EUR']... + def self.all: () -> Array[untyped] + + # We need a string-based validator before creating an unbounded number of + # symbols. + # http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol#11 + # https://github.com/RubyMoney/money/issues/132 + # + # @return [Set] + def self.stringified_keys: () -> untyped + + # Register a new currency + # + # @param curr [Hash] information about the currency + # @option priority [Numeric] a numerical value you can use to sort/group + # the currency list + # @option iso_code [String] the international 3-letter code as defined + # by the ISO 4217 standard + # @option iso_numeric [Integer] the international 3-digit code as + # defined by the ISO 4217 standard + # @option name [String] the currency name + # @option symbol [String] the currency symbol (UTF-8 encoded) + # @option subunit [String] the name of the fractional monetary unit + # @option subunit_to_unit [Numeric] the proportion between the unit and + # the subunit + # @option separator [String] character between the whole and fraction + # amounts + # @option delimiter [String] character between each thousands place + def self.register: (Hash[untyped, untyped] curr) -> Currency + + # Inherit a new currency from existing one + # + # @param parent_iso_code [String] the international 3-letter code as defined + # @param curr [Hash] See {register} method for hash structure + def self.inherit: (string parent_iso_code, Hash[untyped, untyped] curr) -> untyped + + # Unregister a currency. + # + # @param [Object] curr A Hash with the key `:iso_code`, or the ISO code + # as a String or Symbol. + # + # @return [Boolean] true if the currency previously existed, false + # if it didn't. + def self.unregister: (Hash[untyped, untyped] curr) -> bool + + def self.each: () { (untyped) -> untyped } -> untyped + + def self.reset!: () -> untyped + + private + + def self.stringify_keys: () -> untyped + + public + + attr_reader id: untyped + + attr_reader priority: untyped + + attr_reader iso_code: untyped + + attr_reader iso_numeric: untyped + + attr_reader name: untyped + + attr_reader symbol: untyped + + attr_reader disambiguate_symbol: untyped + + attr_reader html_entity: untyped + + attr_reader subunit: untyped + + attr_reader subunit_to_unit: untyped + + attr_reader decimal_mark: untyped + + attr_reader thousands_separator: untyped + + attr_reader symbol_first: untyped + + attr_reader smallest_denomination: untyped + + attr_reader format: untyped + + alias separator decimal_mark + + alias delimiter thousands_separator + + alias eql? == + + # Create a new +Currency+ object. + # + # @param [String, Symbol, #to_s] id Used to look into +table+ and retrieve + # the applicable attributes. + # + # @return [Money::Currency] + # + # @example + # Money::Currency.new(:usd) #=> # + def initialize: (untyped id) -> void + + # Compares +self+ with +other_currency+ against the value of +priority+ + # attribute. + # + # @param [Money::Currency] other_currency The currency to compare to. + # + # @return [-1,0,1] -1 if less than, 0 is equal to, 1 if greater than + # + # @example + # c1 = Money::Currency.new(:usd) + # c2 = Money::Currency.new(:jpy) + # c1 <=> c2 #=> 1 + # c2 <=> c1 #=> -1 + # c1 <=> c1 #=> 0 + def <=>: (untyped other_currency) -> untyped + + # Compares +self+ with +other_currency+ and returns +true+ if the are the + # same or if their +id+ attributes match. + # + # @param [Money::Currency] other_currency The currency to compare to. + # + # @return [Boolean] + # + # @example + # c1 = Money::Currency.new(:usd) + # c2 = Money::Currency.new(:jpy) + # c1 == c1 #=> true + # c1 == c2 #=> false + def ==: (untyped other_currency) -> untyped + + private + + def compare_ids: (untyped other_currency) -> untyped + + public + + # Returns a Integer hash value based on the +id+ attribute in order to use + # functions like & (intersection), group_by, etc. + # + # @return [Integer] + # + # @example + # Money::Currency.new(:usd).hash #=> 428936 + def hash: () -> untyped + + # Returns a human readable representation. + # + # @return [String] + # + # @example + # Money::Currency.new(:usd) #=> # + def inspect: () -> ::String + + # Returns a string representation corresponding to the upcase +id+ + # attribute. + # + # -- + # DEV: id.to_s.upcase corresponds to iso_code but don't use ISO_CODE for consistency. + # + # @return [String] + # + # @example + # Money::Currency.new(:usd).to_s #=> "USD" + # Money::Currency.new(:eur).to_s #=> "EUR" + def to_s: () -> untyped + + # Returns a string representation corresponding to the upcase +id+ + # attribute. Useful in cases where only implicit conversions are made. + # + # @return [String] + # + # @example + # Money::Currency.new(:usd).to_str #=> "USD" + # Money::Currency.new(:eur).to_str #=> "EUR" + def to_str: () -> untyped + + # Returns a symbol representation corresponding to the upcase +id+ + # attribute. + # + # @return [Symbol] + # + # @example + # Money::Currency.new(:usd).to_sym #=> :USD + # Money::Currency.new(:eur).to_sym #=> :EUR + def to_sym: () -> untyped + + # Conversion to +self+. + # + # @return [self] + def to_currency: () -> self + + # Returns currency symbol or iso code for currencies with no symbol. + # + # @return [String] + def code: () -> untyped + + def symbol_first?: () -> untyped + + # Returns if a code currency is ISO. + # + # @return [Boolean] + # + # @example + # Money::Currency.new(:usd).iso? + # + def iso?: () -> untyped + + # Returns the relation between subunit and unit as a base 10 exponent. + # + # Note that MGA and MRU are exceptions and are rounded to 1 + # @see https://en.wikipedia.org/wiki/ISO_4217#Active_codes + # + # @return [Integer] + def exponent: () -> untyped + + alias decimal_places exponent + + private + + def initialize_data!: () -> untyped + end +end \ No newline at end of file diff --git a/sig/lib/money/money.rbs b/sig/lib/money/money.rbs new file mode 100644 index 0000000000..6d08c3e307 --- /dev/null +++ b/sig/lib/money/money.rbs @@ -0,0 +1,540 @@ +# "Money is any object or record that is generally accepted as payment for +# goods and services and repayment of debts in a given socio-economic context +# or country." -Wikipedia +# +# An instance of Money represents an amount of a specific currency. +# +# Money is a value object and should be treated as immutable. +# +# @see http://en.wikipedia.org/wiki/Money +class Money + include Comparable + + include Money::Arithmetic + + extend Constructors + + # Raised when smallest denomination of a currency is not defined + class UndefinedSmallestDenomination < StandardError + end + + @default_currency: Currency + @fractional: BigDecimal + @using_deprecated_default_currency: bool + + # Convenience method for fractional part of the amount. Synonym of #fractional + # + # @return [Integer] when infinite_precision is false + # @return [BigDecimal] when infinite_precision is true + # + # @see infinite_precision + def cents: () -> (Integer | BigDecimal) + + # The value of the monetary amount represented in the fractional or subunit + # of the currency. + # + # For example, in the US dollar currency the fractional unit is cents, and + # there are 100 cents in one US dollar. So given the Money representation of + # one US dollar, the fractional interpretation is 100. + # + # Another example is that of the Kuwaiti dinar. In this case the fractional + # unit is the fils and there 1000 fils to one Kuwaiti dinar. So given the + # Money representation of one Kuwaiti dinar, the fractional interpretation is + # 1000. + # + # @return [Integer] when infinite_precision is false + # @return [BigDecimal] when infinite_precision is true + # + # @see infinite_precision + def fractional: () -> (Integer | BigDecimal) + + # Round a given amount of money to the nearest possible amount in cash value. For + # example, in Swiss franc (CHF), the smallest possible amount of cash value is + # CHF 0.05. Therefore, this method rounds CHF 0.07 to CHF 0.05, and CHF 0.08 to + # CHF 0.10. + # + # @return [Integer] when infinite_precision is false + # @return [BigDecimal] when infinite_precision is true + # + # @see infinite_precision + def round_to_nearest_cash_value: () -> (Integer | BigDecimal) + + attr_reader currency: Currency + + attr_reader bank: untyped + + # @!attribute [rw] default_bank + # Used to set a default bank for currency exchange. + # + # Each Money object is associated with a bank + # object, which is responsible for currency exchange. This property + # allows you to specify the default bank object. The default value for + # this property is an instance of +Bank::VariableExchange.+ It allows + # one to specify custom exchange rates. + # + # @return [Money::Bank::Base] + # + # @!attribute default_formatting_rules + # Used to define a default hash of rules for every time + # +Money#format+ is called. Rules provided on method call will be + # merged with the default ones. To overwrite a rule, just provide the + # intended value while calling +format+. + # + # @see Money::Formatter#initialize Money::Formatter for more details + # + # @example + # Money.default_formatting_rules = { display_free: true } + # Money.new(0, "USD").format # => "free" + # Money.new(0, "USD").format(display_free: false) # => "$0.00" + # + # @return [Hash] + # + # @!attribute [rw] use_i18n + # Used to disable i18n even if it's used by other components of your app. + # + # @return [Boolean] + # + # @!attribute [rw] default_infinite_precision + # @return [Boolean] Use this to enable infinite precision cents as the + # global default + # + # @!attribute [rw] conversion_precision + # Used to specify precision for converting Rational to BigDecimal + # + # @return [Integer] + attr_accessor self.default_formatting_rules: untyped + + # @!attribute [rw] default_bank + # Used to set a default bank for currency exchange. + # + # Each Money object is associated with a bank + # object, which is responsible for currency exchange. This property + # allows you to specify the default bank object. The default value for + # this property is an instance of +Bank::VariableExchange.+ It allows + # one to specify custom exchange rates. + # + # @return [Money::Bank::Base] + # + # @!attribute default_formatting_rules + # Used to define a default hash of rules for every time + # +Money#format+ is called. Rules provided on method call will be + # merged with the default ones. To overwrite a rule, just provide the + # intended value while calling +format+. + # + # @see Money::Formatter#initialize Money::Formatter for more details + # + # @example + # Money.default_formatting_rules = { display_free: true } + # Money.new(0, "USD").format # => "free" + # Money.new(0, "USD").format(display_free: false) # => "$0.00" + # + # @return [Hash] + # + # @!attribute [rw] use_i18n + # Used to disable i18n even if it's used by other components of your app. + # + # @return [Boolean] + # + # @!attribute [rw] default_infinite_precision + # @return [Boolean] Use this to enable infinite precision cents as the + # global default + # + # @!attribute [rw] conversion_precision + # Used to specify precision for converting Rational to BigDecimal + # + # @return [Integer] + attr_accessor self.default_infinite_precision: untyped + + # @!attribute [rw] default_bank + # Used to set a default bank for currency exchange. + # + # Each Money object is associated with a bank + # object, which is responsible for currency exchange. This property + # allows you to specify the default bank object. The default value for + # this property is an instance of +Bank::VariableExchange.+ It allows + # one to specify custom exchange rates. + # + # @return [Money::Bank::Base] + # + # @!attribute default_formatting_rules + # Used to define a default hash of rules for every time + # +Money#format+ is called. Rules provided on method call will be + # merged with the default ones. To overwrite a rule, just provide the + # intended value while calling +format+. + # + # @see Money::Formatter#initialize Money::Formatter for more details + # + # @example + # Money.default_formatting_rules = { display_free: true } + # Money.new(0, "USD").format # => "free" + # Money.new(0, "USD").format(display_free: false) # => "$0.00" + # + # @return [Hash] + # + # @!attribute [rw] use_i18n + # Used to disable i18n even if it's used by other components of your app. + # + # @return [Boolean] + # + # @!attribute [rw] default_infinite_precision + # @return [Boolean] Use this to enable infinite precision cents as the + # global default + # + # @!attribute [rw] conversion_precision + # Used to specify precision for converting Rational to BigDecimal + # + # @return [Integer] + attr_accessor self.conversion_precision: untyped + + attr_reader self.use_i18n: untyped + + attr_reader self.locale_backend: untyped + + attr_writer self.default_bank: untyped + + def self.infinite_precision: () -> untyped + + def self.infinite_precision=: (untyped value) -> untyped + + # @!attribute default_currency + # @return [Money::Currency] The default currency, which is used when + # +Money.new+ is called without an explicit currency argument. The + # default value is Currency.new("USD"). The value must be a valid + # +Money::Currency+ instance. + def self.default_currency: () -> Currency + + def self.default_currency=: (Currency currency) -> Currency + + def self.default_bank: () -> untyped + + def self.locale_backend=: (untyped value) -> untyped + + # @attr_writer rounding_mode Use this to specify the rounding mode + def self.rounding_mode=: (untyped new_rounding_mode) -> untyped + + def self.use_i18n=: (untyped value) -> untyped + + def self.setup_defaults: () -> untyped + + def self.inherited: (untyped base) -> untyped + + # Use this to return the rounding mode. + # + # @param [BigDecimal::ROUND_MODE] mode + # + # @return [BigDecimal::ROUND_MODE] rounding mode + def self.rounding_mode: (?untyped? mode) { () -> untyped } -> untyped + + # Temporarily changes the rounding mode in a given block. + # + # @param [BigDecimal::ROUND_MODE] mode + # + # @yield The block within which rounding mode will be changed. Its return + # value will also be the return value of the whole method. + # + # @return [Object] block results + # + # @example + # fee = Money.with_rounding_mode(BigDecimal::ROUND_HALF_UP) do + # Money.new(1200) * BigDecimal('0.029') + # end + def self.with_rounding_mode: (untyped mode) { () -> untyped } -> untyped + + # Adds a new exchange rate to the default bank and return the rate. + # + # @param [Currency, String, Symbol] from_currency Currency to exchange from. + # @param [Currency, String, Symbol] to_currency Currency to exchange to. + # @param [Numeric] rate Rate to exchange with. + # + # @return [Numeric] + # + # @example + # Money.add_rate("USD", "CAD", 1.25) #=> 1.25 + def self.add_rate: ( + (Currency | string | Symbol) from_currency, + (Currency | string | Symbol) to_currency, + (Currency | string | Symbol) rate) + -> Numeric + + # Sets the default bank to be a SingleCurrency bank that raises on + # currency exchange. Useful when apps operate in a single currency at a time. + def self.disallow_currency_conversion!: () -> untyped + + # Creates a new Money object of value given in the +unit+ of the given + # +currency+. + # + # @param [Numeric] amount The numerical value of the money. + # @param [Currency, String, Symbol] currency The currency format. + # @param [Hash] options Optional settings for the new Money instance + # @option [Money::Bank::*] :bank The exchange bank to use. + # + # @example + # Money.from_amount(23.45, "USD") # => # + # Money.from_amount(23.45, "JPY") # => # + # + # @return [Money] + # + # @see #initialize + def self.from_amount: (Numeric amount, ?(Currency | string | Symbol) currency, ?::Hash[untyped, untyped] options) -> Money + + alias self.from_cents self.new + + alias self.from_dollars self.from_amount + + # Creates a new Money object of value given in the + # +fractional unit+ of the given +currency+. + # + # Alternatively you can use the convenience + # methods like {Money.ca_dollar} and {Money.us_dollar}. + # + # @param [Object] obj Either the fractional value of the money, + # a Money object, or a currency. (If passed a currency as the first + # argument, a Money will be created in that currency with fractional value + # = 0. + # @param [Currency, String, Symbol] currency The currency format. + # @param [Hash] options Optional settings for the new Money instance + # @option [Money::Bank::*] :bank The exchange bank to use. + # + # @return [Money] + # + # @example + # Money.new(100) #=> # + # Money.new(100, "USD") #=> # + # Money.new(100, "EUR") #=> # + # + def initialize: (Object obj, ?(Currency | string | Symbol) currency, ?::Hash[untyped, untyped] options) -> Money + + # Assuming using a currency using dollars: + # Returns the value of the money in dollars, + # instead of in the fractional unit cents. + # + # Synonym of #amount + # + # @return [BigDecimal] + # + # @example + # Money.new(1_00, "USD").dollars # => BigDecimal("1.00") + # + # @see #amount + # @see #to_d + # @see #cents + # + def dollars: () -> BigDecimal + + # Returns the numerical value of the money + # + # @return [BigDecimal] + # + # @example + # Money.new(1_00, "USD").amount # => BigDecimal("1.00") + # + # @see #to_d + # @see #fractional + # + def amount: () -> BigDecimal + + # Return string representation of currency object + # + # @return [String] + # + # @example + # Money.new(100, :USD).currency_as_string #=> "USD" + def currency_as_string: () -> string + + # Set currency object using a string + # + # @param [String] val The currency string. + # + # @return [Money::Currency] + # + # @example + # Money.new(100).currency_as_string("CAD") #=> # + def currency_as_string=: (string val) -> Currency + + # Returns a Integer hash value based on the +fractional+ and +currency+ attributes + # in order to use functions like & (intersection), group_by, etc. + # + # @return [Integer] + # + # @example + # Money.new(100).hash #=> 908351 + def hash: () -> int + + # Uses +Currency#symbol+. If +nil+ is returned, defaults to "¤". + # + # @return [String] + # + # @example + # Money.new(100, "USD").symbol #=> "$" + def symbol: () -> string + + # Common inspect function + # + # @return [String] + def inspect: () -> ::String + + # Returns the amount of money as a string. + # + # @return [String] + # + # @example + # Money.ca_dollar(100).to_s #=> "1.00" + def to_s: () -> string + + # Return the amount of money as a BigDecimal. + # + # @return [BigDecimal] + # + # @example + # Money.us_dollar(1_00).to_d #=> BigDecimal("1.00") + def to_d: () -> BigDecimal + + # Return the amount of money as a Integer. + # + # @return [Integer] + # + # @example + # Money.us_dollar(1_00).to_i #=> 1 + def to_i: () -> int + + # Return the amount of money as a float. Floating points cannot guarantee + # precision. Therefore, this function should only be used when you no longer + # need to represent currency or working with another system that requires + # floats. + # + # @return [Float] + # + # @example + # Money.us_dollar(100).to_f #=> 1.0 + def to_f: () -> Float + + # Returns a new Money instance in a given currency leaving the amount intact + # and not performing currency conversion. + # + # @param [Currency, String, Symbol] new_currency Currency of the new object. + # + # @return [self] + def with_currency: ((Currency | string | Symbol) new_currency) -> Money + + # Conversion to +self+. + # + # @return [self] + def to_money: (?untyped? given_currency) -> Money + + # Receive the amount of this money object in another Currency. + # + # @param [Currency, String, Symbol] other_currency Currency to exchange to. + # + # @yield [n] Optional block to use when rounding after exchanging one currency + # for another. + # @yieldparam [Float] n The resulting float after exchanging one currency for + # another. + # @yieldreturn [Integer] + # + # @return [Money] + # + # @example + # Money.new(2000, "USD").exchange_to("EUR") + # Money.new(2000, "USD").exchange_to("EUR") {|x| x.round} + # Money.new(2000, "USD").exchange_to(Currency.new("EUR")) + def exchange_to: ((Currency | string | Symbol) other_currency) { () -> int } -> Money + + # Receive a money object with the same amount as the current Money object + # in United States dollar. + # + # @return [Money] + # + # @example + # n = Money.new(100, "CAD").as_us_dollar + # n.currency #=> # + def as_us_dollar: () -> Money + + # Receive a money object with the same amount as the current Money object + # in Canadian dollar. + # + # @return [Money] + # + # @example + # n = Money.new(100, "USD").as_ca_dollar + # n.currency #=> # + def as_ca_dollar: () -> Money + + # Receive a money object with the same amount as the current Money object + # in euro. + # + # @return [Money] + # + # @example + # n = Money.new(100, "USD").as_euro + # n.currency #=> # + def as_euro: () -> Money + + # Splits a given amount in parts without losing pennies. The left-over pennies will be + # distributed round-robin amongst the parties. This means that parts listed first will likely + # receive more pennies than ones listed later. + # + # Pass [2, 1, 1] as input to give twice as much to part1 as part2 or + # part3 which results in 50% of the cash to party1, 25% to part2, and 25% to part3. Passing a + # number instead of an array will split the amount evenly (without losing pennies when rounding). + # + # @param [Array, Numeric] parts how amount should be distributed to parts + # + # @return [Array] + # + # @example + # Money.new(5, "USD").allocate([3, 7]) #=> [Money.new(2), Money.new(3)] + # Money.new(100, "USD").allocate([1, 1, 1]) #=> [Money.new(34), Money.new(33), Money.new(33)] + # Money.new(100, "USD").allocate(2) #=> [Money.new(50), Money.new(50)] + # Money.new(100, "USD").allocate(3) #=> [Money.new(34), Money.new(33), Money.new(33)] + # + def allocate: ((Array[Numeric] | Numeric) parts) -> Array[Money] + + alias split allocate + + # Round the monetary amount to smallest unit of coinage. + # + # @note + # This method is only useful when operating with infinite_precision turned + # on. Without infinite_precision values are rounded to the smallest unit of + # coinage automatically. + # + # @return [Money] + # + # @example + # Money.new(10.1, 'USD').round #=> Money.new(10, 'USD') + # + # @see + # Money.default_infinite_precision + # + def round: (?untyped rounding_mode, ?::Integer rounding_precision) -> Money + + # Creates a formatted price string according to several rules. + # + # @param [Hash] rules See {Money::Formatter Money::Formatter} for the list of formatting options + # + # @return [String] + # + def format: (*Hash[untyped, untyped] rules) -> string + + # Returns a thousands separator according to the locale + # + # @return [String] + # + def thousands_separator: () -> string + + # Returns a decimal mark according to the locale + # + # @return [String] + # + def decimal_mark: () -> string + + def dup_with: (?::Hash[untyped, untyped] options) -> untyped + + private + + def as_d: (untyped num) -> untyped + + def return_value: (untyped value) -> untyped + + def locale_backend: () -> untyped +end \ No newline at end of file From 5345db660607c33dbf131ad3bf9e9782a4c6e109 Mon Sep 17 00:00:00 2001 From: Dalen Ward Date: Sat, 13 May 2023 14:10:42 -0600 Subject: [PATCH 3/6] bank --- sig/lib/money/bank/base.rbs | 117 ++++++++++++++ sig/lib/money/bank/variable_exchange.rbs | 198 +++++++++++++++++++++++ sig/lib/money/currency.rbs | 10 +- sig/lib/money/money.rbs | 20 +-- 4 files changed, 330 insertions(+), 15 deletions(-) create mode 100644 sig/lib/money/bank/base.rbs create mode 100644 sig/lib/money/bank/variable_exchange.rbs diff --git a/sig/lib/money/bank/base.rbs b/sig/lib/money/bank/base.rbs new file mode 100644 index 0000000000..c3d83ca542 --- /dev/null +++ b/sig/lib/money/bank/base.rbs @@ -0,0 +1,117 @@ +class Money + # Provides classes that aid in the ability of exchange one currency with + # another. + module Bank + # The lowest Money::Bank error class. + # All Money::Bank errors should inherit from it. + class Error < StandardError + end + + # Raised when the bank doesn't know about the conversion rate + # for specified currencies. + class UnknownRate < Error + end + + # Money::Bank::Base is the basic interface for creating a money exchange + # object, also called Bank. + # + # A Bank is responsible for storing exchange rates, take a Money object as + # input and returns the corresponding Money object converted into an other + # currency. + # + # This class exists for aiding in the creating of other classes to exchange + # money between different currencies. When creating a subclass you will + # need to implement the following methods to exchange money between + # currencies: + # + # - #exchange_with(Money) #=> Money + # + # See Money::Bank::VariableExchange for a real example. + # + # Also, you can extend +Money::Bank::VariableExchange+ instead of + # +Money::Bank::Base+ if your bank implementation needs to store rates + # internally. + # + # @abstract Subclass and override +#exchange_with+ to implement a custom + # +Money::Bank+ class. You can also override +#setup+ instead of + # +#initialize+ to setup initial variables, etc. + class Base + @singleton: Money::Bank::Base + + # Returns the singleton instance of the Base bank. + # + # @return [Money::Bank::Base] + def self.instance: () -> Money::Bank::Base + + # The rounding method to use when exchanging rates. + # + # @return [Proc] + attr_reader rounding_method: untyped + + # Initializes a new +Money::Bank::Base+ object. An optional block can be + # passed to dictate the rounding method that +#exchange_with+ can use. + # + # @yield [n] Optional block to use when rounding after exchanging one + # currency for another. + # @yieldparam [Float] n The resulting float after exchanging one currency + # for another. + # @yieldreturn [Integer] + # + # @return [Money::Bank::Base] + # + # @example + # Money::Bank::Base.new #=> # + # Money::Bank::Base.new {|n| + # n.floor + # } #=> #> + def initialize: () { () -> untyped } -> void + + # Called after initialize. Subclasses can use this method to setup + # variables, etc that they normally would in +#initialize+. + # + # @abstract Subclass and override +#setup+ to implement a custom + # +Money::Bank+ class. + # + # @return [self] + def setup: () -> nil + + # Exchanges the given +Money+ object to a new +Money+ object in + # +to_currency+. + # + # @abstract Subclass and override +#exchange_with+ to implement a custom + # +Money::Bank+ class. + # + # @raise NotImplementedError + # + # @param [Money] from The +Money+ object to exchange from. + # @param [Money::Currency, String, Symbol] to_currency The currency + # string or object to exchange to. + # @yield [n] Optional block to use to round the result after making + # the exchange. + # @yieldparam [Float] n The result after exchanging from one currency to + # the other. + # @yieldreturn [Integer] + # + # @return [Money] + def exchange_with: (Money from, (Money::Currency | string | Symbol) to_currency) { () -> int } -> Money + + # Given two currency strings or object, checks whether they're both the + # same currency. Return +true+ if the currencies are the same, +false+ + # otherwise. + # + # @param [Money::Currency, String, Symbol] currency1 The first currency + # to compare. + # @param [Money::Currency, String, Symbol] currency2 The second currency + # to compare. + # + # @return [Boolean] + # + # @example + # same_currency?("usd", "USD") #=> true + # same_currency?("usd", "EUR") #=> false + # same_currency?("usd", Currency.new("USD")) #=> true + # same_currency?("usd", "USD") #=> true + def same_currency?: ((Money::Currency | string | Symbol) currency1, (Money::Currency | string | Symbol) currency2) -> bool + end + end +end \ No newline at end of file diff --git a/sig/lib/money/bank/variable_exchange.rbs b/sig/lib/money/bank/variable_exchange.rbs new file mode 100644 index 0000000000..ebd24a058b --- /dev/null +++ b/sig/lib/money/bank/variable_exchange.rbs @@ -0,0 +1,198 @@ +class Money + module Bank + # Thrown when an unknown rate format is requested. + class UnknownRateFormat < StandardError + end + + # Class for aiding in exchanging money between different currencies. By + # default, the +Money+ class uses an object of this class (accessible + # through +Money#bank+) for performing currency exchanges. + # + # By default, +Money::Bank::VariableExchange+ has no knowledge about + # conversion rates. One must manually specify them with +add_rate+, after + # which one can perform exchanges with +#exchange_with+. + # + # Exchange rates are stored in memory using +Money::RatesStore::Memory+ by default. + # Pass custom rates stores for other types of storage (file, database, etc) + # + # @example + # bank = Money::Bank::VariableExchange.new + # bank.add_rate("USD", "CAD", 1.24515) + # bank.add_rate("CAD", "USD", 0.803115) + # + # c1 = Money.new(100_00, "USD") + # c2 = Money.new(100_00, "CAD") + # + # # Exchange 100 USD to CAD: + # bank.exchange_with(c1, "CAD") #=> # + # + # # Exchange 100 CAD to USD: + # bank.exchange_with(c2, "USD") #=> # + # + # # With custom exchange rates storage + # redis_store = MyCustomRedisStore.new(host: 'localhost:6379') + # bank = Money::Bank::VariableExchange.new(redis_store) + # # Store rates in redis + # bank.add_rate 'USD', 'CAD', 0.98 + # # Get rate from redis + # bank.get_rate 'USD', 'CAD' + class VariableExchange < Base + attr_reader mutex: untyped + + # Available formats for importing/exporting rates. + RATE_FORMATS: Array[Symbol] + + SERIALIZER_SEPARATOR: string + + FORMAT_SERIALIZERS: Hash[Symbol, (JSON | Marshal | YAML)] + + # Initializes a new +Money::Bank::VariableExchange+ object. + # It defaults to using an in-memory, thread safe store instance for + # storing exchange rates. + # + # @param [RateStore] st An exchange rate store, used to persist exchange rate pairs. + # @yield [n] Optional block to use when rounding after exchanging one + # currency for another. See +Money::bank::base+ + def initialize: (?untyped st) { () -> untyped } -> void + + def store: () -> untyped + + def marshal_dump: () -> ::Array[untyped] + + def marshal_load: (untyped arr) -> untyped + + # Exchanges the given +Money+ object to a new +Money+ object in + # +to_currency+. + # + # @param [Money] from + # The +Money+ object to exchange. + # @param [Currency, String, Symbol] to_currency + # The currency to exchange to. + # + # @yield [n] Optional block to use when rounding after exchanging one + # currency for another. + # @yieldparam [Float] n The resulting float after exchanging one currency + # for another. + # @yieldreturn [Integer] + # + # @return [Money] + # + # @raise +Money::Bank::UnknownRate+ if the conversion rate is unknown. + # + # @example + # bank = Money::Bank::VariableExchange.new + # bank.add_rate("USD", "CAD", 1.24515) + # bank.add_rate("CAD", "USD", 0.803115) + # + # c1 = Money.new(100_00, "USD") + # c2 = Money.new(100_00, "CAD") + # + # # Exchange 100 USD to CAD: + # bank.exchange_with(c1, "CAD") #=> # + # + # # Exchange 100 CAD to USD: + # bank.exchange_with(c2, "USD") #=> # + def exchange_with: (Money from, (Money::Currency | string | Symbol) to_currency) { () -> int } -> Money + + def calculate_fractional: (untyped from, untyped to_currency) -> untyped + + def exchange: (untyped fractional, untyped rate) ?{ (untyped) -> untyped } -> untyped + + # Registers a conversion rate and returns it (uses +#set_rate+). + # Delegates to +Money::RatesStore::Memory+ + # + # @param [Currency, String, Symbol] from Currency to exchange from. + # @param [Currency, String, Symbol] to Currency to exchange to. + # @param [Numeric] rate Rate to use when exchanging currencies. + # + # @return [Numeric] + # + # @example + # bank = Money::Bank::VariableExchange.new + # bank.add_rate("USD", "CAD", 1.24515) + # bank.add_rate("CAD", "USD", 0.803115) + def add_rate: ((Money::Currency | string | Symbol) from, (Money::Currency | string | Symbol) to, Numeric rate) -> Numeric + + # Set the rate for the given currencies. + # access. + # Delegates to +Money::RatesStore::Memory+ + # + # @param [Currency, String, Symbol] from Currency to exchange from. + # @param [Currency, String, Symbol] to Currency to exchange to. + # @param [Numeric] rate Rate to use when exchanging currencies. + # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. + # + # @return [Numeric] + # + # @example + # bank = Money::Bank::VariableExchange.new + # bank.set_rate("USD", "CAD", 1.24515) + # bank.set_rate("CAD", "USD", 0.803115) + def set_rate: ((Money::Currency | string | Symbol) from, (Money::Currency | string | Symbol) to, Numeric rate, ?::Hash[untyped, untyped] opts) -> Numeric + + # Retrieve the rate for the given currencies. + # data access. + # Delegates to +Money::RatesStore::Memory+ + # + # @param [Currency, String, Symbol] from Currency to exchange from. + # @param [Currency, String, Symbol] to Currency to exchange to. + # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. + # + # @return [Numeric] + # + # @example + # bank = Money::Bank::VariableExchange.new + # bank.set_rate("USD", "CAD", 1.24515) + # bank.set_rate("CAD", "USD", 0.803115) + # + # bank.get_rate("USD", "CAD") #=> 1.24515 + # bank.get_rate("CAD", "USD") #=> 0.803115 + def get_rate: ((Money::Currency | string | Symbol) from, (Money::Currency | string | Symbol) to, ?::Hash[untyped, untyped] opts) -> Numeric + + # Return the known rates as a string in the format specified. If +file+ + # is given will also write the string out to the file specified. + # Available formats are +:json+, +:ruby+ and +:yaml+. + # + # @param [Symbol] format Request format for the resulting string. + # @param [String] file Optional file location to write the rates to. + # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. + # + # @return [String] + # + # @raise +Money::Bank::UnknownRateFormat+ if format is unknown. + # + # @example + # bank = Money::Bank::VariableExchange.new + # bank.set_rate("USD", "CAD", 1.24515) + # bank.set_rate("CAD", "USD", 0.803115) + # + # s = bank.export_rates(:json) + # s #=> "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}" + def export_rates: (Symbol format, ?string? file, ?::Hash[untyped, untyped] opts) -> string + + # This should be deprecated. + def rates: () -> untyped + + # Loads rates provided in +s+ given the specified format. Available + # formats are +:json+, +:ruby+ and +:yaml+. + # Delegates to +Money::RatesStore::Memory+ + # + # @param [Symbol] format The format of +s+. + # @param [String] s The rates string. + # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. + # + # @return [self] + # + # @raise +Money::Bank::UnknownRateFormat+ if format is unknown. + # + # @example + # s = "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}" + # bank = Money::Bank::VariableExchange.new + # bank.import_rates(:json, s) + # + # bank.get_rate("USD", "CAD") #=> 1.24515 + # bank.get_rate("CAD", "USD") #=> 0.803115 + def import_rates: (Symbol format, string s, ?::Hash[untyped, untyped] opts) -> Money::Bank::VariableExchange + end + end +end \ No newline at end of file diff --git a/sig/lib/money/currency.rbs b/sig/lib/money/currency.rbs index ed85c8279f..1a5b083ef8 100644 --- a/sig/lib/money/currency.rbs +++ b/sig/lib/money/currency.rbs @@ -35,7 +35,7 @@ class Money # @example # Money::Currency.find(:eur) #=> # # Money::Currency.find(:foo) #=> nil - def self.find: ((string | Symbol) id) -> Currency + def self.find: ((string | Symbol) id) -> Money::Currency # Lookup a currency with given +num+ as an ISO 4217 numeric and returns an # +Currency+ instance on success, +nil+ otherwise. @@ -49,7 +49,7 @@ class Money # Money::Currency.find_by_iso_numeric(978) #=> # # Money::Currency.find_by_iso_numeric(51) #=> # # Money::Currency.find_by_iso_numeric('001') #=> nil - def self.find_by_iso_numeric: ((string | Numeric) num) -> Currency + def self.find_by_iso_numeric: ((string | Numeric) num) -> Money::Currency # Wraps the object in a +Currency+ unless it's already a +Currency+ # object. @@ -64,7 +64,7 @@ class Money # Money::Currency.wrap(nil) #=> nil # Money::Currency.wrap(c1) #=> # # Money::Currency.wrap("usd") #=> # - def self.wrap: (Object object) -> (nil | Currency) + def self.wrap: (Object object) -> (nil | Money::Currency) # List of known currencies. # @@ -112,7 +112,7 @@ class Money # @option separator [String] character between the whole and fraction # amounts # @option delimiter [String] character between each thousands place - def self.register: (Hash[untyped, untyped] curr) -> Currency + def self.register: (Hash[untyped, untyped] curr) -> Money::Currency # Inherit a new currency from existing one # @@ -213,7 +213,7 @@ class Money # c2 = Money::Currency.new(:jpy) # c1 == c1 #=> true # c1 == c2 #=> false - def ==: (untyped other_currency) -> untyped + def ==: (Money::Currency? other_currency) -> bool private diff --git a/sig/lib/money/money.rbs b/sig/lib/money/money.rbs index 6d08c3e307..4ae9772d86 100644 --- a/sig/lib/money/money.rbs +++ b/sig/lib/money/money.rbs @@ -18,7 +18,7 @@ class Money class UndefinedSmallestDenomination < StandardError end - @default_currency: Currency + @default_currency: Money::Currency @fractional: BigDecimal @using_deprecated_default_currency: bool @@ -201,9 +201,9 @@ class Money # +Money.new+ is called without an explicit currency argument. The # default value is Currency.new("USD"). The value must be a valid # +Money::Currency+ instance. - def self.default_currency: () -> Currency + def self.default_currency: () -> Money::Currency - def self.default_currency=: (Currency currency) -> Currency + def self.default_currency=: (Money::Currency currency) -> Money::Currency def self.default_bank: () -> untyped @@ -251,9 +251,9 @@ class Money # @example # Money.add_rate("USD", "CAD", 1.25) #=> 1.25 def self.add_rate: ( - (Currency | string | Symbol) from_currency, - (Currency | string | Symbol) to_currency, - (Currency | string | Symbol) rate) + (Money::Currency | string | Symbol) from_currency, + (Money::Currency | string | Symbol) to_currency, + (Money::Currency | string | Symbol) rate) -> Numeric # Sets the default bank to be a SingleCurrency bank that raises on @@ -275,7 +275,7 @@ class Money # @return [Money] # # @see #initialize - def self.from_amount: (Numeric amount, ?(Currency | string | Symbol) currency, ?::Hash[untyped, untyped] options) -> Money + def self.from_amount: (Numeric amount, ?(Money::Currency | string | Symbol) currency, ?::Hash[untyped, untyped] options) -> Money alias self.from_cents self.new @@ -302,7 +302,7 @@ class Money # Money.new(100, "USD") #=> # # Money.new(100, "EUR") #=> # # - def initialize: (Object obj, ?(Currency | string | Symbol) currency, ?::Hash[untyped, untyped] options) -> Money + def initialize: (Object obj, ?(Money::Currency | string | Symbol) currency, ?::Hash[untyped, untyped] options) -> Money # Assuming using a currency using dollars: # Returns the value of the money in dollars, @@ -414,7 +414,7 @@ class Money # @param [Currency, String, Symbol] new_currency Currency of the new object. # # @return [self] - def with_currency: ((Currency | string | Symbol) new_currency) -> Money + def with_currency: ((Money::Currency | string | Symbol) new_currency) -> Money # Conversion to +self+. # @@ -437,7 +437,7 @@ class Money # Money.new(2000, "USD").exchange_to("EUR") # Money.new(2000, "USD").exchange_to("EUR") {|x| x.round} # Money.new(2000, "USD").exchange_to(Currency.new("EUR")) - def exchange_to: ((Currency | string | Symbol) other_currency) { () -> int } -> Money + def exchange_to: ((Money::Currency | string | Symbol) other_currency) { () -> int } -> Money # Receive a money object with the same amount as the current Money object # in United States dollar. From 9dccc52046243dad8727f2d16635127b985af00e Mon Sep 17 00:00:00 2001 From: Dalen Ward Date: Sat, 13 May 2023 14:38:59 -0600 Subject: [PATCH 4/6] more money --- lib/money/money/allocation.rb | 2 +- sig/lib/money/locale_backend/i18n.rbs | 11 + sig/lib/money/money/allocation.rbs | 15 ++ sig/lib/money/money/arithmetic.rbs | 197 ++++++++++++++++ sig/lib/money/money/constructors.rbs | 73 ++++++ sig/lib/money/money/formatter.rbs | 271 +++++++++++++++++++++++ sig/lib/money/money/formatting_rules.rbs | 36 +++ sig/lib/money/money/locale_backend.rbs | 7 + 8 files changed, 611 insertions(+), 1 deletion(-) create mode 100644 sig/lib/money/locale_backend/i18n.rbs create mode 100644 sig/lib/money/money/allocation.rbs create mode 100644 sig/lib/money/money/arithmetic.rbs create mode 100644 sig/lib/money/money/constructors.rbs create mode 100644 sig/lib/money/money/formatter.rbs create mode 100644 sig/lib/money/money/formatting_rules.rbs create mode 100644 sig/lib/money/money/locale_backend.rbs diff --git a/lib/money/money/allocation.rb b/lib/money/money/allocation.rb index 6e47b2d279..3033571968 100644 --- a/lib/money/money/allocation.rb +++ b/lib/money/money/allocation.rb @@ -9,7 +9,7 @@ class Allocation # The results should always add up to the original amount. # # The parts can be specified as: - # Numeric — performs the split between a given number of parties evenely + # Numeric — performs the split between a given number of parties evenly # Array — allocates the amounts proportionally to the given array # def self.generate(amount, parts, whole_amounts = true) diff --git a/sig/lib/money/locale_backend/i18n.rbs b/sig/lib/money/locale_backend/i18n.rbs new file mode 100644 index 0000000000..5c815e49b7 --- /dev/null +++ b/sig/lib/money/locale_backend/i18n.rbs @@ -0,0 +1,11 @@ +class Money + module LocaleBackend + class I18n < Base + KEY_MAP: Hash[Symbol, Symbol] + + def initialize: () -> void + + def lookup: (Symbol key, untyped _) -> untyped + end + end +end \ No newline at end of file diff --git a/sig/lib/money/money/allocation.rbs b/sig/lib/money/money/allocation.rbs new file mode 100644 index 0000000000..4de5045c77 --- /dev/null +++ b/sig/lib/money/money/allocation.rbs @@ -0,0 +1,15 @@ +class Money + class Allocation + # Splits a given amount in parts without losing pennies. + # The left-over pennies will be distributed round-robin amongst the parts. This means that + # parts listed first will likely receive more pennies than the ones listed later. + # + # The results should always add up to the original amount. + # + # The parts can be specified as: + # Numeric — performs the split between a given number of parties evenely + # Array — allocates the amounts proportionally to the given array + # + def self.generate: (untyped amount, (Numeric | Array[Numeric]) parts, ?bool whole_amounts) -> untyped + end +end \ No newline at end of file diff --git a/sig/lib/money/money/arithmetic.rbs b/sig/lib/money/money/arithmetic.rbs new file mode 100644 index 0000000000..8abffe9141 --- /dev/null +++ b/sig/lib/money/money/arithmetic.rbs @@ -0,0 +1,197 @@ +class Money + module Arithmetic + # Wrapper for coerced numeric values to distinguish + # when numeric was on the 1st place in operation. + CoercedNumeric: untyped + + # Returns a money object with changed polarity. + # + # @return [Money] + # + # @example + # - Money.new(100) #=> # + def -@: () -> Money + + # Checks whether two Money objects have the same currency and the same + # amount. If Money objects have a different currency it will only be true + # if the amounts are both zero. Checks against objects that are not Money or + # a subclass will always return false. + # + # @param [Money] other_money Value to compare with. + # + # @return [Boolean] + # + # @example + # Money.new(100).eql?(Money.new(101)) #=> false + # Money.new(100).eql?(Money.new(100)) #=> true + # Money.new(100, "USD").eql?(Money.new(100, "GBP")) #=> false + # Money.new(0, "USD").eql?(Money.new(0, "EUR")) #=> true + # Money.new(100).eql?("1.00") #=> false + def eql?: (Money other_money) -> bool + + # Compares two Money objects. If money objects have a different currency it + # will attempt to convert the currency. + # + # @param [Money] other Value to compare with. + # + # @return [Integer] + # + # @raise [TypeError] when other object is not Money + # + def <=>: (Money other) -> Integer + + # Uses Comparable's implementation but raises ArgumentError if non-zero + # numeric value is given. + def ==: ((Money | Numeric) other) -> bool + + # Test if the amount is positive. Returns +true+ if the money amount is + # greater than 0, +false+ otherwise. + # + # @return [Boolean] + # + # @example + # Money.new(1).positive? #=> true + # Money.new(0).positive? #=> false + # Money.new(-1).positive? #=> false + def positive?: () -> bool + + # Test if the amount is negative. Returns +true+ if the money amount is + # less than 0, +false+ otherwise. + # + # @return [Boolean] + # + # @example + # Money.new(-1).negative? #=> true + # Money.new(0).negative? #=> false + # Money.new(1).negative? #=> false + def negative?: () -> bool + + # Multiplies the monetary value with the given number and returns a new + # +Money+ object with this monetary value and the same currency. + # + # Note that you can't multiply a Money object by an other +Money+ object. + # + # @param [Numeric] value Number to multiply by. + # + # @return [Money] The resulting money. + # + # @raise [TypeError] If +value+ is NOT a number. + # + # @example + # Money.new(100) * 2 #=> # + # + def *: (Numeric value) -> Money + + # Divides the monetary value with the given number and returns a new +Money+ + # object with this monetary value and the same currency. + # Can also divide by another +Money+ object to get a ratio. + # + # +Money/Numeric+ returns +Money+. +Money/Money+ returns +Float+. + # + # @param [Money, Numeric] value Number to divide by. + # + # @return [Money] The resulting money if you divide Money by a number. + # @return [Float] The resulting number if you divide Money by a Money. + # + # @example + # Money.new(100) / 10 #=> # + # Money.new(100) / Money.new(10) #=> 10.0 + # + def /: ((Money | Numeric) value) -> (Money | Float) + + # Synonym for +#/+. + # + # @param [Money, Numeric] value Number to divide by. + # + # @return [Money] The resulting money if you divide Money by a number. + # @return [Float] The resulting number if you divide Money by a Money. + # + # @see #/ + # + def div: ((Money | Numeric) value) -> (Money | Float) + + # Divide money by money or fixnum and return array containing quotient and + # modulus. + # + # @param [Money, Integer] val Number to divmod by. + # + # @return [Array,Array] + # + # @example + # Money.new(100).divmod(9) #=> [#, #] + # Money.new(100).divmod(Money.new(9)) #=> [11, #] + def divmod: ((Money | Integer) val) -> Array[Money | Integer] + + private + + def divmod_money: (untyped val) -> ::Array[untyped] + + def divmod_other: (untyped val) -> ::Array[untyped] + + public + + # Equivalent to +self.divmod(val)[1]+ + # + # @param [Money, Integer] val Number take modulo with. + # + # @return [Money] + # + # @example + # Money.new(100).modulo(9) #=> # + # Money.new(100).modulo(Money.new(9)) #=> # + def modulo: ((Money | Integer) val) -> Money + + # Synonym for +#modulo+. + # + # @param [Money, Integer] val Number take modulo with. + # + # @return [Money] + # + # @see #modulo + def %: ((Money | Integer) val) -> Money + + # If different signs +self.modulo(val) - val+ otherwise +self.modulo(val)+ + # + # @param [Money, Integer] val Number to rake remainder with. + # + # @return [Money] + # + # @example + # Money.new(100).remainder(9) #=> # + def remainder: ((Money | Integer) val) -> Money + + # Return absolute value of self as a new Money object. + # + # @return [Money] + # + # @example + # Money.new(-100).abs #=> # + def abs: () -> Money + + # Test if the money amount is zero. + # + # @return [Boolean] + # + # @example + # Money.new(100).zero? #=> false + # Money.new(0).zero? #=> true + def zero?: () -> bool + + # Test if the money amount is non-zero. Returns this money object if it is + # non-zero, or nil otherwise, like +Numeric#nonzero?+. + # + # @return [Money, nil] + # + # @example + # Money.new(100).nonzero? #=> # + # Money.new(0).nonzero? #=> nil + def nonzero?: () -> Arithmetic? + + # Used to make Money instance handle the operations when arguments order is reversed + # @return [Array] + # + # @example + # 2 * Money.new(10) #=> # + def coerce: (untyped other) -> ::Array[self | untyped] + end +end \ No newline at end of file diff --git a/sig/lib/money/money/constructors.rbs b/sig/lib/money/money/constructors.rbs new file mode 100644 index 0000000000..2641b248af --- /dev/null +++ b/sig/lib/money/money/constructors.rbs @@ -0,0 +1,73 @@ +class Money + module Constructors + # Create a new money object with value 0. + # + # @param [Currency, String, Symbol] currency The currency to use. + # + # @return [Money] + # + # @example + # Money.empty #=> # + def empty: (?(Money::Currency | string | Symbol) currency) -> Money + + alias zero empty + + # Creates a new Money object of the given value, using the Canadian + # dollar currency. + # + # @param [Integer] cents The cents value. + # + # @return [Money] + # + # @example + # n = Money.ca_dollar(100) + # n.cents #=> 100 + # n.currency #=> # + def ca_dollar: (int cents) -> Money + + alias cad ca_dollar + + # Creates a new Money object of the given value, using the American dollar + # currency. + # + # @param [Integer] cents The cents value. + # + # @return [Money] + # + # @example + # n = Money.us_dollar(100) + # n.cents #=> 100 + # n.currency #=> # + def us_dollar: (int cents) -> Money + + alias usd us_dollar + + # Creates a new Money object of the given value, using the Euro currency. + # + # @param [Integer] cents The cents value. + # + # @return [Money] + # + # @example + # n = Money.euro(100) + # n.cents #=> 100 + # n.currency #=> # + def euro: (int cents) -> Money + + alias eur euro + + # Creates a new Money object of the given value, in British pounds. + # + # @param [Integer] pence The pence value. + # + # @return [Money] + # + # @example + # n = Money.pound_sterling(100) + # n.fractional #=> 100 + # n.currency #=> # + def pound_sterling: (int pence) -> Money + + alias gbp pound_sterling + end +end \ No newline at end of file diff --git a/sig/lib/money/money/formatter.rbs b/sig/lib/money/money/formatter.rbs new file mode 100644 index 0000000000..53aa06a5ed --- /dev/null +++ b/sig/lib/money/money/formatter.rbs @@ -0,0 +1,271 @@ +class Money + class Formatter + DEFAULTS: Hash[Symbol, string] + + # Creates a formatted price string according to several rules. + # + # @param [Hash] rules The options used to format the string. + # + # @return [String] + # + # @option rules [Boolean, String] :display_free (false) Whether a zero + # amount of money should be formatted of "free" or as the supplied string. + # + # @example + # Money.us_dollar(0).format(display_free: true) #=> "free" + # Money.us_dollar(0).format(display_free: "gratis") #=> "gratis" + # Money.us_dollar(0).format #=> "$0.00" + # + # @option rules [Boolean] :with_currency (false) Whether the currency name + # should be appended to the result string. + # + # @example + # Money.ca_dollar(100).format #=> "$1.00" + # Money.ca_dollar(100).format(with_currency: true) #=> "$1.00 CAD" + # Money.us_dollar(85).format(with_currency: true) #=> "$0.85 USD" + # + # @option rules [Boolean] :rounded_infinite_precision (false) Whether the + # amount of money should be rounded when using {infinite_precision} + # + # @example + # Money.us_dollar(100.1).format #=> "$1.001" + # Money.us_dollar(100.1).format(rounded_infinite_precision: true) #=> "$1" + # Money.us_dollar(100.9).format(rounded_infinite_precision: true) #=> "$1.01" + # + # @option rules [Boolean] :no_cents (false) Whether cents should be omitted. + # + # @example + # Money.ca_dollar(100).format(no_cents: true) #=> "$1" + # Money.ca_dollar(599).format(no_cents: true) #=> "$5" + # + # @option rules [Boolean] :no_cents_if_whole (false) Whether cents should be + # omitted if the cent value is zero + # + # @example + # Money.ca_dollar(10000).format(no_cents_if_whole: true) #=> "$100" + # Money.ca_dollar(10034).format(no_cents_if_whole: true) #=> "$100.34" + # + # @option rules [Boolean, String, nil] :symbol (true) Whether a money symbol + # should be prepended to the result string. The default is true. This method + # attempts to pick a symbol that's suitable for the given currency. + # + # @example + # Money.new(100, "USD") #=> "$1.00" + # Money.new(100, "GBP") #=> "£1.00" + # Money.new(100, "EUR") #=> "€1.00" + # + # # Same thing. + # Money.new(100, "USD").format(symbol: true) #=> "$1.00" + # Money.new(100, "GBP").format(symbol: true) #=> "£1.00" + # Money.new(100, "EUR").format(symbol: true) #=> "€1.00" + # + # # You can specify a false expression or an empty string to disable + # # prepending a money symbol.§ + # Money.new(100, "USD").format(symbol: false) #=> "1.00" + # Money.new(100, "GBP").format(symbol: nil) #=> "1.00" + # Money.new(100, "EUR").format(symbol: "") #=> "1.00" + # + # # If the symbol for the given currency isn't known, then it will default + # # to "¤" as symbol. + # Money.new(100, "AWG").format(symbol: true) #=> "¤1.00" + # + # # You can specify a string as value to enforce using a particular symbol. + # Money.new(100, "AWG").format(symbol: "ƒ") #=> "ƒ1.00" + # + # # You can specify a indian currency format + # Money.new(10000000, "INR").format(south_asian_number_formatting: true) #=> "1,00,000.00" + # Money.new(10000000).format(south_asian_number_formatting: true) #=> "$1,00,000.00" + # + # @option rules [Boolean, nil] :symbol_before_without_space (true) Whether + # a space between the money symbol and the amount should be inserted when + # +:symbol_position+ is +:before+. The default is true (meaning no space). Ignored + # if +:symbol+ is false or +:symbol_position+ is not +:before+. + # + # @example + # # Default is to not insert a space. + # Money.new(100, "USD").format #=> "$1.00" + # + # # Same thing. + # Money.new(100, "USD").format(symbol_before_without_space: true) #=> "$1.00" + # + # # If set to false, will insert a space. + # Money.new(100, "USD").format(symbol_before_without_space: false) #=> "$ 1.00" + # + # @option rules [Boolean, nil] :symbol_after_without_space (false) Whether + # a space between the amount and the money symbol should be inserted when + # +:symbol_position+ is +:after+. The default is false (meaning space). Ignored + # if +:symbol+ is false or +:symbol_position+ is not +:after+. + # + # @example + # # Default is to insert a space. + # Money.new(100, "USD").format(symbol_position: :after) #=> "1.00 $" + # + # # If set to true, will not insert a space. + # Money.new(100, "USD").format(symbol_position: :after, symbol_after_without_space: true) #=> "1.00$" + # + # @option rules [Boolean, String, nil] :decimal_mark (true) Whether the + # currency should be separated by the specified character or '.' + # + # @example + # # If a string is specified, it's value is used. + # Money.new(100, "USD").format(decimal_mark: ",") #=> "$1,00" + # + # # If the decimal_mark for a given currency isn't known, then it will default + # # to "." as decimal_mark. + # Money.new(100, "FOO").format #=> "$1.00" + # + # @option rules [Boolean, String, nil] :thousands_separator (true) Whether + # the currency should be delimited by the specified character or ',' + # + # @example + # # If a falsey value is specified, no thousands_separator is used. + # Money.new(100000, "USD").format(thousands_separator: false) #=> "1000.00" + # Money.new(100000, "USD").format(thousands_separator: nil) #=> "1000.00" + # Money.new(100000, "USD").format(thousands_separator: "") #=> "1000.00" + # + # # If true is specified, the locale or default thousands_separator is used. + # Money.new(100000, "USD").format(thousands_separator: true) #=> "1,000.00" + # + # # If a string is specified, it's value is used. + # Money.new(100000, "USD").format(thousands_separator: ".") #=> "$1.000.00" + # + # # If the thousands_separator for a given currency isn't known, then it will + # # default to "," as thousands_separator. + # Money.new(100000, "FOO").format #=> "$1,000.00" + # + # @option rules [Boolean] :html (false) Whether the currency should be + # HTML-formatted. Only useful in combination with +:with_currency+. + # + # @example + # Money.ca_dollar(570).format(html: true, with_currency: true) + # #=> "$5.70 CAD" + # + # @option rules [Boolean] :html_wrap (false) Whether all currency parts should be HTML-formatted. + # + # @example + # Money.ca_dollar(570).format(html_wrap: true, with_currency: true) + # #=> "$5.70 CAD" + # + # @option rules [Boolean] :sign_before_symbol (false) Whether the sign should be + # before the currency symbol. + # + # @example + # # You can specify to display the sign before the symbol for negative numbers + # Money.new(-100, "GBP").format(sign_before_symbol: true) #=> "-£1.00" + # Money.new(-100, "GBP").format(sign_before_symbol: false) #=> "£-1.00" + # Money.new(-100, "GBP").format #=> "£-1.00" + # + # @option rules [Boolean] :sign_positive (false) Whether positive numbers should be + # signed, too. + # + # @example + # # You can specify to display the sign with positive numbers + # Money.new(100, "GBP").format(sign_positive: true, sign_before_symbol: true) #=> "+£1.00" + # Money.new(100, "GBP").format(sign_positive: true, sign_before_symbol: false) #=> "£+1.00" + # Money.new(100, "GBP").format(sign_positive: false, sign_before_symbol: true) #=> "£1.00" + # Money.new(100, "GBP").format(sign_positive: false, sign_before_symbol: false) #=> "£1.00" + # Money.new(100, "GBP").format #=> "£+1.00" + # + # @option rules [Boolean] :disambiguate (false) Prevents the result from being ambiguous + # due to equal symbols for different currencies. Uses the `disambiguate_symbol`. + # + # @example + # Money.new(10000, "USD").format(disambiguate: false) #=> "$100.00" + # Money.new(10000, "CAD").format(disambiguate: false) #=> "$100.00" + # Money.new(10000, "USD").format(disambiguate: true) #=> "$100.00" + # Money.new(10000, "CAD").format(disambiguate: true) #=> "C$100.00" + # + # @option rules [Boolean] :html_wrap_symbol (false) Wraps the currency symbol + # in a html tag. + # + # @example + # Money.new(10000, "USD").format(disambiguate: false) + # #=> "$100.00 + # + # @option rules [Symbol] :symbol_position (:before) `:before` if the currency + # symbol goes before the amount, `:after` if it goes after. + # + # @example + # Money.new(10000, "USD").format(symbol_position: :before) #=> "$100.00" + # Money.new(10000, "USD").format(symbol_position: :after) #=> "100.00 $" + # + # @option rules [Boolean] :translate (true) `true` Checks for custom + # symbol definitions using I18n. + # + # @example + # # With the following entry in the translation files: + # # en: + # # number: + # # currency: + # # symbol: + # # CAD: "CAD$" + # Money.new(10000, "CAD").format(translate: true) #=> "CAD$100.00" + # + # @option rules [Boolean] :drop_trailing_zeros (false) Ignore trailing zeros after + # the decimal mark + # + # @example + # Money.new(89000, :btc).format(drop_trailing_zeros: true) #=> B⃦0.00089 + # Money.new(110, :usd).format(drop_trailing_zeros: true) #=> $1.1 + # + # @option rules [Boolean] :delimiter_pattern (/(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/) Regular expression to set the placement + # for the thousands delimiter + # + # @example + # Money.new(89000, :btc).format(delimiter_pattern: /(\d)(?=\d)/) #=> B⃦8,9,0.00 + # + # @option rules [String] :format (nil) Provide a template for formatting. `%u` will be replaced + # with the symbol (if present) and `%n` will be replaced with the number. + # + # @example + # Money.new(10000, "USD").format(format: '%u %n') #=> "$ 100.00" + # Money.new(10000, "USD").format(format: '%u%n') #=> "$100.00" + # + # Note that the default rules can be defined through {Money.default_formatting_rules} hash. + # + # @see Money.default_formatting_rules Money.default_formatting_rules for more information. + def initialize: (untyped money, *untyped rules) -> void + + def to_s: () -> string + + def thousands_separator: () -> string + + def decimal_mark: () -> string + + alias delimiter thousands_separator + + alias separator decimal_mark + + private + + attr_reader money: Money + + attr_reader currency: Currency + + attr_reader rules: FormattingRules + + def format_number: () -> string + + def append_sign: (untyped formatted_number) -> string + + def append_currency_symbol: (untyped formatted_number) -> string + + def show_free_text?: () -> untyped + + def html_wrap: (string string, string class_name) -> ::String + + def free_text: () -> (untyped | "free") + + def format_whole_part: (untyped value) -> untyped + + def extract_whole_and_decimal_parts: () -> Array[string] + + def format_decimal_part: (untyped value) -> (nil | string) + + def lookup: (Symbol key) -> untyped + + def lookup_default: (Symbol key) -> untyped + + def symbol_value_from: (Hash[Symbol, untyped] rules) -> (untyped | untyped | "" | untyped) + end +end \ No newline at end of file diff --git a/sig/lib/money/money/formatting_rules.rbs b/sig/lib/money/money/formatting_rules.rbs new file mode 100644 index 0000000000..89f4c449a0 --- /dev/null +++ b/sig/lib/money/money/formatting_rules.rbs @@ -0,0 +1,36 @@ +class Money + class FormattingRules + @rules: Hash[Symbol, untyped] + + def initialize: (untyped currency, *untyped raw_rules) -> void + + def []: (untyped key) -> untyped + + def has_key?: (untyped key) -> untyped + + private + + attr_reader currency: untyped + + # Cleans up formatting rules. + # + # @param [Hash] rules + # + # @return [Hash] + def normalize_formatting_rules: (Hash[Symbol, untyped] rules) -> Hash[Symbol, untyped] + + def default_formatting_rules: () -> Hash[Symbol, untyped] + + def translate_formatting_rules: (Hash[Symbol, untyped] rules) -> Hash[Symbol, untyped] + + def localize_formatting_rules: (Hash[Symbol, untyped] rules) -> Hash[Symbol, untyped] + + def determine_format_from_formatting_rules: (Hash[Symbol, untyped] rules) -> Hash[Symbol, untyped] + + def delimiter_pattern_rule: (Hash[Symbol, untyped] rules) -> ::Regexp + + def symbol_position_from: (Hash[Symbol, untyped] rules) -> (Hash[Symbol, untyped] | :before | :after) + + def warn_about_deprecated_rules: (Hash[Symbol, untyped] rules) -> void + end +end \ No newline at end of file diff --git a/sig/lib/money/money/locale_backend.rbs b/sig/lib/money/money/locale_backend.rbs new file mode 100644 index 0000000000..40c8705e7d --- /dev/null +++ b/sig/lib/money/money/locale_backend.rbs @@ -0,0 +1,7 @@ +class Money + module LocaleBackend + BACKENDS: { legacy: untyped, :i18n => untyped, currency: untyped } + + def self.find: (untyped name) -> untyped + end +end \ No newline at end of file From e3c24be102a5beffe92f6e04fe320d9917384c48 Mon Sep 17 00:00:00 2001 From: Dalen Ward Date: Sat, 13 May 2023 14:42:28 -0600 Subject: [PATCH 5/6] rates store --- sig/lib/money/rates_store/memory.rbs | 90 ++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 sig/lib/money/rates_store/memory.rbs diff --git a/sig/lib/money/rates_store/memory.rbs b/sig/lib/money/rates_store/memory.rbs new file mode 100644 index 0000000000..4624629d09 --- /dev/null +++ b/sig/lib/money/rates_store/memory.rbs @@ -0,0 +1,90 @@ +class Money + module RatesStore + # Class for thread-safe storage of exchange rate pairs. + # Used by instances of +Money::Bank::VariableExchange+. + # + # @example + # store = Money::RatesStore::Memory.new + # store.add_rate 'USD', 'CAD', 0.98 + # store.get_rate 'USD', 'CAD' # => 0.98 + # # iterates rates + # store.each_rate {|iso_from, iso_to, rate| puts "#{from} -> #{to}: #{rate}" } + class Memory + INDEX_KEY_SEPARATOR: string + + # Initializes a new +Money::RatesStore::Memory+ object. + # + # @param [Hash] opts Optional store options. + # @option opts [Boolean] :without_mutex disables the usage of a mutex + # @param [Hash] rates Optional initial exchange rate data. + def initialize: (?::Hash[untyped, untyped] opts, ?::Hash[untyped, untyped] rates) -> void + + # Registers a conversion rate and returns it. Uses +Mutex+ to synchronize data access. + # + # @param [String] currency_iso_from Currency to exchange from. + # @param [String] currency_iso_to Currency to exchange to. + # @param [Numeric] rate Rate to use when exchanging currencies. + # + # @return [Numeric] + # + # @example + # store = Money::RatesStore::Memory.new + # store.add_rate("USD", "CAD", 1.24515) + # store.add_rate("CAD", "USD", 0.803115) + def add_rate: (string currency_iso_from, string currency_iso_to, Numeric rate) -> Numeric + + # Retrieve the rate for the given currencies. Uses +Mutex+ to synchronize data access. + # Delegates to +Money::RatesStore::Memory+ + # + # @param [String] currency_iso_from Currency to exchange from. + # @param [String] currency_iso_to Currency to exchange to. + # + # @return [Numeric] + # + # @example + # store = Money::RatesStore::Memory.new + # store.add_rate("USD", "CAD", 1.24515) + # + # store.get_rate("USD", "CAD") #=> 1.24515 + def get_rate: (string currency_iso_from, string currency_iso_to) -> Numeric + + def marshal_dump: () -> untyped + + # Wraps block execution in a thread-safe transaction + def transaction: () { () -> untyped } -> untyped + + # Iterate over rate tuples (iso_from, iso_to, rate) + # + # @yieldparam iso_from [String] Currency ISO string. + # @yieldparam iso_to [String] Currency ISO string. + # @yieldparam rate [Numeric] Exchange rate. + # + # @return [Enumerator] + # + # @example + # store.each_rate do |iso_from, iso_to, rate| + # puts [iso_from, iso_to, rate].join + # end + def each_rate: () ?{ (string iso_from, string iso_to, Numeric rate) -> untyped } -> untyped + + private + + attr_reader rates: untyped + + attr_reader options: untyped + + attr_reader guard: untyped + + # Return the rate hashkey for the given currencies. + # + # @param [String] currency_iso_from The currency to exchange from. + # @param [String] currency_iso_to The currency to exchange to. + # + # @return [String] + # + # @example + # rate_key_for("USD", "CAD") #=> "USD_TO_CAD" + def rate_key_for: (string currency_iso_from, string currency_iso_to) -> string + end + end +end \ No newline at end of file From b6652a4c2320499b0f76ba7093c6bdad6a56253b Mon Sep 17 00:00:00 2001 From: Dalen Ward Date: Sat, 13 May 2023 19:48:14 -0600 Subject: [PATCH 6/6] move manifest.yml --- manifest.yml => sig/manifest.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename manifest.yml => sig/manifest.yml (100%) diff --git a/manifest.yml b/sig/manifest.yml similarity index 100% rename from manifest.yml rename to sig/manifest.yml