holidays 5.4.0 → 5.5.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Makefile +1 -1
  4. data/README.md +6 -6
  5. data/Rakefile +7 -8
  6. data/lib/generated_definitions/REGIONS.rb +3 -1
  7. data/lib/generated_definitions/ar.rb +0 -6
  8. data/lib/generated_definitions/at.rb +0 -6
  9. data/lib/generated_definitions/au.rb +6 -9
  10. data/lib/generated_definitions/be_fr.rb +0 -6
  11. data/lib/generated_definitions/be_nl.rb +0 -6
  12. data/lib/generated_definitions/bg.rb +0 -6
  13. data/lib/generated_definitions/br.rb +0 -6
  14. data/lib/generated_definitions/ca.rb +0 -6
  15. data/lib/generated_definitions/ch.rb +0 -6
  16. data/lib/generated_definitions/cl.rb +0 -6
  17. data/lib/generated_definitions/cr.rb +0 -6
  18. data/lib/generated_definitions/cz.rb +0 -6
  19. data/lib/generated_definitions/de.rb +0 -6
  20. data/lib/generated_definitions/dk.rb +0 -6
  21. data/lib/generated_definitions/ecb_target.rb +0 -6
  22. data/lib/generated_definitions/el.rb +0 -6
  23. data/lib/generated_definitions/es.rb +0 -6
  24. data/lib/generated_definitions/europe.rb +0 -6
  25. data/lib/generated_definitions/federal_reserve.rb +0 -6
  26. data/lib/generated_definitions/fedex.rb +0 -6
  27. data/lib/generated_definitions/fi.rb +0 -6
  28. data/lib/generated_definitions/fr.rb +0 -6
  29. data/lib/generated_definitions/gb.rb +0 -6
  30. data/lib/generated_definitions/hk.rb +0 -6
  31. data/lib/generated_definitions/hr.rb +0 -6
  32. data/lib/generated_definitions/hu.rb +0 -6
  33. data/lib/generated_definitions/ie.rb +0 -6
  34. data/lib/generated_definitions/is.rb +0 -6
  35. data/lib/generated_definitions/it.rb +0 -6
  36. data/lib/generated_definitions/jp.rb +0 -6
  37. data/lib/generated_definitions/kr.rb +15 -225
  38. data/lib/generated_definitions/li.rb +0 -6
  39. data/lib/generated_definitions/lt.rb +0 -6
  40. data/lib/generated_definitions/lu.rb +0 -6
  41. data/lib/generated_definitions/ma.rb +0 -6
  42. data/lib/generated_definitions/mx.rb +0 -6
  43. data/lib/generated_definitions/my.rb +0 -6
  44. data/lib/generated_definitions/nerc.rb +0 -6
  45. data/lib/generated_definitions/nl.rb +0 -6
  46. data/lib/generated_definitions/no.rb +0 -6
  47. data/lib/generated_definitions/north_america.rb +0 -6
  48. data/lib/generated_definitions/nyse.rb +1 -7
  49. data/lib/generated_definitions/nz.rb +0 -6
  50. data/lib/generated_definitions/pe.rb +0 -6
  51. data/lib/generated_definitions/ph.rb +0 -6
  52. data/lib/generated_definitions/pl.rb +0 -6
  53. data/lib/generated_definitions/pt.rb +0 -6
  54. data/lib/generated_definitions/ro.rb +0 -6
  55. data/lib/generated_definitions/scandinavia.rb +0 -6
  56. data/lib/generated_definitions/se.rb +0 -6
  57. data/lib/generated_definitions/sg.rb +0 -6
  58. data/lib/generated_definitions/si.rb +0 -6
  59. data/lib/generated_definitions/sk.rb +0 -6
  60. data/lib/generated_definitions/tn.rb +0 -6
  61. data/lib/generated_definitions/united_nations.rb +0 -6
  62. data/lib/generated_definitions/ups.rb +0 -6
  63. data/lib/generated_definitions/us.rb +0 -6
  64. data/lib/generated_definitions/ve.rb +0 -6
  65. data/lib/generated_definitions/vi.rb +5 -10
  66. data/lib/generated_definitions/za.rb +0 -6
  67. data/lib/holidays.rb +0 -1
  68. data/lib/holidays/date_calculator/lunar_date.rb +371 -0
  69. data/lib/holidays/definition/context/function_processor.rb +20 -15
  70. data/lib/holidays/definition/context/generator.rb +0 -6
  71. data/lib/holidays/definition/context/load.rb +29 -0
  72. data/lib/holidays/definition/context/merger.rb +0 -4
  73. data/lib/holidays/definition/generator/regions.rb +50 -0
  74. data/lib/holidays/definition/repository/cache.rb +20 -7
  75. data/lib/holidays/definition/repository/proc_result_cache.rb +1 -1
  76. data/lib/holidays/definition/repository/regions.rb +23 -13
  77. data/lib/holidays/definition/validator/custom_method.rb +1 -1
  78. data/lib/holidays/definition/validator/region.rb +2 -9
  79. data/lib/holidays/factory/date_calculator.rb +5 -0
  80. data/lib/holidays/factory/definition.rb +17 -1
  81. data/lib/holidays/factory/finder.rb +1 -1
  82. data/lib/holidays/finder/context/between.rb +3 -0
  83. data/lib/holidays/finder/context/parse_options.rb +53 -52
  84. data/lib/holidays/finder/context/search.rb +23 -6
  85. data/lib/holidays/finder/rules/in_region.rb +1 -1
  86. data/lib/holidays/load_all_definitions.rb +9 -0
  87. data/lib/holidays/version.rb +1 -1
  88. data/test/data/test_invalid_region.rb +15 -0
  89. data/test/data/test_region.rb +15 -0
  90. data/test/defs/test_defs_au.rb +11 -1
  91. data/test/defs/test_defs_kr.rb +15 -12
  92. data/test/defs/test_defs_nyse.rb +5 -0
  93. data/test/defs/test_defs_vi.rb +6 -4
  94. data/test/holidays/date_calculator/test_lunar_date.rb +89 -0
  95. data/test/holidays/definition/context/test_function_processor.rb +47 -23
  96. data/test/holidays/definition/context/test_generator.rb +3 -3
  97. data/test/holidays/definition/context/test_load.rb +37 -0
  98. data/test/holidays/definition/generator/test_regions.rb +97 -0
  99. data/test/holidays/definition/repository/test_cache.rb +47 -6
  100. data/test/holidays/definition/repository/test_proc_result_cache.rb +7 -0
  101. data/test/holidays/definition/repository/test_regions.rb +31 -13
  102. data/test/holidays/definition/validator/test_custom_method.rb +5 -0
  103. data/test/holidays/definition/validator/test_region.rb +7 -12
  104. data/test/holidays/factory/test_date_calculator.rb +5 -0
  105. data/test/holidays/factory/test_definition.rb +9 -0
  106. data/test/holidays/finder/context/test_parse_options.rb +102 -33
  107. data/test/holidays/finder/context/test_search.rb +45 -16
  108. data/test/integration/test_available_regions.rb +1 -1
  109. data/test/integration/test_custom_year_range_holidays.rb +0 -1
  110. data/test/integration/test_holidays.rb +3 -3
  111. data/test/integration/test_multiple_regions.rb +0 -1
  112. metadata +16 -3
@@ -9,54 +9,59 @@ module Holidays
9
9
  @proc_result_cache_repo = proc_result_cache_repo
10
10
  end
11
11
 
12
- def call(year, month, day, func_id, desired_func_args, func_modifier = nil)
13
- validate!(year, month, day, func_id, desired_func_args)
12
+ def call(input, func_id, desired_func_args, func_modifier = nil)
13
+ validate!(input, func_id, desired_func_args)
14
14
 
15
15
  function = @custom_methods_repo.find(func_id)
16
16
  raise Holidays::FunctionNotFound.new("Unable to find function with id '#{func_id}'") if function.nil?
17
17
 
18
- calculate(year, month, function, parse_arguments(year, month, day, desired_func_args), func_modifier)
18
+ calculate(input, function, parse_arguments(input, desired_func_args), func_modifier)
19
19
  end
20
20
 
21
21
  private
22
22
 
23
- VALID_ARGUMENTS = [:year, :month, :day, :date]
23
+ VALID_ARGUMENTS = [:year, :month, :day, :date, :region]
24
24
 
25
- def validate!(year, month, day, func_id, desired_func_args)
25
+ def validate!(input, func_id, desired_func_args)
26
26
  raise ArgumentError if desired_func_args.nil? || desired_func_args.empty?
27
27
 
28
28
  desired_func_args.each do |name|
29
29
  raise ArgumentError unless VALID_ARGUMENTS.include?(name)
30
30
  end
31
31
 
32
- raise ArgumentError if desired_func_args.include?(:year) && !year.is_a?(Integer)
33
- raise ArgumentError if desired_func_args.include?(:month) && (month < 0 || month > 12)
34
- raise ArgumentError if desired_func_args.include?(:day) && (day < 1 || day > 31)
32
+ raise ArgumentError if desired_func_args.include?(:year) && !input[:year].is_a?(Integer)
33
+ raise ArgumentError if desired_func_args.include?(:month) && (input[:month] < 0 || input[:month] > 12)
34
+ raise ArgumentError if desired_func_args.include?(:day) && (input[:day] < 1 || input[:day] > 31)
35
+ raise ArgumentError if desired_func_args.include?(:region) && !input[:region].is_a?(Symbol)
35
36
  end
36
37
 
37
- def parse_arguments(year, month, day, target_args)
38
+ def parse_arguments(input, target_args)
38
39
  args = []
39
40
 
40
41
  if target_args.include?(:year)
41
- args << year
42
+ args << input[:year]
42
43
  end
43
44
 
44
45
  if target_args.include?(:month)
45
- args << month
46
+ args << input[:month]
46
47
  end
47
48
 
48
49
  if target_args.include?(:day)
49
- args << day
50
+ args << input[:day]
50
51
  end
51
52
 
52
53
  if target_args.include?(:date)
53
- args << Date.civil(year, month, day)
54
+ args << Date.civil(input[:year], input[:month], input[:day])
55
+ end
56
+
57
+ if target_args.include?(:region)
58
+ args << input[:region]
54
59
  end
55
60
 
56
61
  args
57
62
  end
58
63
 
59
- def calculate(year, month, id, args, modifier)
64
+ def calculate(input, id, args, modifier)
60
65
  result = @proc_result_cache_repo.lookup(id, *args)
61
66
  if result.kind_of?(Date)
62
67
  if modifier
@@ -64,7 +69,7 @@ module Holidays
64
69
  end
65
70
  elsif result.is_a?(Integer)
66
71
  begin
67
- result = Date.civil(year, month, result)
72
+ result = Date.civil(input[:year], input[:month], result)
68
73
  rescue ArgumentError
69
74
  raise Holidays::InvalidFunctionResponse.new("invalid day response from custom method call resulting in invalid date. Result: '#{result}'")
70
75
  end
@@ -235,12 +235,6 @@ module Holidays
235
235
  #
236
236
  # Definitions loaded: #{files.join(', ')}
237
237
  #
238
- # To use the definitions in this file, load it right after you load the
239
- # Holiday gem:
240
- #
241
- # require 'holidays'
242
- # require '#{DEFINITIONS_PATH}/#{module_name.to_s.downcase}'
243
- #
244
238
  # All the definitions are available at https://github.com/holidays/holidays
245
239
  module #{module_name.to_s.upcase} # :nodoc:
246
240
  def self.defined_regions
@@ -0,0 +1,29 @@
1
+ module Holidays
2
+ module Definition
3
+ module Context
4
+ class Load
5
+ def initialize(definition_merger, full_definitions_path)
6
+ @definition_merger = definition_merger
7
+ @full_definitions_path = full_definitions_path
8
+ end
9
+
10
+ def call(region)
11
+ region_definition_file = "#{@full_definitions_path}/#{region}"
12
+ require region_definition_file
13
+
14
+ target_region_module = Module.const_get("Holidays").const_get(region.upcase)
15
+
16
+ @definition_merger.call(
17
+ target_region_module.defined_regions,
18
+ target_region_module.holidays_by_month,
19
+ target_region_module.custom_methods,
20
+ )
21
+
22
+ target_region_module.defined_regions
23
+ rescue NameError, LoadError => e
24
+ raise UnknownRegionError.new(e), "Could not load region prefix: #{region.to_s}"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -2,10 +2,6 @@ module Holidays
2
2
  module Definition
3
3
  module Context
4
4
  # Merge a new set of definitions into the Holidays module.
5
- #
6
- # This method is automatically called when including holiday definition
7
- # files. This is accomplished because the Generator class generates the
8
- # definition source with this class explicitly.
9
5
  class Merger
10
6
  def initialize(holidays_by_month_repo, regions_repo, custom_methods_repo)
11
7
  @holidays_repo = holidays_by_month_repo
@@ -0,0 +1,50 @@
1
+ module Holidays
2
+ module Definition
3
+ module Generator
4
+ class Regions
5
+ def call(regions)
6
+ validate!(regions)
7
+
8
+ <<-EOF
9
+ # encoding: utf-8
10
+ module Holidays
11
+ REGIONS = #{to_array(regions)}
12
+
13
+ PARENT_REGION_LOOKUP = #{generate_parent_lookup(regions)}
14
+ end
15
+ EOF
16
+ end
17
+
18
+ private
19
+
20
+ def validate!(regions)
21
+ raise ArgumentError.new("regions cannot be missing") if regions.nil?
22
+ raise ArgumentError.new("regions must be a hash") unless regions.is_a?(Hash)
23
+ raise ArgumentError.new("regions cannot be empty") if regions.empty?
24
+ end
25
+
26
+ def to_array(regions)
27
+ all_regions = []
28
+
29
+ regions.each do |region, subregions|
30
+ all_regions << subregions
31
+ end
32
+
33
+ all_regions.flatten.uniq
34
+ end
35
+
36
+ def generate_parent_lookup(regions)
37
+ lookup = {}
38
+
39
+ regions.each do |region, subregions|
40
+ subregions.each do |s|
41
+ lookup[s] = region unless lookup.has_key?(s)
42
+ end
43
+ end
44
+
45
+ lookup
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -10,16 +10,18 @@ module Holidays
10
10
  raise ArgumentError unless cache_data
11
11
 
12
12
  @cache_range[options] = start_date..end_date
13
- @cache[options] = cache_data
13
+ @cache[options] = cache_data.group_by { |holiday| holiday[:date] }
14
14
  end
15
15
 
16
16
  def find(start_date, end_date, options)
17
- if range = @cache_range[options]
18
- if range.begin <= start_date && range.end >= end_date
19
- return @cache[options].select do |holiday|
20
- holiday[:date] >= start_date && holiday[:date] <= end_date
21
- end
22
- end
17
+ return nil unless in_cache_range?(start_date, end_date, options)
18
+
19
+ if start_date == end_date
20
+ @cache[options].fetch(start_date, [])
21
+ else
22
+ @cache[options].select do |date, holidays|
23
+ date >= start_date && date <= end_date
24
+ end.flat_map { |date, holidays| holidays }
23
25
  end
24
26
  end
25
27
 
@@ -27,6 +29,17 @@ module Holidays
27
29
  @cache = {}
28
30
  @cache_range = {}
29
31
  end
32
+
33
+ private
34
+
35
+ def in_cache_range?(start_date, end_date, options)
36
+ range = @cache_range[options]
37
+ if range
38
+ range.begin <= start_date && range.end >= end_date
39
+ else
40
+ false
41
+ end
42
+ end
30
43
  end
31
44
  end
32
45
  end
@@ -38,7 +38,7 @@ module Holidays
38
38
  def validate!(function, function_arguments)
39
39
  raise ArgumentError.new("function must be a proc") unless function.is_a?(Proc)
40
40
  function_arguments.each do |arg|
41
- raise ArgumentError.new("function arguments '#{function_arguments}' must contain either integers or dates") unless arg.is_a?(Integer) || arg.is_a?(Date)
41
+ raise ArgumentError.new("function arguments '#{function_arguments}' must contain either integers or dates") unless arg.is_a?(Integer) || arg.is_a?(Date) || arg.is_a?(Symbol)
42
42
  end
43
43
  end
44
44
 
@@ -2,12 +2,27 @@ module Holidays
2
2
  module Definition
3
3
  module Repository
4
4
  class Regions
5
- def initialize
6
- @regions = []
5
+ def initialize(all_generated_regions, parent_region_lookup)
6
+ @loaded_regions = []
7
+ @all_generated_regions = all_generated_regions
8
+ @parent_region_lookup = parent_region_lookup
7
9
  end
8
10
 
9
- def all
10
- @regions
11
+ def all_generated
12
+ @all_generated_regions
13
+ end
14
+
15
+ def parent_region_lookup(r)
16
+ @parent_region_lookup[r]
17
+ end
18
+
19
+ def all_loaded
20
+ @loaded_regions
21
+ end
22
+
23
+ def loaded?(region)
24
+ raise ArgumentError unless region.is_a?(Symbol)
25
+ @loaded_regions.include?(region)
11
26
  end
12
27
 
13
28
  def add(regions)
@@ -17,18 +32,13 @@ module Holidays
17
32
  raise ArgumentError unless region.is_a?(Symbol)
18
33
  end
19
34
 
20
- @regions = @regions | regions
21
- @regions.uniq!
22
- end
23
-
24
- def exists?(region)
25
- raise ArgumentError unless region.is_a?(Symbol)
26
- @regions.include?(region)
35
+ @loaded_regions = @loaded_regions | regions
36
+ @loaded_regions.uniq!
27
37
  end
28
38
 
29
39
  def search(prefix)
30
- raise ArgumentError unless prefix.is_a?(String)
31
- @regions.select { |region| region.to_s =~ Regexp.new("^#{prefix}") }
40
+ raise ArgumentError unless prefix.is_a?(Symbol)
41
+ @loaded_regions.select { |region| region.to_s =~ Regexp.new("^#{prefix}") }
32
42
  end
33
43
  end
34
44
  end
@@ -2,7 +2,7 @@ module Holidays
2
2
  module Definition
3
3
  module Validator
4
4
  class CustomMethod
5
- VALID_ARGUMENTS = ["date", "year", "month", "day"]
5
+ VALID_ARGUMENTS = ["date", "year", "month", "day", "region"]
6
6
 
7
7
  def valid?(m)
8
8
  valid_name?(m[:name]) &&
@@ -12,8 +12,8 @@ module Holidays
12
12
  region = find_wildcard_base(r)
13
13
 
14
14
  (region == :any ||
15
- @regions_repo.exists?(region) ||
16
- region_in_static_definitions?(region))
15
+ @regions_repo.loaded?(region) ||
16
+ @regions_repo.all_generated.include?(region))
17
17
  end
18
18
 
19
19
  private
@@ -30,13 +30,6 @@ module Holidays
30
30
 
31
31
  base.to_sym
32
32
  end
33
-
34
- def region_in_static_definitions?(region)
35
- static_regions_definition = "#{DEFINITIONS_PATH}/REGIONS.rb"
36
- require static_regions_definition
37
-
38
- Holidays::REGIONS.include?(region)
39
- end
40
33
  end
41
34
  end
42
35
  end
@@ -1,6 +1,7 @@
1
1
  require 'holidays/date_calculator/easter'
2
2
  require 'holidays/date_calculator/weekend_modifier'
3
3
  require 'holidays/date_calculator/day_of_month'
4
+ require 'holidays/date_calculator/lunar_date'
4
5
 
5
6
  module Holidays
6
7
  module Factory
@@ -24,6 +25,10 @@ module Holidays
24
25
  end
25
26
 
26
27
  class << self
28
+ def lunar_date
29
+ Holidays::DateCalculator::LunarDate.new
30
+ end
31
+
27
32
  def weekend_modifier
28
33
  Holidays::DateCalculator::WeekendModifier.new
29
34
  end
@@ -1,8 +1,10 @@
1
1
  require 'holidays/definition/context/generator'
2
2
  require 'holidays/definition/context/merger'
3
3
  require 'holidays/definition/context/function_processor'
4
+ require 'holidays/definition/context/load'
4
5
  require 'holidays/definition/decorator/custom_method_proc'
5
6
  require 'holidays/definition/decorator/custom_method_source'
7
+ require 'holidays/definition/generator/regions'
6
8
  require 'holidays/definition/parser/custom_method'
7
9
  require 'holidays/definition/repository/holidays_by_month'
8
10
  require 'holidays/definition/repository/regions'
@@ -76,7 +78,10 @@ module Holidays
76
78
  end
77
79
 
78
80
  def regions_repository
79
- @regions_repo ||= Holidays::Definition::Repository::Regions.new
81
+ @regions_repo ||= Holidays::Definition::Repository::Regions.new(
82
+ Holidays::REGIONS,
83
+ Holidays::PARENT_REGION_LOOKUP,
84
+ )
80
85
  end
81
86
 
82
87
  def cache_repository
@@ -90,6 +95,17 @@ module Holidays
90
95
  def custom_methods_repository
91
96
  @custom_methods_repository ||= Holidays::Definition::Repository::CustomMethods.new
92
97
  end
98
+
99
+ def regions_generator
100
+ Holidays::Definition::Generator::Regions.new
101
+ end
102
+
103
+ def loader
104
+ Holidays::Definition::Context::Load.new(
105
+ merger,
106
+ Holidays::FULL_DEFINITIONS_PATH,
107
+ )
108
+ end
93
109
  end
94
110
  end
95
111
  end
@@ -48,7 +48,7 @@ module Holidays
48
48
  Holidays::Finder::Context::ParseOptions.new(
49
49
  Factory::Definition.regions_repository,
50
50
  Factory::Definition.region_validator,
51
- Factory::Definition.merger,
51
+ Factory::Definition.loader,
52
52
  )
53
53
  end
54
54
 
@@ -15,6 +15,9 @@ module Holidays
15
15
  dates_driver = @dates_driver_builder.call(start_date, end_date)
16
16
 
17
17
  holidays = []
18
+
19
+ #FIXME Why are we calling the options_parser to convert the observed/informal
20
+ # symbols to bool and then...converting them back? O_o
18
21
  opts = gather_options(observed, informal)
19
22
 
20
23
  holidays = @definition_search.call(dates_driver, regions, opts)
@@ -2,10 +2,10 @@ module Holidays
2
2
  module Finder
3
3
  module Context
4
4
  class ParseOptions
5
- def initialize(regions_repo, region_validator, definition_merger)
5
+ def initialize(regions_repo, region_validator, definition_loader)
6
6
  @regions_repo = regions_repo
7
7
  @region_validator = region_validator
8
- @definition_merger = definition_merger
8
+ @definition_loader = definition_loader
9
9
  end
10
10
 
11
11
  # Returns [(arr)regions, (bool)observed, (bool)informal]
@@ -31,42 +31,57 @@ module Holidays
31
31
  # of its available sub regions.
32
32
  def parse_regions!(regions)
33
33
  regions = [regions] unless regions.kind_of?(Array)
34
- return [:any] if regions.empty?
35
34
 
36
- regions = regions.collect { |r| r.to_sym }
35
+ if regions.empty?
36
+ regions = [:any]
37
+ else
38
+ regions = regions.collect { |r| r.to_sym }
39
+ end
37
40
 
38
41
  validate!(regions)
39
42
 
40
- # Found sub region wild-card
41
- regions.delete_if do |r|
42
- if r.to_s =~ /_$/
43
- load_containing_region(r.to_s)
44
- regions << @regions_repo.search(r.to_s)
45
- true
46
- end
47
- end
43
+ loaded_regions = []
44
+
45
+ #FIXME I don't know what this means or why we have it! I'm reluctant to remove it
46
+ # at this time without understanding more. -PP 2017/3/29
47
+ #
48
+ # special case for north_america/US cross-linking
49
+ load_region!(:north_america) if regions.include?(:us)
48
50
 
49
- regions.flatten!
50
-
51
- load_definition_data("north_america") if regions.include?(:us) # special case for north_america/US cross-linking
52
-
53
- regions.each do |region|
54
- unless region == :any || @regions_repo.exists?(region)
55
- begin
56
- load_definition_data(region.to_s)
57
- rescue NameError, LoadError => e
58
- # This could be a sub region that does not have any holiday
59
- # definitions of its own; try to load the containing region instead.
60
- if region.to_s =~ /_/
61
- load_containing_region(region.to_s)
62
- else
63
- raise UnknownRegionError.new(e), "Could not load #{region.to_s}"
51
+ if regions.include?(:any)
52
+ @regions_repo.all_generated.each do |r|
53
+ if @regions_repo.loaded?(r)
54
+ loaded_regions << r
55
+ next
56
+ end
57
+
58
+ target = @regions_repo.parent_region_lookup(r)
59
+ load_region!(target)
60
+
61
+ loaded_regions << r
62
+ end
63
+ else
64
+ regions.each do |r|
65
+ if is_wildcard?(r)
66
+ loaded_regions << load_wildcard_parent!(r)
67
+ else
68
+ parent = @regions_repo.parent_region_lookup(r)
69
+
70
+ target = parent || r
71
+
72
+ if @regions_repo.loaded?(target)
73
+ loaded_regions << r
74
+ next
64
75
  end
76
+
77
+ load_region!(target)
78
+
79
+ loaded_regions << r
65
80
  end
66
81
  end
67
82
  end
68
83
 
69
- regions
84
+ loaded_regions.flatten.compact.uniq
70
85
  end
71
86
 
72
87
  def validate!(regions)
@@ -75,33 +90,19 @@ module Holidays
75
90
  end
76
91
  end
77
92
 
78
- # Derive the containing region from a sub region wild-card or a sub region
79
- # and load its definition. (Common code factored out from parse_regions)
80
- def load_containing_region(sub_reg)
81
- prefix = sub_reg.split('_').first
82
-
83
- return if @regions_repo.exists?(prefix.to_sym)
84
-
85
- begin
86
- load_definition_data(prefix)
87
- rescue NameError, LoadError => e
88
- raise UnknownRegionError.new(e), "Could not load region prefix: #{prefix.to_s}, original subregion: #{sub_reg.to_s}"
89
- end
93
+ def is_wildcard?(r)
94
+ r.to_s =~ /_$/
90
95
  end
91
96
 
92
- def load_definition_data(region)
93
- # Lazy loading of definition files. We verify the region doesn't
94
- # contain malicious stuff in the initial validation.
95
- region_definition_file = "#{FULL_DEFINITIONS_PATH}/#{region}"
96
- require region_definition_file
97
-
98
- target_region_module = Module.const_get("Holidays").const_get(region.upcase)
97
+ def load_wildcard_parent!(wildcard_region)
98
+ prefix = wildcard_region.to_s.split('_').first.to_sym
99
+ load_region!(prefix)
100
+ end
99
101
 
100
- @definition_merger.call(
101
- target_region_module.defined_regions,
102
- target_region_module.holidays_by_month,
103
- target_region_module.custom_methods,
104
- )
102
+ def load_region!(r)
103
+ @definition_loader.call(r)
104
+ rescue NameError, LoadError => e
105
+ raise UnknownRegionError.new(e), "Could not load region: #{r}"
105
106
  end
106
107
  end
107
108
  end