weather-sage 0.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.
- checksums.yaml +7 -0
- data/README.md +88 -0
- data/Rakefile +16 -0
- data/bin/weather-sage +6 -0
- data/lib/weather-sage.rb +25 -0
- data/license.txt +20 -0
- data/test/make-csvs.sh +10 -0
- data/test/test-cache.rb +64 -0
- data/test/test-census-geocoder.rb +49 -0
- data/test/test-helpers.rb +24 -0
- data/test/test-http-cache.rb +103 -0
- data/test/test-weather-point.rb +32 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 390dc567cf5a2696830a36bd2a6a27020a2310721a95f69530ccbd0688c06d28
|
4
|
+
data.tar.gz: 9fc5165689410c41763750e06b5590452294f2588880cb2f027dbe98191e0be6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b23545938bb233191fb042f1cb7d45c098332421dbfb53c6fae126f5a3ef8f6543d75c16d4537582222e519e7da320fc11abbcaadaeed0f7fd4fcb31f83cdefc
|
7
|
+
data.tar.gz: 1541a3ef620d4667e45fe513f95f61e891ff259ab0309c4286ca709498eca8bca2972d9ede59e0587bd51dbacb9403c9ebdff1d491af33320f58400fae619c9f
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
Weather Sage
|
2
|
+
============
|
3
|
+
Ruby library and command-line tool to get the weather forecast and
|
4
|
+
current weather observations for an address.
|
5
|
+
|
6
|
+
Uses the [Census Bureau Geocoding API][census-api] to geocode street
|
7
|
+
addresses, and the [National Weather Service Weather API][weather-api]
|
8
|
+
to get weather forecasts and current weather observations.
|
9
|
+
|
10
|
+
Here's an example of using the command-line tool to get the current
|
11
|
+
weather forecast for the address "1600 pennsylvania ave nw, washington
|
12
|
+
dc":
|
13
|
+
|
14
|
+
```
|
15
|
+
> bin/weather-sage forecast '1600 pennsylvania ave nw washington dc'
|
16
|
+
address,name,temperature,temperature_unit,wind_speed,wind_direction,short_forecast
|
17
|
+
1600 pennsylvania ave washington dc,Today,97,F,7 mph,SW,Scattered Showers And Thunderstorms
|
18
|
+
1600 pennsylvania ave washington dc,Tonight,76,F,2 to 7 mph,SW,Scattered Showers And Thunderstorms then Mostly Cloudy
|
19
|
+
1600 pennsylvania ave washington dc,Tuesday,94,F,6 mph,E,Slight Chance Rain Showers then Chance Showers And Thunderstorms
|
20
|
+
1600 pennsylvania ave washington dc,Tuesday Night,75,F,2 to 6 mph,S,Chance Showers And Thunderstorms
|
21
|
+
1600 pennsylvania ave washington dc,Wednesday,94,F,3 to 9 mph,SW,Chance Showers And Thunderstorms
|
22
|
+
1600 pennsylvania ave washington dc,Wednesday Night,76,F,5 to 8 mph,SW,Chance Showers And Thunderstorms
|
23
|
+
...
|
24
|
+
```
|
25
|
+
|
26
|
+
Installation
|
27
|
+
------------
|
28
|
+
Install via [RubyGems][]:
|
29
|
+
|
30
|
+
```
|
31
|
+
# install weather-sage
|
32
|
+
> sudo gem install weather-sage
|
33
|
+
```
|
34
|
+
|
35
|
+
Examples
|
36
|
+
--------
|
37
|
+
**Get weather forecast for an address:**
|
38
|
+
```
|
39
|
+
# get weather forecast for address
|
40
|
+
> bin/weather-sage forecast '1600 pennsylvania ave washington dc'
|
41
|
+
address,name,temperature,temperature_unit,wind_speed,wind_direction,short_forecast
|
42
|
+
1600 pennsylvania ave washington dc,Today,97,F,7 mph,SW,Scattered Showers And Thunderstorms
|
43
|
+
1600 pennsylvania ave washington dc,Tonight,76,F,2 to 7 mph,SW,Scattered Showers And Thunderstorms then Mostly Cloudy
|
44
|
+
1600 pennsylvania ave washington dc,Tuesday,94,F,6 mph,E,Slight Chance Rain Showers then Chance Showers And Thunderstorms
|
45
|
+
1600 pennsylvania ave washington dc,Tuesday Night,75,F,2 to 6 mph,S,Chance Showers And Thunderstorms
|
46
|
+
1600 pennsylvania ave washington dc,Wednesday,94,F,3 to 9 mph,SW,Chance Showers And Thunderstorms
|
47
|
+
1600 pennsylvania ave washington dc,Wednesday Night,76,F,5 to 8 mph,SW,Chance Showers And Thunderstorms
|
48
|
+
...
|
49
|
+
```
|
50
|
+
|
51
|
+
**Get current observations from nearest weather station:**
|
52
|
+
```
|
53
|
+
# get current observations from nearest weather station
|
54
|
+
> weather-sage now '1600 pennsylvania ave washington dc'
|
55
|
+
address,name,type,value,unit,quality_control
|
56
|
+
1600 pennsylvania ave washington dc,timestamp,time,2019-08-19T06:52:00+00:00
|
57
|
+
1600 pennsylvania ave washington dc,textDescription,text,Mostly Cloudy
|
58
|
+
1600 pennsylvania ave washington dc,temperature,value,26.700000000000045,unit:degC,qc:V
|
59
|
+
1600 pennsylvania ave washington dc,relativeHumidity,value,81.65039907186703,unit:percent,qc:C
|
60
|
+
...
|
61
|
+
```
|
62
|
+
|
63
|
+
Commands
|
64
|
+
--------
|
65
|
+
Available commands in command-line interface.
|
66
|
+
|
67
|
+
* `forecast`: Get weather forecast for address.
|
68
|
+
* `geocode`: Geocode address.
|
69
|
+
* `help`: List commands.
|
70
|
+
* `hourly`: Get hourly weather forecast for address.
|
71
|
+
* `now`: Get current weather from station closest to address.
|
72
|
+
* `stations`: List weather stations near address.
|
73
|
+
|
74
|
+
Environment Variables
|
75
|
+
---------------------
|
76
|
+
The command-line tool can be configured via the following environment
|
77
|
+
variables:
|
78
|
+
|
79
|
+
* `WEATHER_SAGE_LOG_LEVEL`: Log level. One of: `fatal`, `error`,
|
80
|
+
`warning`, `info`, `debug`). Defaults to `warn`.
|
81
|
+
* `WEATHER_SAGE_LOG_PATH`: Path to log file. Defaults to standard error.
|
82
|
+
* `WEATHER_SAGE_CACHE_PATH`: Path to HTTP cache. Defaults to
|
83
|
+
`~/.config/weather-sage/http-cache.pstore`.
|
84
|
+
|
85
|
+
[ruby]: https://ruby-lang.org/ "Ruby programming language"
|
86
|
+
[rubygems]: https://rubygems.org/ "Ruby package manager"
|
87
|
+
[weather-api]: https://api.weather.gov/ "national Weather Service (NWS) Weather API"
|
88
|
+
[census-api]: https://geocoding.geo.census.gov/geocoder/ "Census Bureau Geocoding API"
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rdoc/task'
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << 'test'
|
6
|
+
end
|
7
|
+
|
8
|
+
RDoc::Task.new :docs do |t|
|
9
|
+
t.main = "lib/weather-sage.rb"
|
10
|
+
t.rdoc_files.include('lib/*.rb')
|
11
|
+
t.rdoc_dir = 'docs'
|
12
|
+
# t.options << "--all"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Run tests"
|
16
|
+
task default: :test
|
data/bin/weather-sage
ADDED
data/lib/weather-sage.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Get weather forecast and current weather for address.
|
3
|
+
#
|
4
|
+
# Wrapper around the following APIs:
|
5
|
+
#
|
6
|
+
# * National Weather Service Weather API (https://api.weather.gov/)
|
7
|
+
# * Census Bureau Geocoder API (https://geocoding.geo.census.gov/geocoder/)
|
8
|
+
#
|
9
|
+
module WeatherSage
|
10
|
+
#
|
11
|
+
# Release version.
|
12
|
+
#
|
13
|
+
VERSION = '0.1.0'
|
14
|
+
|
15
|
+
# :nodoc:
|
16
|
+
LIB_DIR = File.join(__dir__, 'weather-sage').freeze
|
17
|
+
|
18
|
+
autoload :CacheEntry, File.join(LIB_DIR, 'cache-entry.rb')
|
19
|
+
autoload :Cache, File.join(LIB_DIR, 'cache.rb')
|
20
|
+
autoload :HTTP, File.join(LIB_DIR, 'http.rb')
|
21
|
+
autoload :Context, File.join(LIB_DIR, 'context.rb')
|
22
|
+
autoload :Census, File.join(LIB_DIR, 'census.rb')
|
23
|
+
autoload :Weather, File.join(LIB_DIR, 'weather.rb')
|
24
|
+
autoload :CLI, File.join(LIB_DIR, 'cli.rb')
|
25
|
+
end
|
data/license.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2019 Paul Duncan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
4
|
+
copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included
|
12
|
+
in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
15
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/test/make-csvs.sh
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# TODO: move to rake task
|
4
|
+
ADDR='7309 carol ln falls church va 22042'
|
5
|
+
|
6
|
+
bin/weather-sage hourly -f "$ADDR" > hourly-full.csv
|
7
|
+
bin/weather-sage hourly -b "$ADDR" > hourly-brief.csv
|
8
|
+
bin/weather-sage forecast -b "$ADDR" > forecast-brief.csv
|
9
|
+
bin/weather-sage forecast -f "$ADDR" > forecast-full.csv
|
10
|
+
bin/weather-sage now "$ADDR" > now.csv
|
data/test/test-cache.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'fileutils'
|
3
|
+
require_relative '../lib/weather-sage'
|
4
|
+
|
5
|
+
class TestWeatherSageCache < Minitest::Test
|
6
|
+
def setup
|
7
|
+
# create temporary directory that is removed on exit
|
8
|
+
@dir = Dir.mktmpdir('test-cache')
|
9
|
+
at_exit { FileUtils.rm_r(@dir) }
|
10
|
+
|
11
|
+
# build absolute path to backing store for cache
|
12
|
+
path = File.join(@dir, 'cache.pstore')
|
13
|
+
|
14
|
+
# create cache instance
|
15
|
+
@cache = WeatherSage::Cache.new(path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_new
|
19
|
+
# build absolute path to backing store for cache
|
20
|
+
path = File.join(@dir, 'test-new.pstore')
|
21
|
+
|
22
|
+
# asset that cache is not nil
|
23
|
+
assert WeatherSage::Cache.new(path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_set
|
27
|
+
key, want = 'test_set', 'bar'
|
28
|
+
assert_equal want, @cache.set(key, want)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_get
|
32
|
+
# set value
|
33
|
+
key, want = 'test_get', 'bar'
|
34
|
+
@cache.set(key, want)
|
35
|
+
|
36
|
+
# get value, test result
|
37
|
+
got = @cache.get(key)
|
38
|
+
assert_equal want, got
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_key?
|
42
|
+
key, want = 'test_key?', 'bar'
|
43
|
+
@cache.set(key, want)
|
44
|
+
assert @cache.key?(key)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_set_timeout
|
48
|
+
key, want, timeout = 'test_set_timeout', 'bar', 10
|
49
|
+
|
50
|
+
# set long timeout, then get result before expiration
|
51
|
+
@cache.set(key, want, timeout)
|
52
|
+
assert_equal want, @cache.get(key)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_set_timeout_expired
|
56
|
+
key, want, timeout = 'test_set_timeout_expired', 'bar', 0.1
|
57
|
+
|
58
|
+
# set short timeout, then wait for it to pass
|
59
|
+
@cache.set(key, want, timeout)
|
60
|
+
sleep(timeout + 1)
|
61
|
+
|
62
|
+
assert_nil @cache.get(key)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'logger'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../lib/weather-sage'
|
5
|
+
require_relative './test-helpers'
|
6
|
+
|
7
|
+
class TestWeatherSageCensusGeocoder < Minitest::Test
|
8
|
+
#
|
9
|
+
# Test addresses.
|
10
|
+
#
|
11
|
+
TESTS = [{
|
12
|
+
text: '2565 van buren st eugene or 97405',
|
13
|
+
want: [-123.109825, 44.03039],
|
14
|
+
}, {
|
15
|
+
text: '1600 pennsylvania ave nw washington dc',
|
16
|
+
want: [-77.03535, 38.898754],
|
17
|
+
}, {
|
18
|
+
text: '3150 fairview park dr falls church va 22042',
|
19
|
+
want: [-77.216194, 38.859795],
|
20
|
+
}]
|
21
|
+
|
22
|
+
def setup
|
23
|
+
# cache test context
|
24
|
+
@ctx = WeatherSage::Tests.get_test_context
|
25
|
+
|
26
|
+
# create and save geocoder
|
27
|
+
@geocoder = WeatherSage::Census::Geocoder.new(@ctx)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_new
|
31
|
+
# create new geocoder
|
32
|
+
assert WeatherSage::Census::Geocoder.new(@ctx)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_run
|
36
|
+
# assert that geocoder can geocode a single address
|
37
|
+
assert @geocoder.run(TESTS.first[:text])
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_results
|
41
|
+
TESTS.each do |test|
|
42
|
+
# geocode address, get first result
|
43
|
+
pt = @geocoder.run(test[:text]).first.point
|
44
|
+
|
45
|
+
assert_in_delta pt.x, test[:want][0]
|
46
|
+
assert_in_delta pt.y, test[:want][1]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module WeatherSage::Tests
|
2
|
+
def self.get_test_context
|
3
|
+
unless @ctx
|
4
|
+
# create temporary directory that is removed on exit
|
5
|
+
@dir = Dir.mktmpdir('test-weather-sage')
|
6
|
+
at_exit { FileUtils.rm_r(@dir) }
|
7
|
+
|
8
|
+
# build absolute path to backing store for cache
|
9
|
+
cache_path = File.join(@dir, 'cache.pstore')
|
10
|
+
|
11
|
+
# create null logger
|
12
|
+
log = ::Logger.new('/dev/null')
|
13
|
+
|
14
|
+
# create cache instance
|
15
|
+
cache = WeatherSage::HTTP::Cache.new(cache_path, log)
|
16
|
+
|
17
|
+
# create and save context
|
18
|
+
@ctx = WeatherSage::Context.new(log, cache)
|
19
|
+
end
|
20
|
+
|
21
|
+
# return cached context
|
22
|
+
@ctx
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'logger'
|
5
|
+
require_relative '../lib/weather-sage'
|
6
|
+
|
7
|
+
class TestWeatherSageHttpCache < Minitest::Test
|
8
|
+
#
|
9
|
+
# list of test urls
|
10
|
+
#
|
11
|
+
URLS = {
|
12
|
+
good: 'https://pablotron.org/',
|
13
|
+
bad: 'https://pablotron.org/does-not-exist',
|
14
|
+
}
|
15
|
+
|
16
|
+
def setup
|
17
|
+
# create temporary directory that is removed on exit
|
18
|
+
@dir = Dir.mktmpdir('test-http-cache')
|
19
|
+
at_exit { FileUtils.rm_r(@dir) }
|
20
|
+
|
21
|
+
# build absolute path to backing store for cache
|
22
|
+
path = File.join(@dir, 'cache.pstore')
|
23
|
+
|
24
|
+
# create null logger
|
25
|
+
@log = ::Logger.new('/dev/null')
|
26
|
+
|
27
|
+
# create cache instance
|
28
|
+
@cache = WeatherSage::HTTP::Cache.new(path, @log)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_new
|
32
|
+
# build absolute path to backing store for cache
|
33
|
+
path = File.join(@dir, 'test-new.pstore')
|
34
|
+
|
35
|
+
# asset that cache is not nil
|
36
|
+
assert WeatherSage::HTTP::Cache.new(path, @log)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_new_timeout
|
40
|
+
# build absolute path to backing store for cache
|
41
|
+
path = File.join(@dir, 'test-new-timeout.pstore')
|
42
|
+
|
43
|
+
# set timeout to one second
|
44
|
+
timeout = 1
|
45
|
+
|
46
|
+
# create cache with timeout
|
47
|
+
cache = WeatherSage::HTTP::Cache.new(path, @log, timeout)
|
48
|
+
|
49
|
+
# asset that timeout is saved
|
50
|
+
assert_equal timeout, cache.timeout
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_new_timeout_expired
|
54
|
+
# build absolute path to backing store for cache
|
55
|
+
path = File.join(@dir, 'test-new-timeout.pstore')
|
56
|
+
|
57
|
+
# set timeout to one seconds
|
58
|
+
timeout = 1
|
59
|
+
|
60
|
+
# create cache with one second
|
61
|
+
cache = WeatherSage::HTTP::Cache.new(path, @log, timeout)
|
62
|
+
|
63
|
+
# get known good url
|
64
|
+
cache.get(URLS[:good])
|
65
|
+
|
66
|
+
# wait for entry to expire
|
67
|
+
sleep(timeout + 0.1)
|
68
|
+
|
69
|
+
# asset that entry is expired
|
70
|
+
assert !cache.key?(URLS[:good])
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_get
|
74
|
+
# read URl directly
|
75
|
+
want = read_url(URLS[:good])
|
76
|
+
|
77
|
+
# get URL through cache
|
78
|
+
got = @cache.get(URLS[:good])
|
79
|
+
|
80
|
+
# test result
|
81
|
+
assert_equal want, got
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_get_bad
|
85
|
+
assert_raises(WeatherSage::HTTP::Error) do
|
86
|
+
@cache.get(URLS[:bad])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
#
|
93
|
+
# Read given URL.
|
94
|
+
#
|
95
|
+
# Note: currently forces UTF-8 encoding.
|
96
|
+
#
|
97
|
+
def read_url(url)
|
98
|
+
# open(url, 'rb') { |fh| fh.read }
|
99
|
+
|
100
|
+
# read contents of URL, force UTF-8 encoding
|
101
|
+
open(url, 'rb', encoding: 'UTF-8') { |fh| fh.read }
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'logger'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../lib/weather-sage'
|
5
|
+
require_relative './test-helpers'
|
6
|
+
|
7
|
+
class WeatherSage::Tests::TestWeatherPoint < Minitest::Test
|
8
|
+
#
|
9
|
+
# Test addresses.
|
10
|
+
#
|
11
|
+
TESTS = [{
|
12
|
+
id: '2565 van buren st eugene or 97405',
|
13
|
+
pt: [-123.109825, 44.03039],
|
14
|
+
}, {
|
15
|
+
id: '1600 pennsylvania ave nw washington dc',
|
16
|
+
pt: [-77.03535, 38.898754],
|
17
|
+
}, {
|
18
|
+
id: '3150 fairview park dr falls church va 22042',
|
19
|
+
pt: [-77.216194, 38.859795],
|
20
|
+
}]
|
21
|
+
|
22
|
+
def setup
|
23
|
+
# cache test context
|
24
|
+
@ctx = WeatherSage::Tests.get_test_context
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_new
|
28
|
+
# create point from lat/long
|
29
|
+
x, y = TESTS.first[:pt]
|
30
|
+
assert WeatherSage::Weather::Point.new(@ctx, x, y)
|
31
|
+
end
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: weather-sage
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Paul Duncan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-08-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: "\n Ruby library and command-line tool to get the weather forecast
|
14
|
+
and\n current weather observations for an address.\n\n Uses the Census Bureau
|
15
|
+
Geocoding API to geocode street addresses,\n and the National Weather Service
|
16
|
+
Weather API to get weather\n forecasts and current weather observations.\n "
|
17
|
+
email: pabs@pablotron.org
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- bin/weather-sage
|
25
|
+
- lib/weather-sage.rb
|
26
|
+
- license.txt
|
27
|
+
- test/make-csvs.sh
|
28
|
+
- test/test-cache.rb
|
29
|
+
- test/test-census-geocoder.rb
|
30
|
+
- test/test-helpers.rb
|
31
|
+
- test/test-http-cache.rb
|
32
|
+
- test/test-weather-point.rb
|
33
|
+
homepage: https://github.com/pablotron/weather-sage
|
34
|
+
licenses:
|
35
|
+
- MIT
|
36
|
+
metadata:
|
37
|
+
bug_tracker_uri: https://github.com/pablotron/weather-sage/issues
|
38
|
+
documentation_uri: https://pablotron.github.io/weather-sage/
|
39
|
+
homepage_uri: https://github.com/pablotron/weather-sage
|
40
|
+
source_code_uri: https://github.com/pablotron/weather-sage
|
41
|
+
wiki_uri: https://github.com/pablotron/weather-sage/wiki
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.7.6.2
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Get weather forecast for an address.
|
62
|
+
test_files: []
|