icalendar 2.0.0.beta.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a5e107e53784e1a46b2eea851f53da90b4c7a5d
4
- data.tar.gz: fc7ab4fdf29eee625e3b34f0c2989611973cb12a
3
+ metadata.gz: 1bec860be74d825a4185f664e5faf729a7dab764
4
+ data.tar.gz: 5b4f8aa6e13794637bd35e1094df96426a8622c1
5
5
  SHA512:
6
- metadata.gz: 8370c7815a1b841a87559805efe26cfe42762bfd6447a44206856fa30b347c6aedab88f6ff1690e44d3512d76506b7d5ca3c2438f9cc0bd53c360a6f84c426bc
7
- data.tar.gz: 38d884b87d744f5224221577d3b0e525810823900c064a1c4c42097235db0fc3a3a16c5cc58e13728846047231753e5a4804bb41a6695874a3261157717d4e6a
6
+ metadata.gz: f2097431525222e84223153f4e1288363600c9635fa29ce951de03ddcb8f400b327d55561861f14032df344db8acc1157c44395cd5a42f1f95eef312555f7cb6
7
+ data.tar.gz: 7b26558a56b5a5e40ab08c4841288122810151de6f701deeb76da0785af4ae57cc0fc2a335354e587a7e2e433f9708640aa3db7108a722bbe48cd370a9d6f0e2
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ Gemfile.lock
5
5
  pkg/
6
6
  .bundle
7
7
  coverage/
8
+ tags
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 2.0.0 2014-04-22
2
+ * Add Icalendar.logger class & logging in Parser
3
+ * Support tzinfo ~> 0.3 and ~> 1.1
4
+
1
5
  === 2.0.0.beta.2 2014-04-11
2
6
  * Add uid & acknowledged fields from valarm extensions
3
7
  * Swallow NoMethodError on non-strict parsers
data/README.md CHANGED
@@ -64,20 +64,22 @@ EXAMPLES
64
64
 
65
65
  params = {"altrep" => "http://my.language.net", "language" => "SPANISH"}
66
66
 
67
- cal.event do |e|
67
+ event = cal.event do |e|
68
68
  e.dtstart = Icalendar::Values::Date.new('20050428')
69
69
  e.dtend = Icalendar::Values::Date.new('20050429')
70
70
  e.summary = Icalendar::Values::Text.new "This is a summary with params.", params
71
71
  end
72
+ event.summary.ical_params #=> {'altrep' => 'http://my.language.net', 'language' => 'SPANISH'}
72
73
 
73
74
  # or
74
75
 
75
- cal.event do |e|
76
+ event = cal.event do |e|
76
77
  e.dtstart = Icalendar::Values::Date.new('20050428')
77
78
  e.dtend = Icalendar::Values::Date.new('20050429')
78
79
  e.summary = "This is a summary with params."
79
80
  e.summary.ical_params = params
80
81
  end
82
+ event.summary.ical_params #=> {'altrep' => 'http://my.language.net', 'language' => 'SPANISH'}
81
83
 
82
84
  #### We can output the calendar as a string ####
83
85
 
@@ -184,7 +186,9 @@ TIMEZONES
184
186
  # END:VTIMEZONE
185
187
 
186
188
  iCalendar has some basic support for creating VTIMEZONE blocks from timezone information pulled from `tzinfo`.
187
- You must require `tzinfo` support manually to take advantage, and iCalendar only supports `tzinfo` with versions `~> 0.3`
189
+ You must require `tzinfo` support manually to take advantage.
190
+
191
+ iCalendar has been tested and works with `tzinfo` versions 0.3 and 1.1
188
192
 
189
193
  #### Example ####
190
194
 
data/icalendar.gemspec CHANGED
@@ -22,9 +22,19 @@ variety of calendaring applications.
22
22
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename f }
23
23
  s.require_paths = ['lib']
24
24
 
25
+ s.required_ruby_version = '>= 1.9.3'
26
+
25
27
  s.add_development_dependency 'rake', '~> 10.0'
26
28
  s.add_development_dependency 'bundler', '~> 1.3'
27
- s.add_development_dependency 'tzinfo', '~> 0.3'
29
+
30
+ # test with both groups of tzinfo dependencies
31
+ # tzinfo 1.x
32
+ s.add_development_dependency 'tzinfo', '~> 1.1'
33
+ s.add_development_dependency 'tzinfo-data', '~> 1.2014'
34
+ # tzinfo 0.x
35
+ # s.add_development_dependency 'tzinfo', '~> 0.3'
36
+ # end tzinfo
37
+
28
38
  s.add_development_dependency 'activesupport', '~> 3.2'
29
39
  s.add_development_dependency 'timecop', '~> 0.7.0'
30
40
  s.add_development_dependency 'rspec', '~> 2.14'
data/lib/icalendar.rb CHANGED
@@ -1,7 +1,17 @@
1
+ require 'icalendar/logger'
2
+
1
3
  module Icalendar
2
4
 
3
5
  MAX_LINE_LENGTH = 75
4
6
 
7
+ def self.logger
8
+ @logger ||= Icalendar::Logger.new(STDERR)
9
+ end
10
+
11
+ def self.logger=(logger)
12
+ @logger = logger
13
+ end
14
+
5
15
  def self.parse(source, single = false)
6
16
  calendars = Parser.new(source).parse
7
17
  single ? calendars.first : calendars
@@ -20,4 +30,4 @@ require 'icalendar/journal'
20
30
  require 'icalendar/freebusy'
21
31
  require 'icalendar/timezone'
22
32
  require 'icalendar/calendar'
23
- require 'icalendar/parser'
33
+ require 'icalendar/parser'
@@ -0,0 +1,16 @@
1
+ require 'delegate'
2
+ require 'logger'
3
+
4
+ module Icalendar
5
+
6
+ class Logger < ::SimpleDelegator
7
+
8
+ def initialize(sink, level = ::Logger::WARN)
9
+ logger = ::Logger.new(sink)
10
+ logger.level = level
11
+ super logger
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -10,7 +10,9 @@ module Icalendar
10
10
  elsif source.respond_to? :to_s
11
11
  @source = StringIO.new source.to_s, 'r'
12
12
  else
13
- raise ArgumentError, 'Icalendar::Parser.new must be called with a String or IO object'
13
+ msg = 'Icalendar::Parser.new must be called with a String or IO object'
14
+ Icalendar.fatal msg
15
+ fail ArgumentError, msg
14
16
  end
15
17
  read_in_data
16
18
  @strict = strict
@@ -49,13 +51,19 @@ module Icalendar
49
51
  end
50
52
  prop_name = %w(class method).include?(fields[:name]) ? "ip_#{fields[:name]}" : fields[:name]
51
53
  begin
52
- if component.class.multiple_properties.include? prop_name
53
- component.send "append_#{prop_name}", prop_value
54
+ method_name = if component.class.multiple_properties.include? prop_name
55
+ "append_#{prop_name}"
54
56
  else
55
- component.send "#{prop_name}=", prop_value
57
+ "#{prop_name}="
56
58
  end
59
+ component.send method_name, prop_value
57
60
  rescue NoMethodError => nme
58
- raise nme if strict?
61
+ if strict?
62
+ Icalendar.logger.error "No method \"#{method_name}\" for component #{component}"
63
+ raise nme
64
+ else
65
+ Icalendar.logger.warn "No method \"#{method_name}\" for component #{component}. Skipping."
66
+ end
59
67
  end
60
68
  end
61
69
 
@@ -71,6 +79,7 @@ module Icalendar
71
79
  break
72
80
  elsif fields[:name] == 'begin'
73
81
  klass_name = fields[:value].gsub(/\AV/, '').downcase.capitalize
82
+ Icalendar.logger.debug "Adding component #{klass_name}"
74
83
  if Icalendar.const_defined? klass_name
75
84
  component.add_component parse_component(Icalendar.const_get(klass_name).new)
76
85
  elsif Icalendar::Timezone.const_defined? klass_name
@@ -79,7 +88,6 @@ module Icalendar
79
88
  component.add_component parse_component(Component.new klass_name.downcase, fields[:value])
80
89
  end
81
90
  else
82
- # new property
83
91
  parse_property component, fields
84
92
  end
85
93
  end
@@ -112,7 +120,7 @@ module Icalendar
112
120
  LINE = "(?<name>#{NAME})(?<params>(?:;#{PARAM})*):(?<value>#{VALUE})"
113
121
 
114
122
  def parse_fields(input)
115
- parts = %r{#{LINE}}.match(input) or raise "Invalid iCalendar input line: #{input}"
123
+ parts = %r{#{LINE}}.match(input) or fail "Invalid iCalendar input line: #{input}"
116
124
  params = {}
117
125
  parts[:params].scan %r{#{PARAM}} do |match|
118
126
  param_name = match[0].downcase
@@ -121,6 +129,7 @@ module Icalendar
121
129
  params[param_name] << param_value.gsub(/\A"|"\z/, '') if param_value.size > 0
122
130
  end
123
131
  end
132
+ Icalendar.logger.debug "Found fields: #{parts.inspect} with params: #{params.inspect}"
124
133
  {
125
134
  name: parts[:name].downcase.gsub('-', '_'),
126
135
  params: params,
@@ -21,7 +21,7 @@
21
21
  # # the mixins now generate all the timezone info for the date in question
22
22
  # timezone = tz.ical_timezone(estart)
23
23
  # cal.add(timezone)
24
- #
24
+ #
25
25
  # cal.event do
26
26
  # dtstart estart
27
27
  # dtend eend
@@ -40,26 +40,14 @@
40
40
 
41
41
 
42
42
  require 'tzinfo'
43
+ begin
44
+ require 'tzinfo/data'
45
+ rescue LoadError
46
+ Icalendar.logger.info "Could not load tzinfo/data, hopefully tzinfo is accurate (ignore for tzinfo 0.x)"
47
+ end
43
48
 
44
- module TZInfo
45
- class Timezone
46
- def ical_timezone(date, dst = Timezone.default_dst)
47
- period = period_for_local(date, dst)
48
- timezone = Icalendar::Timezone.new
49
- timezone.tzid = identifier
50
- if period.start_transition.nil?
51
- timezone.add_component period.single
52
- elsif period.end_transition.nil?
53
- timezone.add_component period.dst? ? period.daylight : period.standard
54
- else
55
- timezone.add_component period.daylight
56
- timezone.add_component period.standard
57
- end
58
- timezone
59
- end
60
- end
61
-
62
- class TimezoneTransitionInfo
49
+ module Icalendar
50
+ module TimezoneTransition
63
51
  def offset_from
64
52
  previous_offset.ical_offset
65
53
  end
@@ -68,7 +56,7 @@ module TZInfo
68
56
  offset.ical_offset
69
57
  end
70
58
 
71
- def rrule
59
+ def rrule
72
60
  start = local_start.to_datetime
73
61
  # this is somewhat of a hack, but seems to work ok
74
62
  [sprintf(
@@ -84,12 +72,52 @@ module TZInfo
84
72
  end
85
73
  end
86
74
 
87
- class TimezoneOffsetInfo
75
+ module TimezoneOffset
88
76
  def ical_offset
89
77
  o = utc_total_offset
90
78
  sprintf '%+-2.2d%2.2d', (o / 3600).to_i, ((o / 60) % 60).to_i
91
79
  end
92
80
  end
81
+ end
82
+
83
+
84
+ module TZInfo
85
+ class Timezone
86
+ def ical_timezone(date, dst = Timezone.default_dst)
87
+ period = period_for_local(date, dst)
88
+ timezone = Icalendar::Timezone.new
89
+ timezone.tzid = identifier
90
+ if period.start_transition.nil?
91
+ timezone.add_component period.single
92
+ elsif period.end_transition.nil?
93
+ timezone.add_component period.dst? ? period.daylight : period.standard
94
+ else
95
+ timezone.add_component period.daylight
96
+ timezone.add_component period.standard
97
+ end
98
+ timezone
99
+ end
100
+ end
101
+
102
+ if defined? TimezoneTransitionInfo
103
+ class TimezoneTransitionInfo
104
+ include Icalendar::TimezoneTransition
105
+ end
106
+ else
107
+ class TimezoneTransition
108
+ include Icalendar::TimezoneTransition
109
+ end
110
+ end
111
+
112
+ if defined? TimezoneOffsetInfo
113
+ class TimezoneOffsetInfo
114
+ include Icalendar::TimezoneOffset
115
+ end
116
+ else
117
+ class TimezoneOffset
118
+ include Icalendar::TimezoneOffset
119
+ end
120
+ end
93
121
 
94
122
  class TimezonePeriod
95
123
  def daylight
@@ -1,5 +1,5 @@
1
1
  module Icalendar
2
2
 
3
- VERSION = '2.0.0.beta.2'
3
+ VERSION = '2.0.0'
4
4
 
5
5
  end
@@ -0,0 +1,25 @@
1
+ BEGIN:VCALENDAR
2
+ VERSION:2.0
3
+ PRODID:bsprodidfortestabc123
4
+ BEGIN:VEVENT
5
+ UID:bsuidfortestabc123
6
+ ORGANIZER:mailto:joebob@random.net
7
+ ATTACH:http://bush.sucks.org/impeach/him.rhtml
8
+ ATTACH:http://corporations-dominate.existence.net/why.rhtml
9
+ SUMMARY:This is a really long summary
10
+ to test the method of unfolding lines\,
11
+ so I'm just going to ma
12
+ ke it
13
+ a whol
14
+ e
15
+ bunch of lines.
16
+ CLASS:PRIVATE
17
+ PRIORITY:2
18
+ CUSTOMFIELD:Not properly noted as custom with X- prefix.
19
+ GEO:37.386013;-122.0829322
20
+ DTSTART;TZID=US-Mountain:20050120T170000
21
+ DTEND:20050120T184500
22
+ DTSTAMP:20050118T211523Z
23
+ NAME:SomeName
24
+ END:VEVENT
25
+ END:VCALENDAR
@@ -37,4 +37,21 @@ describe Icalendar do
37
37
  expect(subject.dtend.to_ical(subject.class.default_property_types['dtend'])).to match /^;VALUE=DATE:20061215$/
38
38
  end
39
39
  end
40
+
41
+ describe 'non-standard values' do
42
+ before(:all) { Icalendar.logger = Icalendar::Logger.new File::NULL }
43
+ after(:all) { Icalendar.logger = nil }
44
+ let(:source) { File.read File.join(File.dirname(__FILE__), 'fixtures', 'nonstandard.ics') }
45
+ subject { Icalendar::Parser.new(source, strict) }
46
+
47
+ context 'strict parser' do
48
+ let(:strict) { true }
49
+ specify { expect { subject.parse }.to raise_error }
50
+ end
51
+
52
+ context 'lenient parser' do
53
+ let(:strict) { false }
54
+ specify { expect { subject.parse}.to_not raise_error }
55
+ end
56
+ end
40
57
  end
data/spec/tzinfo_spec.rb CHANGED
@@ -82,4 +82,4 @@ END:VTIMEZONE
82
82
  end
83
83
  end
84
84
 
85
- end
85
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icalendar
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Ahearn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-11 00:00:00.000000000 Z
11
+ date: 2014-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -44,14 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '0.3'
47
+ version: '1.1'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0.3'
54
+ version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tzinfo-data
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2014'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2014'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: activesupport
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +150,7 @@ files:
136
150
  - lib/icalendar/has_components.rb
137
151
  - lib/icalendar/has_properties.rb
138
152
  - lib/icalendar/journal.rb
153
+ - lib/icalendar/logger.rb
139
154
  - lib/icalendar/parser.rb
140
155
  - lib/icalendar/timezone.rb
141
156
  - lib/icalendar/todo.rb
@@ -162,6 +177,7 @@ files:
162
177
  - spec/calendar_spec.rb
163
178
  - spec/event_spec.rb
164
179
  - spec/fixtures/nondefault_values.ics
180
+ - spec/fixtures/nonstandard.ics
165
181
  - spec/fixtures/single_event.ics
166
182
  - spec/fixtures/timezone.ics
167
183
  - spec/freebusy_spec.rb
@@ -192,12 +208,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
208
  requirements:
193
209
  - - '>='
194
210
  - !ruby/object:Gem::Version
195
- version: '0'
211
+ version: 1.9.3
196
212
  required_rubygems_version: !ruby/object:Gem::Requirement
197
213
  requirements:
198
- - - '>'
214
+ - - '>='
199
215
  - !ruby/object:Gem::Version
200
- version: 1.3.1
216
+ version: '0'
201
217
  requirements: []
202
218
  rubyforge_project:
203
219
  rubygems_version: 2.0.14
@@ -209,6 +225,7 @@ test_files:
209
225
  - spec/calendar_spec.rb
210
226
  - spec/event_spec.rb
211
227
  - spec/fixtures/nondefault_values.ics
228
+ - spec/fixtures/nonstandard.ics
212
229
  - spec/fixtures/single_event.ics
213
230
  - spec/fixtures/timezone.ics
214
231
  - spec/freebusy_spec.rb