open-meteo 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c6c6b4ccb93360c8c3f27479f8bc01cc5cc37a7d14f2ff6942d745e3bd243a8
4
- data.tar.gz: e10768db1766c5c7a48f8c68e6b15d2e367aefa0dc1bc3fc9a3fa263ce7cca93
3
+ metadata.gz: f89e15f29bfd187c332d5543477221061804b3a03e7a9773adebc62639284ab3
4
+ data.tar.gz: e2fd0e2e6c3b78a5448101ad8982da048e3532e4cb6089cfdc5b614d350184b5
5
5
  SHA512:
6
- metadata.gz: 966bbb364b37dc3e4fe846516f862216c172e242949b5b64d45afded542336f704904e6725b7fcb867de0481a23988789c4392f7480c62dc24491d62b65740fa
7
- data.tar.gz: 694c506e84309461346622763b562f34cd9f11d6fb34d7ab81b25faa7a808298cc07ecb58e02765ae9abd8a80b4122df388f9a57d657b7b63131e7cda07008ee
6
+ metadata.gz: e9e564dff02d8e28c5a3c45ef418b901da1dc5dc565231dd9608e8d0c02b8d1b340341d89ce2af7dcf7bec7f631cf38e4460a472d33cdcbec90cc5628767ef1d
7
+ data.tar.gz: f32d7c9de50a39a420aa64e8a7962f3c2fdf27f1bb04e5e86a0e2170077803ca9d31a14904fb0c839c3ef0f511e41d25667f90473501c2746f6beab717f980db
@@ -3,11 +3,13 @@ module OpenMeteo
3
3
  ##
4
4
  # The configuration for the OpenMeteo::Client.
5
5
  class Config
6
- attr_reader :host, :logger
6
+ attr_reader :api_key, :host, :logger, :timeouts
7
7
 
8
- def initialize(host: nil, logger: nil)
8
+ def initialize(api_key: nil, host: nil, logger: nil, timeouts: nil)
9
+ @api_key = api_key || OpenMeteo.configuration.api_key
9
10
  @host = host || OpenMeteo.configuration.host
10
11
  @logger = logger || OpenMeteo.configuration.logger
12
+ @timeouts = timeouts || OpenMeteo.configuration.timeouts
11
13
  end
12
14
 
13
15
  def url
@@ -3,7 +3,7 @@ module OpenMeteo
3
3
  ##
4
4
  # The class that constructs the URLs for given endpoints.
5
5
  class UrlBuilder
6
- API_PATHS = { forecast: "v1/forecast" }.freeze
6
+ API_PATHS = { forecast: "v1/forecast", forecast_dwd_icon: "v1/dwd-icon" }.freeze
7
7
 
8
8
  attr_reader :api_config
9
9
 
@@ -1,5 +1,4 @@
1
- require "faraday"
2
-
1
+ require_relative "faraday_connection"
3
2
  require_relative "client/config"
4
3
  require_relative "client/url_builder"
5
4
 
@@ -12,24 +11,24 @@ module OpenMeteo
12
11
  class Timeout < StandardError
13
12
  end
14
13
 
15
- attr_reader :api_config
14
+ attr_reader :api_config, :agent
16
15
 
17
16
  def initialize(
18
17
  api_config: OpenMeteo::Client::Config.new,
19
- url_builder: OpenMeteo::Client::UrlBuilder.new,
20
- agent: Faraday.new
18
+ url_builder: nil,
19
+ agent: FaradayConnection.new.connect
21
20
  )
22
21
  @api_config = api_config
23
- @url_builder = url_builder
22
+ @url_builder = url_builder || UrlBuilder.new(api_config:)
24
23
  @agent = agent
25
24
  end
26
25
 
27
26
  def get(endpoint_name, *endpoint_args, **get_params)
28
27
  endpoint = url_builder.build_url(endpoint_name, *endpoint_args)
29
28
 
30
- agent.get do |req|
31
- req.params = get_params
32
- req.url(endpoint)
29
+ agent.get do |request|
30
+ request.params = get_params.merge({ apikey: api_config.api_key }.compact)
31
+ request.url(endpoint)
33
32
  end
34
33
  rescue Faraday::ConnectionFailed => e
35
34
  raise ConnectionFailed, "Could not connect to OpenMeteo API: #{e.message}"
@@ -39,6 +38,6 @@ module OpenMeteo
39
38
 
40
39
  private
41
40
 
42
- attr_reader :agent, :url_builder
41
+ attr_reader :url_builder
43
42
  end
44
43
  end
@@ -27,5 +27,7 @@ module OpenMeteo
27
27
 
28
28
  add_setting :logger, -> { Logger.new($stdout) }
29
29
  add_setting :host, "api.open-meteo.com"
30
+ add_setting :api_key, -> { ENV.fetch("OPEN_METEO_API_KEY", nil) }
31
+ add_setting :timeouts, -> { { timeout: 5, open_timeout: 5 } }
30
32
  end
31
33
  end
@@ -0,0 +1,35 @@
1
+ module OpenMeteo
2
+ module Entities
3
+ class Forecast
4
+ ##
5
+ # A forecast Entity for 15 minute data returned by OpenMeteo
6
+ class Minutely15
7
+ attr_reader :items, :units, :raw_json_hourly, :raw_json_hourly_units
8
+
9
+ def initialize(json_minutely_15, json_minutely_15_units)
10
+ @items = initialize_items(json_minutely_15)
11
+ @units =
12
+ json_minutely_15_units &&
13
+ OpenMeteo::Entities::Forecast::Units.new(json_minutely_15_units)
14
+
15
+ @raw_json_minutely_15 = json_minutely_15
16
+ @raw_json_minutely_15_units = json_minutely_15_units
17
+ end
18
+
19
+ private
20
+
21
+ def initialize_items(json_minutely_15)
22
+ json_minutely_15["time"]
23
+ .map do |element|
24
+ json_minutely_15
25
+ .keys
26
+ .each_with_object({}) do |attr, json_item|
27
+ json_item[attr] = json_minutely_15[attr][json_minutely_15["time"].index(element)]
28
+ end
29
+ end
30
+ .map { |json_item| OpenMeteo::Entities::Forecast::Item.new(json_item) }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative "forecast/current"
2
+ require_relative "forecast/minutely_15"
2
3
  require_relative "forecast/hourly"
3
4
  require_relative "forecast/daily"
4
5
  require_relative "forecast/units"
@@ -9,29 +10,35 @@ module OpenMeteo
9
10
  #
10
11
  # A forecast Entity with data returned by OpenMeteo
11
12
  class Forecast
12
- attr_reader :attributes, :current, :hourly, :daily, :raw_json
13
+ attr_reader :attributes, :current, :minutely_15, :hourly, :daily, :raw_json
13
14
 
14
15
  def initialize(json_body)
15
16
  @raw_json = json_body
16
17
 
17
- @current =
18
- json_body["current"] &&
19
- OpenMeteo::Entities::Forecast::Current.new(
20
- json_body["current"],
21
- json_body["current_units"],
22
- )
23
- @hourly =
24
- json_body["hourly"] &&
25
- OpenMeteo::Entities::Forecast::Hourly.new(
26
- json_body["hourly"],
27
- json_body["hourly_units"],
28
- )
29
- @daily =
30
- json_body["daily"] &&
31
- OpenMeteo::Entities::Forecast::Daily.new(json_body["daily"], json_body["daily_units"])
18
+ init_data_for(OpenMeteo::Entities::Forecast::Current)
19
+ init_data_for(OpenMeteo::Entities::Forecast::Minutely15)
20
+ init_data_for(OpenMeteo::Entities::Forecast::Hourly)
21
+ init_data_for(OpenMeteo::Entities::Forecast::Daily)
32
22
 
33
23
  @attributes = json_body.keys
34
24
  end
25
+
26
+ private
27
+
28
+ def init_data_for(klass)
29
+ name = name_for_klass(klass)
30
+
31
+ return if raw_json[name.to_s].nil?
32
+
33
+ instance_variable_set("@#{name}", klass.new(raw_json[name.to_s], raw_json["#{name}_units"]))
34
+ end
35
+
36
+ def name_for_klass(klass)
37
+ # Extract that last part of the class name, e.g. "Minutely15"
38
+ # from "OpenMeteo::Entities::Forecast::Minutely15"
39
+ # but as snake_case version e.g. "minutely_15"
40
+ klass.to_s.split("::").last.downcase.gsub(/(\d+)/, '_\1').to_sym
41
+ end
35
42
  end
36
43
  end
37
44
  end
@@ -0,0 +1,26 @@
1
+ require "faraday"
2
+ require "faraday/retry"
3
+
4
+ module OpenMeteo
5
+ ##
6
+ # The Faraday connection
7
+ class FaradayConnection
8
+ # See https://github.com/lostisland/faraday-retry/tree/main#usage
9
+ RETRY_OPTIONS = { max: 3, interval: 0.05, interval_randomness: 0.5, backoff_factor: 3 }.freeze
10
+
11
+ attr_reader :config
12
+
13
+ def initialize(config: OpenMeteo::Client::Config.new)
14
+ @config = config
15
+ end
16
+
17
+ def connect
18
+ Faraday.new do |conn|
19
+ conn.options[:timeout] = config.timeouts[:timeout]
20
+ conn.options[:open_timeout] = config.timeouts[:open_timeout]
21
+
22
+ conn.request :retry, RETRY_OPTIONS
23
+ end
24
+ end
25
+ end
26
+ end
@@ -9,6 +9,10 @@ module OpenMeteo
9
9
  :current,
10
10
  OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
11
11
  )
12
+ attribute(
13
+ :minutely_15,
14
+ OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
15
+ )
12
16
  attribute(
13
17
  :hourly,
14
18
  OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
@@ -17,13 +21,17 @@ module OpenMeteo
17
21
  :daily,
18
22
  OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
19
23
  )
24
+ attribute(
25
+ :models,
26
+ OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
27
+ )
20
28
 
21
29
  def to_get_params
22
30
  get_params = {}
23
31
 
24
- get_params[:current] = current.join(",") if current != []
25
- get_params[:hourly] = hourly.join(",") if hourly != []
26
- get_params[:daily] = daily.join(",") if daily != []
32
+ %i[current minutely_15 hourly daily models].each do |key|
33
+ get_params[key] = send(key).join(",") if send(key) != []
34
+ end
27
35
 
28
36
  get_params
29
37
  end
@@ -3,7 +3,7 @@ require_relative "forecast/variables"
3
3
 
4
4
  module OpenMeteo
5
5
  ##
6
- # Perform a forecase request to the OpenMeteo API.
6
+ # Perform a forecast request to the OpenMeteo API.
7
7
  #
8
8
  # See https://open-meteo.com/en/docs
9
9
  class Forecast
@@ -36,6 +36,10 @@ module OpenMeteo
36
36
  # See https://open-meteo.com/en/docs
37
37
  endpoint: :forecast,
38
38
  },
39
+ dwd_icon: {
40
+ # See https://open-meteo.com/en/docs/dwd-api
41
+ endpoint: :forecast_dwd_icon,
42
+ },
39
43
  }.freeze
40
44
 
41
45
  def get_model_definition(model)
@@ -1,3 +1,3 @@
1
1
  module OpenMeteo
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.3.1".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open-meteo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Morgenstern
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-08 00:00:00.000000000 Z
11
+ date: 2024-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct
@@ -70,6 +70,26 @@ dependencies:
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
72
  version: 2.0.0
73
+ - !ruby/object:Gem::Dependency
74
+ name: faraday-retry
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '2.0'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 2.0.0
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 2.0.0
73
93
  description:
74
94
  email:
75
95
  - gundel.peter@gmail.com
@@ -89,9 +109,11 @@ files:
89
109
  - lib/open_meteo/entities/forecast/daily.rb
90
110
  - lib/open_meteo/entities/forecast/hourly.rb
91
111
  - lib/open_meteo/entities/forecast/item.rb
112
+ - lib/open_meteo/entities/forecast/minutely_15.rb
92
113
  - lib/open_meteo/entities/forecast/units.rb
93
114
  - lib/open_meteo/entities/location.rb
94
115
  - lib/open_meteo/errors.rb
116
+ - lib/open_meteo/faraday_connection.rb
95
117
  - lib/open_meteo/forecast.rb
96
118
  - lib/open_meteo/forecast/variables.rb
97
119
  - lib/open_meteo/response_wrapper.rb
@@ -117,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
139
  - !ruby/object:Gem::Version
118
140
  version: '0'
119
141
  requirements: []
120
- rubygems_version: 3.4.21
142
+ rubygems_version: 3.4.10
121
143
  signing_key:
122
144
  specification_version: 4
123
145
  summary: A client for OpenMeteo weather data