regentanz 0.3.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +268 -0
  3. data/bin/regentanz +16 -0
  4. data/lib/regentanz.rb +10 -11
  5. data/lib/regentanz/cli/common.rb +35 -0
  6. data/lib/regentanz/cli/compare.rb +85 -0
  7. data/lib/regentanz/cli/compile.rb +27 -0
  8. data/lib/regentanz/template_compiler.rb +263 -0
  9. data/lib/regentanz/version.rb +1 -2
  10. data/lib/regentanz/yaml-ext.rb +18 -0
  11. data/spec/regentanz/resources/test/unloaded.rb +11 -0
  12. data/spec/regentanz/template_compiler_spec.rb +692 -0
  13. data/spec/spec_helper.rb +2 -0
  14. metadata +45 -152
  15. data/.gitignore +0 -5
  16. data/.rvmrc +0 -4
  17. data/CHANGELOG.rdoc +0 -26
  18. data/Gemfile +0 -4
  19. data/LICENSE +0 -24
  20. data/README.rdoc +0 -54
  21. data/Rakefile +0 -23
  22. data/lib/regentanz/astronomy.rb +0 -69
  23. data/lib/regentanz/cache.rb +0 -2
  24. data/lib/regentanz/cache/base.rb +0 -51
  25. data/lib/regentanz/cache/file.rb +0 -86
  26. data/lib/regentanz/callbacks.rb +0 -18
  27. data/lib/regentanz/conditions.rb +0 -3
  28. data/lib/regentanz/conditions/base.rb +0 -16
  29. data/lib/regentanz/conditions/current.rb +0 -14
  30. data/lib/regentanz/conditions/forecast.rb +0 -14
  31. data/lib/regentanz/configuration.rb +0 -55
  32. data/lib/regentanz/configurator.rb +0 -22
  33. data/lib/regentanz/google_weather.rb +0 -151
  34. data/lib/regentanz/parser.rb +0 -1
  35. data/lib/regentanz/parser/google_weather.rb +0 -100
  36. data/lib/regentanz/test_helper.rb +0 -52
  37. data/regentanz.gemspec +0 -30
  38. data/test/factories.rb +0 -6
  39. data/test/support/tmp/.gitignore +0 -1
  40. data/test/support/valid_response.xml.erb +0 -26
  41. data/test/test_helper.rb +0 -14
  42. data/test/unit/astronomy_test.rb +0 -26
  43. data/test/unit/cache/base_test.rb +0 -53
  44. data/test/unit/cache/file_test.rb +0 -141
  45. data/test/unit/callbacks_test.rb +0 -27
  46. data/test/unit/configuration_test.rb +0 -57
  47. data/test/unit/current_condition_test.rb +0 -33
  48. data/test/unit/forecast_condition_test.rb +0 -35
  49. data/test/unit/google_weather_test.rb +0 -125
  50. data/test/unit/parser/google_weather_parser_test.rb +0 -71
@@ -1 +0,0 @@
1
- require 'regentanz/parser/google_weather'
@@ -1,100 +0,0 @@
1
- module Regentanz
2
- module Parser
3
- class GoogleWeather
4
- require 'iconv'
5
-
6
- XML_ENCODING = 'LATIN1' # source encoding of the XML data
7
-
8
- # Converts a string from XML_ENCODING to UTF-8 using the Iconv library.
9
- #
10
- # === Note
11
- # FIXME The XML source document seems to be delivered LATIN1 or UTF-8, completely
12
- # random and unpredictable.
13
- #
14
- # === Parameters
15
- # * +data+: string to convert
16
- def convert_encoding data
17
- return if data.blank?
18
- self.class::XML_ENCODING != "UTF-8" ? Iconv.iconv("UTF-8", self.class::XML_ENCODING, data).flatten.join(" ") : data
19
- end
20
-
21
- def parse_current!(xml)
22
- return if xml.blank?
23
- begin
24
- doc = REXML::Document.new(xml)
25
- if doc.elements['xml_api_reply/weather/current_conditions']
26
- attributes = {}
27
- doc.elements['xml_api_reply/weather/current_conditions'].each_element do |ele|
28
- attributes.merge! parse_node(ele)
29
- end
30
- Regentanz::Conditions::Current.new(attributes)
31
- end
32
- rescue
33
- # FIXME should report error
34
- end
35
- end
36
-
37
- def parse_forecast!(xml)
38
- return if xml.blank?
39
- forecasts = []
40
- begin
41
- doc = REXML::Document.new(xml)
42
- if doc.elements['xml_api_reply/weather/forecast_conditions']
43
- doc.elements.each('xml_api_reply/weather/forecast_conditions') do |forecast_element|
44
- attributes = {}
45
- forecast_element.each_element { |ele| attributes.merge! parse_node(ele) }
46
- forecasts << Regentanz::Conditions::Forecast.new(attributes)
47
- end
48
- end
49
- forecasts
50
- rescue
51
- # FIXME should report error
52
- end
53
- end
54
-
55
- #private # FIXME private methods should start here after parse! has been implemented
56
-
57
- # Handles some special treatment for certain sub-elements, transforms _element_
58
- # into a hash and returns it.
59
- #
60
- # === Parameters
61
- # * +element+ childnode of type REXML::Element
62
- def parse_node(element)
63
- hash = {}
64
- hash.merge! parse_style(element.attribute("data").to_s) if element.name == "icon"
65
- if element.name == "humidity"
66
- # Handle the small whitespace just before the '%'
67
- hash.merge! element.name => element.attribute("data").to_s.gsub(/(\d+).+%$/, '\1 %')
68
- elsif element.name == "icon"
69
- # We want the full URL
70
- hash.merge! element.name => "http://www.google.com" + element.attribute("data").to_s
71
- elsif (element.name == "high" or element.name == "low") and @lang == "en"
72
- # Forecast-temperatures in EN are listed in °F; we fix that here
73
- temp_f = element.attribute("data").to_s.to_i
74
- hash.merge! element.name => ( temp_f - 32 ) * 5 / 9
75
- else
76
- hash.merge! element.name => element.attribute("data").to_s
77
- end
78
- hash
79
- end
80
-
81
- private
82
-
83
- # Extracts a name for the weather condition from the icon name. Intended to
84
- # be used as CSS style class name.
85
- #
86
- # === Parameters
87
- # * +path+ an URI-string to Google's weather icon
88
- def parse_style(path)
89
- hash = {}
90
- unless path.blank?
91
- style = File.basename(path) # FIXME is this what we want for everyone?
92
- style = style.slice(0, style.rindex(".")).gsub(/_/, '-')
93
- hash = { "style" => style }
94
- end
95
- hash
96
- end
97
-
98
- end
99
- end
100
- end
@@ -1,52 +0,0 @@
1
- module Regentanz
2
- module TestHelper
3
-
4
- # Default values used for testing. Use this in your setup methods.
5
- # Configuration values can be overriden by supplying a block. See
6
- # Regentanz::Configuration for supported values.
7
- def setup_regentanz_test_configuration!
8
- Regentanz.configure do |config|
9
- config.retry_ttl = Regentanz::Configuration.default_cache_ttl
10
- config.do_not_get_weather = true
11
- config.retry_ttl = Regentanz::Configuration.default_retry_ttl
12
- config.suppress_stderr_output = true
13
- yield config if block_given? # add settings or override above from client
14
- end
15
- end
16
-
17
- # Returns an invalid API response that will cause REXML to hickup
18
- def invalid_xml_response
19
- '<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">' \
20
- "<TITLE>302 Moved</TITLE></HEAD><BODY>\n" \
21
- "<H1>302 Moved</H1>\n" \
22
- "The document has moved\n" \
23
- '<A HREF="http://sorry.google.com/sorry/?continue=http://www.google.com/ig/api%3Fweather%3D86747%252CGermany%26hl%3Dde">here</A>' \
24
- "</BODY></HTML>\n"
25
- end
26
-
27
- # Returns a valid xml api reply based upon ./test/support/valid_response.xml.erb
28
- def valid_xml_response
29
- filename = File.join(Regentanz.configuration.cache_dir, '..', 'valid_response.xml.erb')
30
- xmlerb = ERB.new(File.open(filename, 'r') { |file| file.read })
31
- xmlerb.result
32
- end
33
-
34
- # Creates a cache file +filename+ with contents of #invalid_xml_response
35
- # FIXME this is deprecated with the introduction of Regentanz::Cache::File
36
- def create_invalid_xml_response(filename)
37
- File.open(filename, "w+") { |f| f.puts invalid_xml_response }
38
- end
39
-
40
- # Stub Net::HTTP.get_response to return a semi-dynamic (ie. current date) xml
41
- # response-
42
- def stub_valid_xml_api_response!
43
- mock_response = mock()
44
- mock_response.stubs(:body).returns(valid_xml_response)
45
- Net::HTTP.stubs(:get_response).returns(mock_response)
46
- end
47
-
48
- end
49
-
50
- end
51
-
52
- include Regentanz::TestHelper
@@ -1,30 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "regentanz/version"
4
-
5
- Gem::Specification.new do |s|
6
- s.name = "regentanz"
7
- s.version = Regentanz::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ["Carsten Zimmermann"]
10
- s.email = ["cz@aegisnet.de"]
11
- s.homepage = ""
12
- s.summary = %q{Library to access the Google Weather API}
13
- s.description = %q{Library to access the Google Weather API}
14
-
15
- s.rubyforge_project = "regentanz"
16
-
17
- s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
- s.require_paths = ["lib"]
21
-
22
- s.add_dependency 'activesupport', '~> 3.0'
23
-
24
- s.add_development_dependency 'rake'
25
- s.add_development_dependency 'mocha'
26
- s.add_development_dependency 'bundler'
27
- s.add_development_dependency 'factory_girl', '~> 2.0'
28
- s.add_development_dependency 'rdoc', '~> 2.4'
29
-
30
- end
@@ -1,6 +0,0 @@
1
- FactoryGirl.define do
2
- factory :google_weather, :class => Regentanz::GoogleWeather, :default_strategy => :build do |f|
3
- f.location "Testhausen"
4
- f.cache_id "test"
5
- end
6
- end
@@ -1 +0,0 @@
1
- *.xml
@@ -1,26 +0,0 @@
1
- <?xml version="1.0"?>
2
- <xml_api_reply version="1">
3
- <weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" >
4
- <forecast_information>
5
- <city data="Berlin, Berlin"/><postal_code data="Berlin,Germany"/>
6
- <latitude_e6 data=""/>
7
- <longitude_e6 data=""/>
8
- <forecast_date data="<%= Date.today.strftime("%Y-%m-%d") %>"/>
9
- <current_date_time data="<%= 5.minutes.ago.utc.strftime("%Y-%m-%d %H:%M:00") %> +0000"/>
10
- <unit_system data="SI"/>
11
- </forecast_information>
12
- <current_conditions>
13
- <condition data="Klar"/><temp_f data="77"/>
14
- <temp_c data="25"/>
15
- <humidity data="Feuchtigkeit: 57 %"/>
16
- <icon data="/ig/images/weather/sunny.gif"/>
17
- <wind_condition data="Wind: W mit 24 km/h"/>
18
- </current_conditions>
19
- <forecast_conditions>
20
- <day_of_week data="Do."/><low data="16"/>
21
- <high data="31"/>
22
- <icon data="/ig/images/weather/chance_of_rain.gif"/>
23
- <condition data="Vereinzelt Regen"/>
24
- </forecast_conditions>
25
- </weather>
26
- </xml_api_reply>
@@ -1,14 +0,0 @@
1
- require 'rubygems'
2
- require "bundler/setup"
3
-
4
- require "test/unit"
5
- require "active_support/test_case"
6
- Bundler.require(:default, :development)
7
- require 'test/factories'
8
-
9
- # Configure for test mode
10
- require 'regentanz/test_helper'
11
- setup_regentanz_test_configuration! do |config|
12
- config.cache_dir = File.expand_path(File.join(File.dirname(__FILE__), '', 'support', 'tmp'))
13
- config.retry_marker = File.expand_path(File.join(File.dirname(__FILE__), 'support', 'tmp', 'test_api_retry.txt'))
14
- end
@@ -1,26 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
-
3
- class AstronomyTest < Test::Unit::TestCase
4
-
5
- def setup
6
- @object = Object.new
7
- @object.extend Regentanz::Astronomy
8
- end
9
-
10
- def test_google_weather_should_include_astronomy
11
- assert Regentanz::GoogleWeather.included_modules.include?(Regentanz::Astronomy)
12
- end
13
-
14
- def test_deg_to_rad
15
- assert Regentanz::Astronomy.private_instance_methods.include?("deg_to_rad")
16
- degrees = 42
17
- assert_equal degrees*Math::PI/180, @object.send(:deg_to_rad, degrees)
18
- end
19
-
20
- def test_rad_to_deg
21
- assert Regentanz::Astronomy.private_instance_methods.include?("rad_to_deg")
22
- radians = 42
23
- assert_equal radians*180/Math::PI, @object.send(:rad_to_deg, radians)
24
- end
25
-
26
- end
@@ -1,53 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
- require 'digest/sha1'
3
-
4
- class Regentanz::Cache::BaseTest < ActiveSupport::TestCase
5
-
6
- LINT_METHODS = [:available?, :expire!, :get, :set, :valid?]
7
-
8
- test "should define public interface for all cache backend" do
9
- obj = Regentanz::Cache::Base.new
10
- LINT_METHODS.each do |method|
11
- assert_respond_to obj, method
12
- end
13
- end
14
-
15
- test "should have check cache backend compatability via lint class method" do
16
- assert_respond_to Regentanz::Cache::Base, :lint
17
-
18
- obj = Object.new
19
- assert !Regentanz::Cache::Base.lint(obj)
20
- assert !Regentanz::Cache::Base.lint(Object)
21
-
22
- LINT_METHODS.each do |method|
23
- Object.any_instance.stubs(method)
24
- end
25
- assert Regentanz::Cache::Base.lint(obj)
26
- assert Regentanz::Cache::Base.lint(Object)
27
- end
28
-
29
- test "should have key sanitizer class method" do
30
- assert_respond_to Regentanz::Cache::Base, :sanitize_key
31
- key = Digest::SHA1.hexdigest("a test string")
32
- assert_equal key, Regentanz::Cache::Base.sanitize_key("a test string")
33
-
34
- assert_not_equal Regentanz::Cache::Base.sanitize_key("a test string"),
35
- Regentanz::Cache::Base.sanitize_key("another test string")
36
- end
37
-
38
- test "should inform about retry state" do
39
- obj = Regentanz::Cache::Base.new
40
- assert_respond_to obj, :waiting_for_retry?
41
- end
42
-
43
- test "should check if retry wait time is over" do
44
- obj = Regentanz::Cache::Base.new
45
- assert_respond_to obj, :unset_retry_state!
46
- end
47
-
48
- test "should enter retry state" do
49
- obj = Regentanz::Cache::Base.new
50
- assert_respond_to obj, :set_retry_state!
51
- end
52
-
53
- end
@@ -1,141 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
-
3
- class Regentanz::Cache::FileTest < ActiveSupport::TestCase
4
-
5
- def setup
6
- setup_regentanz_test_configuration!
7
- end
8
-
9
- def teardown
10
- Dir.glob(File.join(Regentanz.configuration.cache_dir, "**", "*")).each { |file| File.unlink(file) }
11
- end
12
-
13
- test "should not fail lint" do
14
- assert Regentanz::Cache::Base.lint(Regentanz::Cache::File)
15
- assert Regentanz::Cache::Base.lint(Regentanz::Cache::File.new)
16
- end
17
-
18
- test "should return filename for key" do
19
- obj = Regentanz::Cache::File.new
20
- assert_respond_to obj, :filename
21
- filename = File.join(Regentanz.configuration.cache_dir, "regentanz_test.xml")
22
- assert_equal filename, obj.filename("test")
23
- end
24
-
25
- test "should create cache file" do
26
- obj = Regentanz::Cache::File.new
27
- assert !File.exists?(obj.filename("test"))
28
- assert obj.set("test", "some cache values")
29
- assert File.exists?(obj.filename("test"))
30
- end
31
-
32
- test "should rescue set from saving errors" do
33
- File.expects(:open).raises(SystemCallError, "pretend something went wrong")
34
- obj = Regentanz::Cache::File.new
35
- assert_nothing_raised do
36
- assert !obj.set("test", "some cache values")
37
- end
38
- end
39
-
40
- test "available?" do
41
- obj = Regentanz::Cache::File.new
42
- assert !obj.available?("test")
43
-
44
- File.new(obj.filename("test"), "w+").close
45
- assert obj.available?("test")
46
- end
47
-
48
- test "should delete file after expire" do
49
- obj = Regentanz::Cache::File.new
50
- assert !obj.expire!("test") # nothing to expire, return false
51
-
52
- File.new(obj.filename("test"), "w+").close
53
- assert obj.expire!("test")
54
- assert !File.exists?(obj.filename("test"))
55
- end
56
-
57
- test "should rescue expire from saving errors" do
58
- File.expects(:delete).raises(SystemCallError, "pretend something went wrong").once
59
- obj = Regentanz::Cache::File.new
60
- assert_nothing_raised do
61
- File.new(obj.filename("test"), "w+").close
62
- assert !obj.expire!("test")
63
- end
64
- end
65
-
66
- test "should get contents from file" do
67
- obj = Regentanz::Cache::File.new
68
-
69
- File.open(obj.filename('test_get'), 'w+') {|file| file.print "cached data" }
70
- assert obj.available?('test_get')
71
- assert_equal "cached data", obj.get('test_get')
72
- # cache not available, return false
73
- assert_nil obj.get("does not exist")
74
- end
75
-
76
- test "should rescue get from reading errors" do
77
- obj = Regentanz::Cache::File.new
78
- File.open(obj.filename('test'), 'w+') {|file| file.print "cached data" }
79
- File.expects(:open).raises(SystemCallError, "pretend something went wrong").once
80
-
81
- assert_nothing_raised do
82
- assert !obj.get("test")
83
- end
84
- end
85
-
86
- test "should check validity" do
87
- obj = Regentanz::Cache::File.new
88
- assert !obj.valid?('test')
89
- File.open(obj.filename('test'), 'w+') { |file| file.puts valid_xml_response }
90
-
91
- # valid_xml_response contains current datestamp,
92
- # so should be valid on all fronts
93
- assert obj.valid?('test')
94
-
95
- # Pretend the file is too old
96
- Regentanz.configuration.cache_ttl = 0
97
- assert !obj.valid?('test')
98
- end
99
-
100
- test "should rescue valid from REXML errors" do
101
- obj = Regentanz::Cache::File.new
102
- File.open(obj.filename('test'), 'w+') { |file| file.puts invalid_xml_response }
103
- REXML::Document.expects(:new).raises(REXML::ParseException, "pretend something went wrong")
104
-
105
- assert_nothing_raised do
106
- assert !obj.valid?('test')
107
- end
108
- end
109
-
110
- # ##############################
111
- # Retry-state tests
112
- # ##############################
113
-
114
- test "should inform about retry state" do
115
- obj = Regentanz::Cache::File.new
116
- assert !obj.waiting_for_retry?
117
-
118
- File.expects(:exists?).with(Regentanz.configuration.retry_marker).returns(true)
119
- assert obj.waiting_for_retry?
120
- end
121
-
122
- test "should check if retry wait time is over" do
123
- obj = Regentanz::Cache::File.new
124
- File.new(Regentanz.configuration.retry_marker, "w+").close
125
- Regentanz.configuration.retry_ttl = 1000.hours.to_i # something incredibly high to warrant retry state
126
- assert !obj.unset_retry_state! # not waited long enough
127
-
128
- Regentanz.configuration.retry_ttl = 0
129
- assert obj.unset_retry_state!
130
- assert !File.exists?(Regentanz.configuration.retry_marker)
131
- end
132
-
133
- test "should enter retry state" do
134
- obj = Regentanz::Cache::File.new
135
- assert !File.exists?(Regentanz.configuration.retry_marker)
136
- assert obj.set_retry_state!
137
- assert obj.set_retry_state! # subsequent calls return the same
138
- assert File.exists?(Regentanz.configuration.retry_marker)
139
- end
140
-
141
- end