kopia lustrzana https://github.com/collective/icalendar
				
				
				
			Fixes bug when date-time is recognized as time
Date-time was recognized incorrectly as a date or time. This resulted in wrong representation of some iCalendar strings. Also adds "errors" list in Component for saving error strings from parsing. https://github.com/collective/icalendar/issues/174 https://github.com/collective/icalendar/issues/168pull/175/head
							rodzic
							
								
									ff1f2eec3d
								
							
						
					
					
						commit
						70a7b5a167
					
				|  | @ -10,6 +10,10 @@ New: | |||
| 
 | ||||
| Fixes: | ||||
| 
 | ||||
| - Fixed date-time being recognized as date or time during parsing. Added | ||||
|   better error handling to parsing from ical strings. | ||||
|   [stlaz] | ||||
| 
 | ||||
| - Added __version__ attribute to init.py | ||||
|   [TomTry] | ||||
| 
 | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ icalendar contributors | |||
| - Ronan Dunklau <ronan@dunklau.fr> | ||||
| - Russ <russ@rw.id.au> | ||||
| - Sidnei da Silva <sidnei@enfoldsystems.com> | ||||
| - Stanislav Láznička <slaznick@redhat.com> | ||||
| - Stanislav Ochotnicky <sochotnicky@redhat.com> | ||||
| - Stefan Schwarzer <sschwarzer@sschwarzer.net> | ||||
| - Thomas Bruederli <thomas@roundcube.net> | ||||
|  |  | |||
|  | @ -80,8 +80,8 @@ class Component(CaselessDict): | |||
|         super(Component, self).__init__(*args, **kwargs) | ||||
|         # set parameters here for properties that use non-default values | ||||
|         self.subcomponents = []  # Components can be nested. | ||||
|         self.is_broken = False  # True if we ignored an exception while | ||||
|                                 # parsing a property | ||||
|         self.errors = list()  # If we ignored exception(s) while | ||||
|                                  # parsing a property, contains error strings | ||||
| 
 | ||||
|     # def is_compliant(self, name): | ||||
|     #    """Returns True is the given property name is compliant with the | ||||
|  | @ -309,14 +309,14 @@ class Component(CaselessDict): | |||
| 
 | ||||
|             try: | ||||
|                 name, params, vals = line.parts() | ||||
|             except ValueError: | ||||
|             except ValueError as e: | ||||
|                 # if unable to parse a line within a component | ||||
|                 # that ignores exceptions, mark the component | ||||
|                 # as broken and skip the line. otherwise raise. | ||||
|                 component = stack[-1] if stack else None | ||||
|                 if not component or not component.ignore_exceptions: | ||||
|                     raise | ||||
|                 component.is_broken = True | ||||
|                 component.errors.append((None, str(e))) | ||||
|                 continue | ||||
| 
 | ||||
|             uname = name.upper() | ||||
|  | @ -338,8 +338,7 @@ class Component(CaselessDict): | |||
|                 if not stack:  # we are at the end | ||||
|                     comps.append(component) | ||||
|                 else: | ||||
|                     if not component.is_broken: | ||||
|                         stack[-1].add_component(component) | ||||
|                     stack[-1].add_component(component) | ||||
|                 if vals == 'VTIMEZONE' and \ | ||||
|                         'TZID' in component and \ | ||||
|                         component['TZID'] not in pytz.all_timezones and \ | ||||
|  | @ -356,10 +355,11 @@ class Component(CaselessDict): | |||
|                         vals = factory(factory.from_ical(vals, params['TZID'])) | ||||
|                     else: | ||||
|                         vals = factory(factory.from_ical(vals)) | ||||
|                 except ValueError: | ||||
|                 except ValueError as e: | ||||
|                     if not component.ignore_exceptions: | ||||
|                         raise | ||||
|                     component.is_broken = True | ||||
|                     component.errors.append((uname, str(e))) | ||||
|                     component.add(name, None, encode=0) | ||||
|                 else: | ||||
|                     vals.params = params | ||||
|                     component.add(name, vals, encode=0) | ||||
|  |  | |||
|  | @ -341,7 +341,7 @@ class Contentline(compat.unicode_type): | |||
|             return (name, params, values) | ||||
|         except ValueError as exc: | ||||
|             raise ValueError( | ||||
|                 u"Content line could not be parsed into parts: %r: %s" | ||||
|                 u"Content line could not be parsed into parts: '%s': %s" | ||||
|                 % (self, exc) | ||||
|             ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -313,13 +313,15 @@ class vDDDTypes(object): | |||
|         u = ical.upper() | ||||
|         if u.startswith(('P', '-P', '+P')): | ||||
|             return vDuration.from_ical(ical) | ||||
|         try: | ||||
| 
 | ||||
|         if len(ical) in (15, 16): | ||||
|             return vDatetime.from_ical(ical, timezone=timezone) | ||||
|         except ValueError: | ||||
|             try: | ||||
|                 return vDate.from_ical(ical) | ||||
|             except ValueError: | ||||
|                 return vTime.from_ical(ical) | ||||
|         elif len(ical) == 8: | ||||
|             return vDate.from_ical(ical) | ||||
|         elif len(ical) in (6,7): | ||||
|             return vTime.from_ical(ical) | ||||
|         else: | ||||
|             raise ValueError("Expected datetime, date, or time, got: '%s'" % ical) | ||||
| 
 | ||||
| 
 | ||||
| class vDate(object): | ||||
|  |  | |||
|  | @ -200,7 +200,9 @@ X | |||
| END:VEVENT""" | ||||
|         event = icalendar.Calendar.from_ical(ical_str) | ||||
|         self.assertTrue(isinstance(event, icalendar.Event)) | ||||
|         self.assertTrue(event.is_broken) | ||||
|         self.assertEqual(event.errors, | ||||
|             [(None, "Content line could not be parsed into parts: 'X': Invalid content line")] | ||||
|         ) | ||||
| 
 | ||||
|     def test_issue_104__no_ignore_exceptions(self): | ||||
|         """ | ||||
|  |  | |||
|  | @ -389,8 +389,9 @@ class TestCal(unittest.TestCase): | |||
|         directory = tempfile.mkdtemp() | ||||
|         open(os.path.join(directory, 'test.ics'), 'wb').write(cal.to_ical()) | ||||
| 
 | ||||
|         # Parsing a complete calendar from a string will silently ignore bogus | ||||
|         # events. The bogosity in the following is the third EXDATE: it has an | ||||
|         # Parsing a complete calendar from a string will silently ignore wrong | ||||
|         # events but adding the error information to the component's 'errors' | ||||
|         # attribute. The error in the following is the third EXDATE: it has an | ||||
|         # empty DATE. | ||||
|         s = '\r\n'.join(('BEGIN:VCALENDAR', | ||||
|                          'PRODID:-//Google Inc//Google Calendar 70.9054//EN', | ||||
|  | @ -405,7 +406,7 @@ class TestCal(unittest.TestCase): | |||
|                          'EXDATE;VALUE=DATE:20080311', | ||||
|                          'END:VEVENT', | ||||
|                          'BEGIN:VEVENT', | ||||
|                          'DESCRIPTION:Bogus event', | ||||
|                          'DESCRIPTION:Wrong event', | ||||
|                          'DTSTART;VALUE=DATE:20080303', | ||||
|                          'DTEND;VALUE=DATE:20080304', | ||||
|                          'RRULE:FREQ=DAILY;UNTIL=20080323T235959Z', | ||||
|  | @ -416,4 +417,9 @@ class TestCal(unittest.TestCase): | |||
|         self.assertEqual( | ||||
|             [e['DESCRIPTION'].to_ical() | ||||
|                 for e in icalendar.cal.Calendar.from_ical(s).walk('VEVENT')], | ||||
|             [b'Perfectly OK event']) | ||||
|             [b'Perfectly OK event', b'Wrong event']) | ||||
|         self.assertEqual( | ||||
|             [e.errors | ||||
|                 for e in icalendar.cal.Calendar.from_ical(s).walk('VEVENT')], | ||||
|             [[], [('EXDATE', "Expected datetime, date, or time, got: ''")]] | ||||
|             ) | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Stanislav Laznicka
						Stanislav Laznicka