sec_id 5.2.0 → 6.1.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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -0
  3. data/CHANGELOG.md +31 -0
  4. data/MIGRATION.md +101 -0
  5. data/README.md +245 -17
  6. data/lib/sec_id/active_model.rb +144 -0
  7. data/lib/sec_id/base.rb +64 -2
  8. data/lib/sec_id/bic/country_codes.rb +46 -0
  9. data/lib/sec_id/bic.rb +123 -0
  10. data/lib/sec_id/cei.rb +19 -7
  11. data/lib/sec_id/cfi/attribute_set.rb +49 -0
  12. data/lib/sec_id/cfi/classification.rb +107 -0
  13. data/lib/sec_id/cfi/field.rb +56 -0
  14. data/lib/sec_id/cfi/tables.rb +1033 -0
  15. data/lib/sec_id/cfi.rb +138 -208
  16. data/lib/sec_id/cik.rb +13 -0
  17. data/lib/sec_id/concerns/checkable.rb +2 -2
  18. data/lib/sec_id/concerns/generatable.rb +71 -0
  19. data/lib/sec_id/concerns/normalizable.rb +1 -0
  20. data/lib/sec_id/concerns/validatable.rb +14 -3
  21. data/lib/sec_id/cusip.rb +18 -7
  22. data/lib/sec_id/deep_freeze.rb +18 -0
  23. data/lib/sec_id/detector.rb +29 -31
  24. data/lib/sec_id/dti.rb +104 -0
  25. data/lib/sec_id/figi.rb +18 -0
  26. data/lib/sec_id/fisn.rb +31 -0
  27. data/lib/sec_id/iban/country_rules.rb +7 -6
  28. data/lib/sec_id/iban.rb +19 -1
  29. data/lib/sec_id/isin.rb +20 -15
  30. data/lib/sec_id/lei.rb +13 -0
  31. data/lib/sec_id/occ.rb +21 -0
  32. data/lib/sec_id/railtie.rb +14 -0
  33. data/lib/sec_id/scanner.rb +18 -27
  34. data/lib/sec_id/sedol.rb +16 -0
  35. data/lib/sec_id/valoren.rb +13 -0
  36. data/lib/sec_id/version.rb +2 -1
  37. data/lib/sec_id/wkn.rb +16 -0
  38. data/lib/sec_id.rb +31 -7
  39. data/sec_id.gemspec +11 -5
  40. data/sig/manifest.yaml +8 -0
  41. data/sig/sec_id/base.rbs +78 -0
  42. data/sig/sec_id/bic/country_codes.rbs +5 -0
  43. data/sig/sec_id/bic.rbs +30 -0
  44. data/sig/sec_id/cei.rbs +26 -0
  45. data/sig/sec_id/cfi/attribute_set.rbs +68 -0
  46. data/sig/sec_id/cfi/classification.rbs +23 -0
  47. data/sig/sec_id/cfi/field.rbs +337 -0
  48. data/sig/sec_id/cfi/tables.rbs +68 -0
  49. data/sig/sec_id/cfi.rbs +56 -0
  50. data/sig/sec_id/cik.rbs +19 -0
  51. data/sig/sec_id/concerns/checkable.rbs +41 -0
  52. data/sig/sec_id/concerns/generatable.rbs +26 -0
  53. data/sig/sec_id/concerns/normalizable.rbs +34 -0
  54. data/sig/sec_id/concerns/validatable.rbs +42 -0
  55. data/sig/sec_id/cusip.rbs +29 -0
  56. data/sig/sec_id/deep_freeze.rbs +6 -0
  57. data/sig/sec_id/detector.rbs +29 -0
  58. data/sig/sec_id/dti.rbs +27 -0
  59. data/sig/sec_id/errors.rbs +28 -0
  60. data/sig/sec_id/figi.rbs +31 -0
  61. data/sig/sec_id/fisn.rbs +24 -0
  62. data/sig/sec_id/iban/country_rules.rbs +10 -0
  63. data/sig/sec_id/iban.rbs +54 -0
  64. data/sig/sec_id/isin.rbs +40 -0
  65. data/sig/sec_id/lei.rbs +33 -0
  66. data/sig/sec_id/occ.rbs +45 -0
  67. data/sig/sec_id/scanner.rbs +44 -0
  68. data/sig/sec_id/sedol.rbs +34 -0
  69. data/sig/sec_id/valoren.rbs +29 -0
  70. data/sig/sec_id/version.rbs +3 -0
  71. data/sig/sec_id/wkn.rbs +15 -0
  72. data/sig/sec_id.rbs +58 -0
  73. metadata +55 -7
  74. data/lib/sec_id/concerns/identifier_metadata.rb +0 -56
@@ -0,0 +1,29 @@
1
+ module SecID
2
+ # Detects which identifier types match a given string.
3
+ #
4
+ # @api private
5
+ class Detector
6
+ def initialize: (Array[singleton(Base)] identifier_list) -> void
7
+ def call: (SecID::input str) -> Array[Symbol]
8
+ def matches?: (SecID::input str) -> bool
9
+ def first_match: (SecID::input str) -> Base?
10
+
11
+ private
12
+
13
+ def filter_candidates: (String upcased) -> Array[singleton(Base)]
14
+ def validate_and_sort: (String input, Array[untyped] candidates) -> Array[Symbol]
15
+ def precompute: () -> void
16
+ def build_discriminator_sets: () -> void
17
+ def build_length_table: () -> void
18
+ def stage1_special_chars: (String upcased) -> Array[singleton(Base)]?
19
+ def stage2_length: (Integer length) -> Array[singleton(Base)]
20
+ def stage3_charset: (String upcased, Array[singleton(Base)] candidates) -> Array[singleton(Base)]
21
+ def accepts_char?: (singleton(Base) klass, String char) -> bool
22
+
23
+ @classes: Array[singleton(Base)]
24
+ @slash_types: Array[singleton(Base)]
25
+ @space_only_types: Array[singleton(Base)]
26
+ @special_types: Array[singleton(Base)]
27
+ @candidates_by_length: Hash[Integer, Array[singleton(Base)]]
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ module SecID
2
+ # Digital Token Identifier (DTI, ISO 24165).
3
+ class DTI < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ ALPHABET: Array[String]
13
+ ALPHABET_VALUE: Hash[String, Integer]
14
+ GENERATE_CHARSET: Array[String]
15
+ GRANDFATHERED_CODES: Hash[String, String]
16
+
17
+ def initialize: (SecID::input dti) -> void
18
+ def calculate_check_digit: () -> String
19
+ private def self.generate_body: (Random random) -> String
20
+
21
+ private
22
+
23
+ def components: () -> Hash[Symbol, untyped]
24
+ def grandfathered_check_digit: (untyped base) -> String?
25
+ def iso7064_mod31_30_check_char: (untyped base) -> String
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ module SecID
2
+ # Immutable value object representing validation errors for an identifier.
3
+ class Errors
4
+ # A single error entry. `{ error:, message: }` in the source, but `Hash#freeze`
5
+ # in `build_error` widens the record literal, so it is modelled as a Hash.
6
+ type detail = Hash[Symbol, untyped]
7
+
8
+ attr_reader details: Array[detail]
9
+
10
+ def initialize: (Array[detail] errors) -> void
11
+
12
+ def messages: () -> Array[String?]
13
+
14
+ def any?: () -> bool
15
+
16
+ def empty?: () -> bool
17
+
18
+ alias none? empty?
19
+
20
+ def size: () -> Integer
21
+
22
+ def each: () { (detail) -> void } -> Array[detail]
23
+
24
+ def to_a: () -> Array[String?]
25
+
26
+ def as_json: (*untyped) -> Array[detail]
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module SecID
2
+ # Financial Instrument Global Identifier (FIGI).
3
+ class FIGI < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ RESTRICTED_PREFIXES: Set[String]
13
+ GENERATE_CHARSET: Array[String]
14
+
15
+ attr_reader prefix: String?
16
+ attr_reader random_part: String?
17
+
18
+ def initialize: (SecID::input figi) -> void
19
+ def to_pretty_s: () -> String?
20
+ def calculate_check_digit: () -> Integer
21
+ def self.check_digit: (SecID::input id) -> Integer
22
+ private def self.generate_body: (Random random) -> String
23
+
24
+ private
25
+
26
+ def components: () -> Hash[Symbol, untyped]
27
+ def valid_format?: () -> bool
28
+ def detect_errors: () -> Array[Symbol]
29
+ def validation_message: (Symbol code) -> String?
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ module SecID
2
+ # Financial Instrument Short Name (FISN).
3
+ class FISN < Base
4
+ FULL_NAME: String
5
+ ID_LENGTH: ::Range[Integer]
6
+ EXAMPLE: String
7
+ VALID_CHARS_REGEX: ::Regexp
8
+ SEPARATORS: ::Regexp
9
+ ID_REGEX: ::Regexp
10
+ FISN_CHARSET: Array[String]
11
+
12
+ attr_reader issuer: String?
13
+ attr_reader description: String?
14
+
15
+ def initialize: (SecID::input fisn) -> void
16
+ def to_s: () -> String
17
+ private def self.generate_body: (Random random) -> String
18
+ private def self.generate_part: (Integer length, Random random) -> String
19
+
20
+ private
21
+
22
+ def components: () -> Hash[Symbol, untyped]
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ module SecID
2
+ class IBAN < Base
3
+ # `{ length: Integer, format: Regexp, components?: {name => [start, length]} }`, but
4
+ # the nested literal infers as a broad Hash, so it is modelled loosely.
5
+ type rule = Hash[Symbol, untyped]
6
+
7
+ COUNTRY_RULES: Hash[String, rule]
8
+ LENGTH_ONLY_COUNTRIES: Hash[String, Integer]
9
+ end
10
+ end
@@ -0,0 +1,54 @@
1
+ module SecID
2
+ # International Bank Account Number (IBAN).
3
+ class IBAN < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: ::Range[Integer]
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ NUMERIC_COUNTRY_RULES: Array[[String, rule]]
13
+
14
+ def self.supported_countries: () -> Array[String]
15
+
16
+ # country_code/bban are used unguarded after validation; typed loosely so static
17
+ # Steep and runtime RBS::Test (which sees nil for invalid) agree.
18
+ attr_reader country_code: untyped
19
+ attr_reader bban: untyped
20
+ # Optional BBAN components; typed loosely so `#components` (which conditionally
21
+ # assigns them into an inferred hash) type-checks.
22
+ attr_reader bank_code: untyped
23
+ attr_reader branch_code: untyped
24
+ attr_reader account_number: untyped
25
+ attr_reader national_check: untyped
26
+
27
+ def initialize: (SecID::input iban) -> void
28
+ def restore: () -> String
29
+ def calculate_check_digit: () -> Integer
30
+ def self.check_digit: (SecID::input id) -> Integer
31
+ private def self.generate_body: (Random random) -> String
32
+ def valid_bban_format?: () -> bool
33
+ def country_rule: () -> rule?
34
+ def known_country?: () -> bool
35
+ def to_s: () -> String
36
+ def to_pretty_s: () -> String?
37
+
38
+ private
39
+
40
+ def components: () -> Hash[Symbol, untyped]
41
+ def check_digit_width: () -> Integer
42
+ def valid_format?: () -> bool
43
+ def detect_errors: () -> Array[Symbol]
44
+ def validation_message: (Symbol code) -> String?
45
+ def extract_check_digit_and_bban: (String rest) -> void
46
+ def expected_bban_length_for_country: () -> Integer?
47
+ def check_digits?: (untyped rest, Integer? expected_bban_length) -> bool
48
+ def extract_bban_components: () -> void
49
+ def valid_bban_length_only?: () -> bool
50
+ def numeric_string_for_check: () -> String
51
+
52
+ self.@supported_countries: Array[String]
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+ module SecID
2
+ # International Securities Identification Number (ISIN).
3
+ class ISIN < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ CGS_COUNTRY_CODES: Set[String]
13
+ NSIN_COUNTRY_TYPES: Hash[String, Symbol]
14
+
15
+ # Used unguarded as non-nil after validation (indexed/looked-up); typed loosely
16
+ # so both static Steep and runtime RBS::Test (which sees nil for invalid) agree.
17
+ attr_reader country_code: untyped
18
+ attr_reader nsin: untyped
19
+
20
+ def initialize: (SecID::input isin) -> void
21
+ def to_pretty_s: () -> String?
22
+ def calculate_check_digit: () -> Integer
23
+ def self.check_digit: (SecID::input id) -> Integer
24
+ private def self.generate_body: (Random random) -> String
25
+ def to_cusip: () -> CUSIP
26
+ def cgs?: () -> bool
27
+ def sedol?: () -> bool
28
+ def wkn?: () -> bool
29
+ def valoren?: () -> bool
30
+ def to_sedol: () -> SEDOL
31
+ def to_wkn: () -> WKN
32
+ def to_valoren: () -> Valoren
33
+ def nsin_type: () -> Symbol
34
+ def to_nsin: () -> (CUSIP | SEDOL | WKN | Valoren | String | nil)
35
+
36
+ private
37
+
38
+ def components: () -> Hash[Symbol, untyped]
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ module SecID
2
+ # Legal Entity Identifier (LEI).
3
+ class LEI < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+
13
+ attr_reader lou_id: String?
14
+ attr_reader reserved: String?
15
+ attr_reader entity_id: String?
16
+
17
+ # Used unguarded after validation (`#numeric_identifier`); typed loosely so static
18
+ # Steep and runtime RBS::Test (which sees nil for invalid) agree.
19
+ def identifier: () -> untyped
20
+
21
+ def initialize: (SecID::input lei) -> void
22
+ def to_pretty_s: () -> String?
23
+ def calculate_check_digit: () -> Integer
24
+ def self.check_digit: (SecID::input id) -> Integer
25
+ private def self.generate_body: (Random random) -> String
26
+
27
+ private
28
+
29
+ def components: () -> Hash[Symbol, untyped]
30
+ def check_digit_width: () -> Integer
31
+ def numeric_identifier: () -> String
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ module SecID
2
+ # OCC Option Symbol.
3
+ class OCC < Base
4
+ FULL_NAME: String
5
+ ID_LENGTH: ::Range[Integer]
6
+ EXAMPLE: String
7
+ VALID_CHARS_REGEX: ::Regexp
8
+ SEPARATORS: ::Regexp
9
+ ID_REGEX: ::Regexp
10
+
11
+ # Used unguarded as non-nil after validation; typed loosely so static Steep and
12
+ # runtime RBS::Test (which sees nil for invalid) agree.
13
+ attr_reader underlying: untyped
14
+ attr_reader date_str: untyped
15
+ attr_reader type: untyped
16
+ attr_reader strike_mills: untyped
17
+
18
+ def self.generate: (?random: Random) -> OCC
19
+ # build/compose accept any Numeric strike (e.g. Rational) and a String or Symbol type.
20
+ def self.build: (underlying: untyped, date: String | Date, type: untyped, strike: Integer | Float | Rational | String) -> OCC
21
+ def self.compose_symbol: (untyped underlying, untyped date_str, untyped type, untyped strike_mills) -> String
22
+
23
+ def initialize: (SecID::input symbol) -> void
24
+ def normalized: () -> String
25
+ def valid?: () -> bool
26
+ def date: () -> Date?
27
+ alias date_obj date
28
+ def strike: () -> Float?
29
+ def to_s: () -> String
30
+ def to_pretty_s: () -> String?
31
+
32
+ private
33
+
34
+ # `Integer | Float | Rational` (not `Numeric`, which lacks `#*` in RBS) so the
35
+ # `when Numeric then strike * 1000` branch type-checks; String is the 8-digit form.
36
+ def self.normalize_strike_mills: (Integer | Float | Rational | String strike) -> String
37
+
38
+ def components: () -> Hash[Symbol, untyped]
39
+ def error_codes: () -> Array[Symbol]
40
+ def validation_message: (Symbol code) -> String?
41
+
42
+ @date: Date?
43
+ @strike: Float?
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ module SecID
2
+ # Immutable value object representing a matched identifier found in text.
3
+ class Match < Data
4
+ attr_reader type: Symbol
5
+ attr_reader raw: String
6
+ attr_reader range: Range[Integer]
7
+ attr_reader identifier: Base
8
+
9
+ def self.new: (type: Symbol, raw: String, range: Range[Integer], identifier: Base) -> instance
10
+ | (Symbol type, String raw, Range[Integer] range, Base identifier) -> instance
11
+ def self.[]: (type: Symbol, raw: String, range: Range[Integer], identifier: Base) -> instance
12
+ | (Symbol type, String raw, Range[Integer] range, Base identifier) -> instance
13
+ end
14
+
15
+ # Finds securities identifiers in freeform text.
16
+ #
17
+ # @api private
18
+ class Scanner
19
+ # Regex plumbing works with nilable MatchData throughout; typed `untyped` so the
20
+ # nil-unguarded capture access in the internal helpers stays free of noise.
21
+ CANDIDATE_RE: untyped
22
+
23
+ def initialize: (Array[singleton(Base)] identifier_list) -> void
24
+ def call: (String? text, ?classes: Array[singleton(Base)]?) { (Match) -> void } -> void
25
+ | (String? text, ?classes: Array[singleton(Base)]?) -> Enumerator[Match, void]
26
+ | (String? text, ?classes: Array[singleton(Base)]?) ?{ (Match) -> void } -> Enumerator[Match, void]?
27
+
28
+ private
29
+
30
+ def precompute: () -> void
31
+ def build_candidate_partitions: () -> void
32
+ def build_length_table: () -> void
33
+ def scan_text: (String input, Array[singleton(Base)] target_classes) { (Match) -> void } -> void
34
+ def identify_candidate: (untyped match_data, Array[singleton(Base)] target_classes) -> Match?
35
+ def try_classes: (String raw, String cleaned, Integer start_pos, Array[singleton(Base)] classes) -> Match?
36
+ def best_match: (String cleaned, Array[singleton(Base)] classes) -> singleton(Base)?
37
+
38
+ @classes: Array[singleton(Base)]
39
+ @fisn_classes: Array[singleton(Base)]
40
+ @occ_classes: Array[singleton(Base)]
41
+ @simple_classes: Array[singleton(Base)]
42
+ @candidates_by_length: Hash[Integer, Array[singleton(Base)]]
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ module SecID
2
+ # Stock Exchange Daily Official List (SEDOL).
3
+ class SEDOL < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ CHARACTER_WEIGHTS: Array[Integer]
13
+ GENERATE_CHARSET: Array[String]
14
+ ISIN_COUNTRY_CODES: Set[String]
15
+
16
+ # Used unguarded as non-nil after validation (`#id_digits`); typed loosely so static
17
+ # Steep and runtime RBS::Test (which sees nil for invalid) agree.
18
+ def identifier: () -> untyped
19
+
20
+ def initialize: (SecID::input sedol) -> void
21
+ def to_isin: (?String country_code) -> ISIN
22
+ def calculate_check_digit: () -> Integer
23
+ def self.check_digit: (SecID::input id) -> Integer
24
+ private def self.generate_body: (Random random) -> String
25
+
26
+ private
27
+
28
+ def components: () -> Hash[Symbol, untyped]
29
+ def weighted_sum: () -> Integer
30
+ def id_digits: () -> Array[Integer]
31
+
32
+ @id_digits: Array[Integer]
33
+ end
34
+ end
@@ -0,0 +1,29 @@
1
+ module SecID
2
+ class Valoren < Base
3
+ FULL_NAME: String
4
+ # Typed loosely: `#normalized` does `ID_LENGTH.max` and Range#max is nilable in RBS.
5
+ ID_LENGTH: untyped
6
+ EXAMPLE: String
7
+ VALID_CHARS_REGEX: ::Regexp
8
+ ID_REGEX: ::Regexp
9
+ ISIN_COUNTRY_CODES: Set[String]
10
+
11
+ attr_reader padding: String?
12
+
13
+ # Used unguarded after validation (`#normalized`/`#to_pretty_s`); typed loosely so
14
+ # static Steep and runtime RBS::Test (which sees nil for invalid) agree.
15
+ def identifier: () -> untyped
16
+
17
+ def initialize: (SecID::input valoren) -> void
18
+ def to_pretty_s: () -> String?
19
+ def to_isin: (?String country_code) -> ISIN
20
+ def normalized: () -> String
21
+ def normalize!: () -> self
22
+ def to_s: () -> String
23
+ private def self.generate_body: (Random random) -> String
24
+
25
+ private
26
+
27
+ def components: () -> Hash[Symbol, untyped]
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module SecID
2
+ VERSION: String
3
+ end
@@ -0,0 +1,15 @@
1
+ module SecID
2
+ # Wertpapierkennnummer (WKN).
3
+ class WKN < Base
4
+ FULL_NAME: String
5
+ ID_LENGTH: Integer
6
+ EXAMPLE: String
7
+ VALID_CHARS_REGEX: ::Regexp
8
+ ID_REGEX: ::Regexp
9
+ GENERATE_CHARSET: Array[String]
10
+
11
+ def initialize: (SecID::input wkn) -> void
12
+ def to_isin: (?String country_code) -> ISIN
13
+ private def self.generate_body: (Random random) -> String
14
+ end
15
+ end
data/sig/sec_id.rbs ADDED
@@ -0,0 +1,58 @@
1
+ module SecID
2
+ # Base error class for all SecID errors.
3
+ class Error < StandardError
4
+ end
5
+
6
+ # Raised for invalid format, length, or characters.
7
+ class InvalidFormatError < Error
8
+ end
9
+
10
+ # Raised when the check digit does not match the calculated value.
11
+ class InvalidCheckDigitError < Error
12
+ end
13
+
14
+ # Raised for type-specific structural errors.
15
+ class InvalidStructureError < Error
16
+ end
17
+
18
+ # Raised when multiple identifier types match and on_ambiguous: :raise is used.
19
+ class AmbiguousMatchError < Error
20
+ end
21
+
22
+ def self.[]: (Symbol key) -> singleton(Base)
23
+ def self.identifiers: () -> Array[singleton(Base)]
24
+ def self.detect: (SecID::input str) -> Array[Symbol]
25
+ def self.valid?: (SecID::input str, ?types: Array[Symbol]?) -> bool
26
+ def self.extract: (String? text, ?types: Array[Symbol]?) -> Array[Match]
27
+ def self.scan: (String? text, ?types: Array[Symbol]?) { (Match) -> void } -> void
28
+ | (String? text, ?types: Array[Symbol]?) -> Enumerator[Match, void]
29
+ def self.explain: (SecID::input str, ?types: Array[Symbol]?) -> Hash[Symbol, untyped]
30
+ def self.parse: (SecID::input str, ?types: Array[Symbol]?, on_ambiguous: :all) -> Array[Base]
31
+ | (SecID::input str, ?types: Array[Symbol]?, ?on_ambiguous: (:first | :raise)) -> Base?
32
+ | (SecID::input str, ?types: Array[Symbol]?, ?on_ambiguous: Symbol) -> untyped
33
+ # Single broad return, not per-`on_ambiguous` overloads: the shared `parse!` body calls
34
+ # `result.empty?` on the `:all` path, so precise overloads would make Steep check `.empty?`
35
+ # against the `:first`/`:raise` arm's `Base?` and fail. Widening here keeps `result` untyped.
36
+ def self.parse!: (SecID::input str, ?types: Array[Symbol]?, ?on_ambiguous: Symbol) -> (Base | Array[Base])
37
+ def self.generate: (Symbol key, ?random: Random) -> Base
38
+
39
+ # Singleton-method privacy must be declared inline (`private def self.…`); a bare
40
+ # `private` section only affects instance methods, leaving these public.
41
+ private def self.register_identifier: (singleton(Base) klass) -> void
42
+ private def self.parse_any: (SecID::input str) -> Base?
43
+ private def self.parse_from: (SecID::input str, Array[Symbol] types) -> Base?
44
+ private def self.parse_strict: (SecID::input str, Array[Symbol]? types) -> Base?
45
+ private def self.parse_all: (SecID::input str, Array[Symbol]? types) -> Array[Base]
46
+ private def self.resolve_candidates: (SecID::input str, Array[Symbol]? types) -> Array[Symbol]
47
+ private def self.ambiguous_message: (SecID::input str, Array[Symbol] candidates) -> String
48
+ private def self.parse_error_message: (SecID::input str, Array[Symbol]? types) -> String
49
+ private def self.detector: () -> Detector
50
+ private def self.scanner: () -> Scanner
51
+ private def self.identifier_map: () -> Hash[Symbol, singleton(Base)]
52
+ private def self.identifier_list: () -> Array[singleton(Base)]
53
+
54
+ self.@identifier_map: Hash[Symbol, singleton(Base)]
55
+ self.@identifier_list: Array[singleton(Base)]
56
+ self.@detector: Detector?
57
+ self.@scanner: Scanner?
58
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sec_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0
4
+ version: 6.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leonid Svyatov
@@ -9,30 +9,43 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
- description: Validate, normalize, parse, and convert securities identifiers. Auto-detect
13
- identifier type from any string. Calculate and restore check digits. Supports ISIN,
14
- CUSIP, CEI, SEDOL, FIGI, LEI, IBAN, CIK, OCC, WKN, Valoren, CFI, and FISN.
12
+ description: Validate, normalize, parse, convert, generate, and classify securities
13
+ identifiers. Auto-detect identifier type from any string. Calculate and restore
14
+ check digits. Generate format-valid identifiers as test fixtures. Decode CFI codes
15
+ to full ISO 10962:2021 classifications. Includes an opt-in ActiveModel/Rails validator
16
+ that adds no runtime dependency. Supports ISIN, CUSIP, CEI, SEDOL, FIGI, LEI, IBAN,
17
+ CIK, OCC, WKN, Valoren, CFI, FISN, BIC, and DTI.
15
18
  email:
16
19
  - leonid@svyatov.ru
17
20
  executables: []
18
21
  extensions: []
19
22
  extra_rdoc_files: []
20
23
  files:
24
+ - ".yardopts"
21
25
  - CHANGELOG.md
22
26
  - LICENSE.txt
23
27
  - MIGRATION.md
24
28
  - README.md
25
29
  - lib/sec_id.rb
30
+ - lib/sec_id/active_model.rb
26
31
  - lib/sec_id/base.rb
32
+ - lib/sec_id/bic.rb
33
+ - lib/sec_id/bic/country_codes.rb
27
34
  - lib/sec_id/cei.rb
28
35
  - lib/sec_id/cfi.rb
36
+ - lib/sec_id/cfi/attribute_set.rb
37
+ - lib/sec_id/cfi/classification.rb
38
+ - lib/sec_id/cfi/field.rb
39
+ - lib/sec_id/cfi/tables.rb
29
40
  - lib/sec_id/cik.rb
30
41
  - lib/sec_id/concerns/checkable.rb
31
- - lib/sec_id/concerns/identifier_metadata.rb
42
+ - lib/sec_id/concerns/generatable.rb
32
43
  - lib/sec_id/concerns/normalizable.rb
33
44
  - lib/sec_id/concerns/validatable.rb
34
45
  - lib/sec_id/cusip.rb
46
+ - lib/sec_id/deep_freeze.rb
35
47
  - lib/sec_id/detector.rb
48
+ - lib/sec_id/dti.rb
36
49
  - lib/sec_id/errors.rb
37
50
  - lib/sec_id/figi.rb
38
51
  - lib/sec_id/fisn.rb
@@ -41,17 +54,52 @@ files:
41
54
  - lib/sec_id/isin.rb
42
55
  - lib/sec_id/lei.rb
43
56
  - lib/sec_id/occ.rb
57
+ - lib/sec_id/railtie.rb
44
58
  - lib/sec_id/scanner.rb
45
59
  - lib/sec_id/sedol.rb
46
60
  - lib/sec_id/valoren.rb
47
61
  - lib/sec_id/version.rb
48
62
  - lib/sec_id/wkn.rb
49
63
  - sec_id.gemspec
64
+ - sig/manifest.yaml
65
+ - sig/sec_id.rbs
66
+ - sig/sec_id/base.rbs
67
+ - sig/sec_id/bic.rbs
68
+ - sig/sec_id/bic/country_codes.rbs
69
+ - sig/sec_id/cei.rbs
70
+ - sig/sec_id/cfi.rbs
71
+ - sig/sec_id/cfi/attribute_set.rbs
72
+ - sig/sec_id/cfi/classification.rbs
73
+ - sig/sec_id/cfi/field.rbs
74
+ - sig/sec_id/cfi/tables.rbs
75
+ - sig/sec_id/cik.rbs
76
+ - sig/sec_id/concerns/checkable.rbs
77
+ - sig/sec_id/concerns/generatable.rbs
78
+ - sig/sec_id/concerns/normalizable.rbs
79
+ - sig/sec_id/concerns/validatable.rbs
80
+ - sig/sec_id/cusip.rbs
81
+ - sig/sec_id/deep_freeze.rbs
82
+ - sig/sec_id/detector.rbs
83
+ - sig/sec_id/dti.rbs
84
+ - sig/sec_id/errors.rbs
85
+ - sig/sec_id/figi.rbs
86
+ - sig/sec_id/fisn.rbs
87
+ - sig/sec_id/iban.rbs
88
+ - sig/sec_id/iban/country_rules.rbs
89
+ - sig/sec_id/isin.rbs
90
+ - sig/sec_id/lei.rbs
91
+ - sig/sec_id/occ.rbs
92
+ - sig/sec_id/scanner.rbs
93
+ - sig/sec_id/sedol.rbs
94
+ - sig/sec_id/valoren.rbs
95
+ - sig/sec_id/version.rbs
96
+ - sig/sec_id/wkn.rbs
50
97
  homepage: https://github.com/svyatov/sec_id
51
98
  licenses:
52
99
  - MIT
53
100
  metadata:
54
101
  rubygems_mfa_required: 'true'
102
+ documentation_uri: https://rubydoc.info/gems/sec_id
55
103
  source_code_uri: https://github.com/svyatov/sec_id
56
104
  changelog_uri: https://github.com/svyatov/sec_id/blob/main/CHANGELOG.md
57
105
  bug_tracker_uri: https://github.com/svyatov/sec_id/issues
@@ -69,8 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
117
  - !ruby/object:Gem::Version
70
118
  version: '0'
71
119
  requirements: []
72
- rubygems_version: 4.0.6
120
+ rubygems_version: 4.0.12
73
121
  specification_version: 4
74
122
  summary: A Ruby toolkit for securities identifiers — validate, parse, normalize, detect,
75
- and convert.
123
+ convert, generate, and classify.
76
124
  test_files: []