regentanz 0.3.3 → 1.0.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.
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