thundersnow 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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'nokogiri', '~> 1.0'
4
+ gem 'htmlentities'
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ htmlentities (4.2.4)
7
+ jeweler (1.5.2)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ nokogiri (1.4.4)
12
+ rake (0.8.7)
13
+ rcov (0.9.9)
14
+ rspec (2.3.0)
15
+ rspec-core (~> 2.3.0)
16
+ rspec-expectations (~> 2.3.0)
17
+ rspec-mocks (~> 2.3.0)
18
+ rspec-core (2.3.1)
19
+ rspec-expectations (2.3.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.3.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler (~> 1.0.0)
28
+ htmlentities
29
+ jeweler (~> 1.5.2)
30
+ nokogiri (~> 1.0)
31
+ rcov
32
+ rspec (~> 2.3.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Peter Brown
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a 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
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,57 @@
1
+ h1. thundersnow
2
+
3
+ A Ruby based command-line utility for viewing the weather
4
+
5
+ h2. About
6
+
7
+ Inspired by some recent "thundersnow":http://en.wikipedia.org/wiki/Thundersnow in New England, I decided to
8
+ build a simple application to check the weather while I'm coding.
9
+
10
+ h2. Installation
11
+
12
+ Rubygem installation coming soon...
13
+
14
+ h2. Usage
15
+
16
+ <pre>
17
+ thundersnow 05401
18
+ </pre>
19
+
20
+ <pre>
21
+ thundersnow "burlington, vt"
22
+ </pre>
23
+
24
+ h2. Sample Output
25
+
26
+ This is how the current output looks, better formatting is coming.
27
+
28
+ <pre>
29
+ Weather forecast for Burlington, VT
30
+ -------------------------
31
+ Snow Showers
32
+ 33F / 1C
33
+ Wind: S at 3 mph
34
+ Humidity: 97%
35
+ -------------------------
36
+ Forecast for Mon
37
+ High: 35F / Low: 20F
38
+ Conditions: Snow
39
+ -------------------------
40
+ Forecast for Tue
41
+ High: 22F / Low: 4F
42
+ Conditions: Snow
43
+ -------------------------
44
+ Forecast for Wed
45
+ High: 22F / Low: 5F
46
+ Conditions: Snow Showers
47
+ -------------------------
48
+ Forecast for Thu
49
+ High: 18F / Low: 5F
50
+ Conditions: Partly Cloudy
51
+ </pre>
52
+
53
+ h2. Copyright
54
+
55
+ Copyright (c) 2011 Peter Brown. See LICENSE.txt for
56
+ further details.
57
+
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "thundersnow"
16
+ gem.homepage = "http://github.com/beerlington/thundersnow"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Ruby based command-line utility for viewing the weather}
19
+ gem.description = %Q{Check the weather without leaving your terminal. Uses Google's weather API to provide current conditions and forecast weather information.}
20
+ gem.email = "github@lette.us"
21
+ gem.authors = ["Peter Brown"]
22
+ gem.executables = ["thundersnow"]
23
+ gem.add_runtime_dependency 'nokogiri', '~> 1.0'
24
+ gem.add_runtime_dependency 'htmlentities'
25
+ gem.add_development_dependency "rspec", "~> 2.3.0"
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "thundersnow #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/thundersnow ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'thundersnow'
5
+
6
+ if ARGV.size == 0
7
+ puts 'Thundersnow Usage:'
8
+ puts 'Get weather for a zipcode: thundersnow 05401'
9
+ puts 'Get weather for a city, state: thundersnow "burlington, vt"'
10
+ else
11
+ Thundersnow.run ARGV
12
+ end
@@ -0,0 +1,115 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+ require 'htmlentities'
4
+
5
+ class Thundersnow
6
+ class << self
7
+ def run(args)
8
+ @args = args
9
+
10
+ location = args.reject {|a| a =~ /^--/ }[0]
11
+
12
+ uri = URI.encode "http://www.google.com/ig/api?weather=#{location}"
13
+ @xml = Nokogiri::XML(open(uri))
14
+
15
+ # Invalid locations contain problem_cause xml tag
16
+ if @xml.xpath('//weather/problem_cause').size > 0
17
+ return puts "Could not locate weather for #{location}"
18
+ end
19
+
20
+ if show_forecast?
21
+ show :forecast
22
+ else
23
+ show :current
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def show(name)
30
+ puts send(name)
31
+ end
32
+
33
+ def show_forecast?
34
+ @args.detect {|a| a == '--forecast' }
35
+ end
36
+
37
+ def city
38
+ @city ||= read_attr(@xml, '//forecast_information/city')
39
+ end
40
+
41
+ def current
42
+ values = ["Current Conditions for #{city}"]
43
+ values << condition
44
+ values << temperatures
45
+ values << wind
46
+ values << humidity
47
+ values.join("\n")
48
+ end
49
+
50
+ def condition
51
+ read_attr(current_conditions, 'condition')
52
+ end
53
+
54
+ def temperatures
55
+ "#{temp_f} / #{temp_c}"
56
+ end
57
+
58
+ def wind
59
+ read_attr(current_conditions, 'wind_condition')
60
+ end
61
+
62
+ def humidity
63
+ read_attr(current_conditions, 'humidity')
64
+ end
65
+
66
+ def temp_f
67
+ read_attr(current_conditions, 'temp_f').to_s + deg_symbol + "F"
68
+ end
69
+
70
+ def temp_c
71
+ read_attr(current_conditions, 'temp_c').to_s + deg_symbol + 'C'
72
+ end
73
+
74
+ def deg_symbol
75
+ HTMLEntities.new.decode("&deg;")
76
+ end
77
+
78
+ def current_conditions
79
+ @current_conditions ||= @xml.xpath('//current_conditions')
80
+ end
81
+
82
+ def forecast
83
+ values = ["Weather Forecast for #{city}"]
84
+
85
+ @xml.xpath('//forecast_conditions').each do |day|
86
+ day_of_week = read_attr(day, 'day_of_week')
87
+ values << "Forecast for #{readable_day(day_of_week)}"
88
+ values << "High: #{read_attr(day, 'high')+deg_symbol}F / Low: #{read_attr(day, 'low')+deg_symbol}F"
89
+ values << "Conditions: #{read_attr(day, 'condition')}"
90
+ values << "-------------------------"
91
+ end
92
+
93
+ values.join("\n")
94
+ end
95
+
96
+ def readable_day(day_of_week)
97
+ return "Today" if day_of_week == today
98
+ return "Tomorrow" if day_of_week == tomorrow
99
+ day_of_week
100
+ end
101
+
102
+ def today
103
+ Time.now.strftime('%a')
104
+ end
105
+
106
+ def tomorrow
107
+ (Time.now + 86400).strftime('%a')
108
+ end
109
+
110
+ def read_attr(root, node)
111
+ root.xpath(node).attribute('data').to_s
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,33 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'thundersnow'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
13
+
14
+ ZIP = "05401"
15
+
16
+ XML = '<?xml version="1.0"?>
17
+ <xml_api_reply version="1"><weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" >
18
+ <forecast_information><city data="Burlington, VT"/><postal_code data="05401"/><latitude_e6 data=""/><longitude_e6 data=""/><forecast_date data="2011-02-07"/>
19
+ <current_date_time data="2011-02-08 03:19:38 +0000"/><unit_system data="US"/></forecast_information><current_conditions>
20
+ <condition data="Snow Showers"/><temp_f data="34"/><temp_c data="1"/><humidity data="Humidity: 87%"/><icon data="/ig/images/weather/snow.gif"/>
21
+ <wind_condition data="Wind: S at 6 mph"/></current_conditions><forecast_conditions><day_of_week data="Mon"/><low data="20"/><high data="35"/>
22
+ <icon data="/ig/images/weather/snow.gif"/><condition data="Snow"/></forecast_conditions><forecast_conditions><day_of_week data="Tue"/><low data="4"/>
23
+ <high data="22"/><icon data="/ig/images/weather/snow.gif"/><condition data="Snow"/></forecast_conditions><forecast_conditions><day_of_week data="Wed"/>
24
+ <low data="5"/><high data="22"/><icon data="/ig/images/weather/snow.gif"/><condition data="Snow Showers"/></forecast_conditions><forecast_conditions>
25
+ <day_of_week data="Thu"/><low data="5"/><high data="18"/><icon data="/ig/images/weather/partly_cloudy.gif"/><condition data="Partly Cloudy"/>
26
+ </forecast_conditions></weather></xml_api_reply>'
27
+
28
+
29
+ BAD_XML = '<?xml version="1.0"?>
30
+ <xml_api_reply version="1">
31
+ <weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" >
32
+ <problem_cause data=""/>
33
+ </weather></xml_api_reply>'
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thundersnow do
4
+ before do
5
+ Thundersnow.stub(:open).and_return(XML)
6
+ Thundersnow.stub(:show).and_return(true)
7
+ end
8
+
9
+ context "for current conditions" do
10
+ before do
11
+ @args = [ZIP]
12
+ end
13
+
14
+ context "when running" do
15
+
16
+ it "should set the @xml instance variable" do
17
+ Thundersnow.run @args
18
+ Thundersnow.instance_variable_get('@xml').to_s.should == Nokogiri::XML(XML).to_s
19
+ end
20
+
21
+ it "should show the current conditions" do
22
+ Thundersnow.should_receive(:show).with(:current).once
23
+ Thundersnow.run @args
24
+ end
25
+
26
+ it "should not show the forecast conditions" do
27
+ Thundersnow.should_not_receive(:show).with(:forecast)
28
+ Thundersnow.run @args
29
+ end
30
+ end
31
+ end
32
+
33
+ context "for forecast conditions" do
34
+ before do
35
+ @args = [ZIP, '--forecast']
36
+ end
37
+
38
+ context "when running" do
39
+
40
+ it "should set the @xml instance variable" do
41
+ Thundersnow.run @args
42
+ Thundersnow.instance_variable_get('@xml').to_s.should == Nokogiri::XML(XML).to_s
43
+ end
44
+
45
+ it "should show the forecast conditions" do
46
+ Thundersnow.should_receive(:show).with(:forecast).once
47
+ Thundersnow.run @args
48
+ end
49
+
50
+ it "should not show the current conditions" do
51
+ Thundersnow.should_not_receive(:show).with(:current)
52
+ Thundersnow.run @args
53
+ end
54
+ end
55
+ end
56
+
57
+ context "w/ invalid location" do
58
+ before do
59
+ Thundersnow.stub(:open).and_return(BAD_XML)
60
+ end
61
+
62
+ context "when running" do
63
+ before do
64
+ Thundersnow.stub(:show).and_return(true)
65
+ @args = [ZIP]
66
+ end
67
+
68
+ it "should set the @xml instance variable" do
69
+ Thundersnow.run @args
70
+ Thundersnow.instance_variable_get('@xml').to_s.should == Nokogiri::XML(BAD_XML).to_s
71
+ end
72
+
73
+ it "should return and not show anything" do
74
+ Thundersnow.should_not_receive(:show)
75
+ Thundersnow.run @args
76
+ end
77
+ end
78
+ end
79
+
80
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thundersnow
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Peter Brown
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-08 00:00:00 -05:00
14
+ default_executable: thundersnow
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: nokogiri
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: "1.0"
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: htmlentities
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.3.0
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: bundler
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: jeweler
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 1.5.2
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: rcov
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: nokogiri
84
+ requirement: &id007 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: "1.0"
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: htmlentities
95
+ requirement: &id008 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ type: :runtime
102
+ prerelease: false
103
+ version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
105
+ name: rspec
106
+ requirement: &id009 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ version: 2.3.0
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: *id009
115
+ description: Check the weather without leaving your terminal. Uses Google's weather API to provide current conditions and forecast weather information.
116
+ email: github@lette.us
117
+ executables:
118
+ - thundersnow
119
+ extensions: []
120
+
121
+ extra_rdoc_files:
122
+ - LICENSE.txt
123
+ - README.textile
124
+ files:
125
+ - .document
126
+ - .rspec
127
+ - Gemfile
128
+ - Gemfile.lock
129
+ - LICENSE.txt
130
+ - README.textile
131
+ - Rakefile
132
+ - VERSION
133
+ - bin/thundersnow
134
+ - lib/thundersnow.rb
135
+ - spec/spec_helper.rb
136
+ - spec/thundersnow_spec.rb
137
+ has_rdoc: true
138
+ homepage: http://github.com/beerlington/thundersnow
139
+ licenses:
140
+ - MIT
141
+ post_install_message:
142
+ rdoc_options: []
143
+
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ hash: 2985694618793645140
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: "0"
161
+ requirements: []
162
+
163
+ rubyforge_project:
164
+ rubygems_version: 1.5.0
165
+ signing_key:
166
+ specification_version: 3
167
+ summary: Ruby based command-line utility for viewing the weather
168
+ test_files:
169
+ - spec/spec_helper.rb
170
+ - spec/thundersnow_spec.rb