From ad8c14bd4440145eebcfbaca1b4f42e39a72ebf2 Mon Sep 17 00:00:00 2001 From: Pan Thomakos Date: Mon, 29 Apr 2024 19:59:43 -0700 Subject: [PATCH] Add ostruct for Rake incompatibility Also upgrade RuboCop and some formatting to fix errors. Fixes #108 --- .github/workflows/ci.yml | 2 +- .rubocop.yml | 29 ++++++++++++++++++++++----- CHANGES.markdown | 2 ++ lib/timezone/error.rb | 6 ++++++ lib/timezone/loader.rb | 4 ++-- lib/timezone/lookup.rb | 5 +++-- lib/timezone/lookup/geonames.rb | 1 + lib/timezone/lookup/google.rb | 5 +++-- lib/timezone/parser.rb | 9 +++++---- lib/timezone/version.rb | 2 +- lib/timezone/zone.rb | 1 - test/timezone/lookup/test_geonames.rb | 25 ++++++++++++++--------- test/timezone/lookup/test_google.rb | 9 +++++++-- test/timezone/lookup/test_test.rb | 1 + test/timezone/test_lookup.rb | 10 ++++----- timezone.gemspec | 10 +++++---- 16 files changed, 83 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38fcca40..7b4dcbf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2'] + ruby-version: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3'] steps: - uses: actions/checkout@v2 diff --git a/.rubocop.yml b/.rubocop.yml index 795474df..61eddbe6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,8 +1,12 @@ +require: rubocop-performance + AllCops: - TargetRubyVersion: 2.2 + TargetRubyVersion: 2.4 + NewCops: enable + SuggestExtensions: false -Layout/AlignParameters: - EnforcedStyle: with_fixed_indentation +Gemspec/RequiredRubyVersion: + Enabled: false Layout/EmptyLineBetweenDefs: Enabled: true @@ -10,6 +14,9 @@ Layout/EmptyLineBetweenDefs: Layout/MultilineMethodCallIndentation: EnforcedStyle: indented +Layout/ParameterAlignment: + EnforcedStyle: with_fixed_indentation + Layout/SpaceAfterComma: Enabled: true @@ -23,6 +30,9 @@ Layout/SpaceBeforeSemicolon: Enabled: true +Lint/MissingSuper: + Enabled: false + Lint/DuplicateMethods: Enabled: true @@ -39,7 +49,7 @@ Metrics/ClassLength: # Offense count: 13 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes. # URISchemes: http, https -Metrics/LineLength: +Layout/LineLength: Max: 80 Metrics/MethodLength: @@ -85,12 +95,21 @@ Style/NumericLiterals: Style/PreferredHashMethods: Enabled: true +Style/RedundantArgument: + Enabled: false + +Style/RedundantFetchBlock: + Enabled: false + Style/RedundantReturn: Enabled: true Style/RedundantSelf: Enabled: true +Style/SafeNavigation: + Enabled: false + Style/SingleLineMethods: Enabled: false @@ -103,7 +122,7 @@ Style/StringLiterals: Style/TrivialAccessors: Enabled: true -Style/UnneededPercentQ: +Style/RedundantPercentQ: Enabled: true Style/DateTime: diff --git a/CHANGES.markdown b/CHANGES.markdown index 7a2d1db5..5c6b0696 100644 --- a/CHANGES.markdown +++ b/CHANGES.markdown @@ -1,5 +1,7 @@ # master (unreleased) +* Fix Rake 13/OpenStruct incompatibility ([@panthomakos][]) + # 1.3.25 * Updated with `tzdata-2024a` ([@panthomakos][]) diff --git a/lib/timezone/error.rb b/lib/timezone/error.rb index 39a52bed..826c7e3d 100644 --- a/lib/timezone/error.rb +++ b/lib/timezone/error.rb @@ -12,16 +12,22 @@ module Timezone module Error # Top-level error. All other timezone errors subclass this one. class Base < StandardError; end + # Indicates an invalid timezone name. class InvalidZone < Base; end + # Indicates a lookup failure. class Lookup < Base; end + # Indicates an error during lookup using the geonames API. class GeoNames < Lookup; end + # Indicates an error during lookup using the google API. class Google < Lookup; end + # Indicates a missing stub during a test lookup. class Test < Lookup; end + # Indicates an invalid configuration. class InvalidConfig < Base; end end diff --git a/lib/timezone/loader.rb b/lib/timezone/loader.rb index 9bda5ea9..fb69c703 100644 --- a/lib/timezone/loader.rb +++ b/lib/timezone/loader.rb @@ -2,10 +2,10 @@ require 'timezone/error' -module Timezone # rubocop:disable Style/Documentation +module Timezone # Responsible for loading and parsing timezone data from files. module Loader - ZONE_FILE_PATH = File.expand_path(File.dirname(__FILE__) + '/../../data') + ZONE_FILE_PATH = File.expand_path("#{File.dirname(__FILE__)}/../../data") SOURCE_BIT = 0 @rules = {} # cache of loaded rules diff --git a/lib/timezone/lookup.rb b/lib/timezone/lookup.rb index 29886446..a323b5fe 100644 --- a/lib/timezone/lookup.rb +++ b/lib/timezone/lookup.rb @@ -4,12 +4,13 @@ require 'timezone/lookup/google' require 'timezone/lookup/test' require 'timezone/net_http_client' +require 'ostruct' module Timezone # Configure timezone lookups. module Lookup class << self - MISSING_LOOKUP = 'No lookup configured'.freeze + MISSING_LOOKUP = 'No lookup configured' private_constant :MISSING_LOOKUP # Returns the lookup object @@ -45,7 +46,7 @@ class OptionSetter test: ::Timezone::Lookup::Test }.freeze - INVALID_LOOKUP = 'Invalid lookup specified'.freeze + INVALID_LOOKUP = 'Invalid lookup specified' attr_reader :config diff --git a/lib/timezone/lookup/geonames.rb b/lib/timezone/lookup/geonames.rb index ccd6ae0e..1d65ddb1 100644 --- a/lib/timezone/lookup/geonames.rb +++ b/lib/timezone/lookup/geonames.rb @@ -55,6 +55,7 @@ def get_timezone_id(data) return unless data['gmtOffset'].is_a? Numeric return 'Etc/UTC' if data['gmtOffset'].zero? + "Etc/GMT#{format('%+d', -data['gmtOffset'])}" end diff --git a/lib/timezone/lookup/google.rb b/lib/timezone/lookup/google.rb index 56466399..76c522a3 100644 --- a/lib/timezone/lookup/google.rb +++ b/lib/timezone/lookup/google.rb @@ -14,7 +14,7 @@ module Lookup class Google < ::Timezone::Lookup::Basic # Indicates that no time zone data could be found for the specified # . This can occur if the query is incomplete or ambiguous. - NO_TIMEZONE_INFORMATION = 'ZERO_RESULTS'.freeze + NO_TIMEZONE_INFORMATION = 'ZERO_RESULTS' def initialize(config) if config.api_key.nil? @@ -34,7 +34,8 @@ def lookup(lat, long) raise(Timezone::Error::Google, '403 Forbidden') end - return unless response.code =~ /^2\d\d$/ + return unless /^2\d\d$/.match?(response.code) + data = JSON.parse(response.body) return if data['status'] == NO_TIMEZONE_INFORMATION diff --git a/lib/timezone/parser.rb b/lib/timezone/parser.rb index 961823ac..119051e5 100644 --- a/lib/timezone/parser.rb +++ b/lib/timezone/parser.rb @@ -9,7 +9,7 @@ class Parser MIN_YEAR = -500 MAX_YEAR = 2039 - LINE = /\s*(.+)\s*=\s*(.+)\s*isdst=(\d+)\s*gmtoff=([\+\-]*\d+)/ + LINE = /\s*(.+)\s*=\s*(.+)\s*isdst=(\d+)\s*gmtoff=([+\-]*\d+)/.freeze # Bookkeeping files that we do not want to parse. IGNORE = ['leapseconds', 'posixrules', 'tzdata.zi'].freeze @@ -25,6 +25,7 @@ def perform next if File.directory?(file) next if file.end_with?('.tab') next if IGNORE.include?(File.basename(file)) + parse(file) end end @@ -65,7 +66,7 @@ def to_s def parse_offset(offset) arity = offset.start_with?('-') ? -1 : 1 - match = offset.match(/^[\-\+](\d{2})$/) + match = offset.match(/^[\-+](\d{2})$/) arity * match[1].to_i * 60 * 60 end end @@ -76,10 +77,10 @@ def parse_offset(offset) class Line attr_accessor :source, :name, :dst, :offset - SOURCE_FORMAT = '%a %b %e %H:%M:%S %Y %Z'.freeze + SOURCE_FORMAT = '%a %b %e %H:%M:%S %Y %Z' def initialize(match) - self.source = Time.strptime(match[1] + 'C', SOURCE_FORMAT).to_i + self.source = Time.strptime("#{match[1]}C", SOURCE_FORMAT).to_i self.name = match[2].split(' ').last self.dst = match[3].to_i self.offset = match[4].to_i diff --git a/lib/timezone/version.rb b/lib/timezone/version.rb index 41213da9..dee3682e 100644 --- a/lib/timezone/version.rb +++ b/lib/timezone/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Timezone - VERSION = '1.3.25'.freeze + VERSION = '1.3.25' end diff --git a/lib/timezone/zone.rb b/lib/timezone/zone.rb index 3d2ebd56..710355f3 100644 --- a/lib/timezone/zone.rb +++ b/lib/timezone/zone.rb @@ -6,7 +6,6 @@ require 'timezone/loader' require 'timezone/error' -require 'timezone/loader' module Timezone # This object represents a real-world timezone. Each instance provides diff --git a/test/timezone/lookup/test_geonames.rb b/test/timezone/lookup/test_geonames.rb index 6e5ebdf8..92a140a7 100644 --- a/test/timezone/lookup/test_geonames.rb +++ b/test/timezone/lookup/test_geonames.rb @@ -2,6 +2,7 @@ require 'timezone/lookup/geonames' require 'minitest/autorun' +require 'ostruct' require_relative '../../http_test_client' class TestGeonames < ::Minitest::Test @@ -19,6 +20,10 @@ def etc_data } end + def lookup_file(file_name, &block) + lookup(File.open(File.join(mock_path, file_name)).read, &block) + end + def lookup(body = nil, &_block) config = OpenStruct.new config.username = 'timezone' @@ -40,23 +45,25 @@ def test_missing_username end def test_lookup - mine = lookup(File.open(mock_path + '/lat_lon_coords.txt').read) + mine = lookup_file('/lat_lon_coords.txt') assert_equal 'Australia/Adelaide', mine.lookup(*coordinates) end def test_lookup_with_etc etc_data.each do |key, data| - body = File.open(mock_path + "/lat_lon_coords_#{key}.txt").read - mine = lookup(body) { |c| c.offset_etc_zones = true } + mine = lookup_file("/lat_lon_coords_#{key}.txt") do |c| + c.offset_etc_zones = true + end assert_equal data[:name], mine.lookup(*data[:coordinates]) end end def test_wrong_offset - body = File.open(mock_path + '/lat_lon_coords_wrong_offset.txt').read - mine = lookup(body) { |c| c.offset_etc_zones = true } + mine = lookup_file('/lat_lon_coords_wrong_offset.txt') do |c| + c.offset_etc_zones = true + end assert_nil mine.lookup(*coordinates) end @@ -80,7 +87,7 @@ def assert_exception(lookup, message) end def test_api_limit - mine = lookup(File.open(mock_path + '/api_limit_reached.json').read) + mine = lookup_file('/api_limit_reached.json') assert_exception( mine, @@ -90,19 +97,19 @@ def test_api_limit end def test_invalid_latlong - mine = lookup(File.open(mock_path + '/invalid_latlong.json').read) + mine = lookup_file('/invalid_latlong.json') assert_exception(mine, 'invalid lat/lng') end def test_no_result_found - mine = lookup(File.open(mock_path + '/no_result_found.json').read) + mine = lookup_file('/no_result_found.json') assert_nil(mine.lookup(10, 10)) end def test_invalid_parameter - mine = lookup(File.open(mock_path + '/invalid_parameter.json').read) + mine = lookup_file('/invalid_parameter.json') assert_exception(mine, 'error parsing parameter') end diff --git a/test/timezone/lookup/test_google.rb b/test/timezone/lookup/test_google.rb index b8e5db34..17bef979 100644 --- a/test/timezone/lookup/test_google.rb +++ b/test/timezone/lookup/test_google.rb @@ -3,6 +3,7 @@ require 'timezone/lookup/google' require 'minitest/autorun' require 'timecop' +require 'ostruct' require_relative '../../http_test_client' class TestGoogle < ::Minitest::Test @@ -12,6 +13,10 @@ def coordinates [-34.92771808058, 138.477041423321] end + def lookup_file(file_name, &block) + lookup(File.open(File.join(mock_path, file_name)).read, &block) + end + def lookup(body = nil, &_block) config = OpenStruct.new config.api_key = 'MTIzYWJj' @@ -33,7 +38,7 @@ def test_missing_api_key end def test_google_using_lat_long_coordinates - mine = lookup(File.open(mock_path + '/google_lat_lon_coords.txt').read) + mine = lookup_file('/google_lat_lon_coords.txt') assert_equal 'Australia/Adelaide', mine.lookup(*coordinates) end @@ -76,7 +81,7 @@ def test_url_enterprise end def test_no_result_found - mine = lookup(File.open(mock_path + '/google_no_result_found.json').read) + mine = lookup_file('/google_no_result_found.json') assert_nil(mine.lookup(26.188703, -78.987053)) end diff --git a/test/timezone/lookup/test_test.rb b/test/timezone/lookup/test_test.rb index 88a87dc6..1184eca5 100644 --- a/test/timezone/lookup/test_test.rb +++ b/test/timezone/lookup/test_test.rb @@ -3,6 +3,7 @@ require 'timezone/lookup/test' require 'timezone' require 'minitest/autorun' +require 'ostruct' class TestTest < ::Minitest::Test parallelize_me! diff --git a/test/timezone/test_lookup.rb b/test/timezone/test_lookup.rb index 950e1801..e5548ee8 100644 --- a/test/timezone/test_lookup.rb +++ b/test/timezone/test_lookup.rb @@ -8,7 +8,7 @@ def test_test_config Timezone::Lookup.config(:test) assert_equal Timezone::Lookup::Test, - Timezone::Lookup.lookup.class + Timezone::Lookup.lookup.class end def test_geonames_config @@ -17,10 +17,10 @@ def test_geonames_config end assert_equal Timezone::Lookup::Geonames, - Timezone::Lookup.lookup.class + Timezone::Lookup.lookup.class assert_equal Timezone::NetHTTPClient, - Timezone::Lookup.lookup.config.request_handler + Timezone::Lookup.lookup.config.request_handler end def test_google_config @@ -29,10 +29,10 @@ def test_google_config end assert_equal Timezone::Lookup::Google, - Timezone::Lookup.lookup.class + Timezone::Lookup.lookup.class assert_equal Timezone::NetHTTPClient, - Timezone::Lookup.lookup.config.request_handler + Timezone::Lookup.lookup.config.request_handler end def test_custom_config diff --git a/timezone.gemspec b/timezone.gemspec index 97bcb3aa..809e556f 100644 --- a/timezone.gemspec +++ b/timezone.gemspec @@ -1,7 +1,6 @@ # frozen_string_literal: true -# -*- encoding: utf-8 -*- -$:.push File.expand_path('../lib', __FILE__) +$:.push File.expand_path('lib', __dir__) require 'timezone/version' Gem::Specification.new do |s| @@ -25,8 +24,11 @@ Gem::Specification.new do |s| s.rdoc_options = ['--charset=UTF-8'] s.require_paths = ['lib'] + s.add_runtime_dependency('ostruct', '~> 0.6') + s.add_development_dependency('minitest', '~> 5.8') - s.add_development_dependency('rake', '~> 12') - s.add_development_dependency('rubocop', '= 0.51') + s.add_development_dependency('rake', '~> 13') + s.add_development_dependency('rubocop', '= 1.5.1') + s.add_development_dependency('rubocop-performance', '= 1.5.1') s.add_development_dependency('timecop', '~> 0.8') end