icalendar 2.0.0.beta.2 → 2.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.
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