Esempio n. 1
0
    def test_get_property(self):
        cal = self.cal1

        # Component property
        events = cal.get_components('VEVENT')
        properties = events[0][-1]

        expected = u'Résumé'
        property = events[0].get_property('SUMMARY')
        self.assertEqual(property.value, expected)

        expected = 1
        property = events[0].get_property('PRIORITY')
        self.assertEqual(property.value, expected)

        # Component properties
        properties = {}
        properties['MYADD'] = Property(u'Résumé à crêtes')
        value = Property(u'Property added by calling add_property')
        properties['DESCRIPTION'] = value
        member = '"mailto:[email protected]"'
        value = Property('mailto:[email protected]', MEMBER=[member])
        properties['ATTENDEE'] = value
        properties['type'] = 'VEVENT'
        uid = cal.add_record(properties).UID

        event = cal.get_component_by_uid(uid)[0]
        properties = event.get_property()
        self.assertEqual('MYADD' in properties, True)
        self.assertEqual('DESCRIPTION' in properties, True)
        self.assertEqual('ATTENDEE' in properties, True)
        self.assertEqual('VERSION' in properties, False)
Esempio n. 2
0
    def test_add_property(self):
        """Test adding a property to any component.
        """
        cal = self.cal2
        event = cal.get_components('VEVENT')[1]

        # other property (MYADD)
        name, value = 'MYADD', Property(u'Résumé à crêtes')
        cal.update_record(event.id, **{name: value})

        property = event.get_property(name)
        self.assertEqual(property[0], value)
        self.assertEqual(property[0].value, value.value)

        # property DESCRIPTION
        name = 'DESCRIPTION'
        value = Property(u'Property added by calling add_property')
        cal.update_record(event.id, **{name: value})

        property = event.get_property(name)
        self.assertEqual(property, value)

        # property ATTENDEE
        name = 'ATTENDEE'
        value = event.get_property(name)
        member = '"mailto:[email protected]"'
        value.append(Property('mailto:[email protected]', MEMBER=[member]))
        cal.update_record(event.id, **{name: value})

        property = event.get_property(name)
        self.assertEqual(str(property[0].value), 'mailto:[email protected]')
        self.assertEqual(property[1].parameters, {'MEMBER': [member]})
        self.assertEqual(property[1], value[1])
Esempio n. 3
0
 def get_property(self, name, language=None):
     if name not in self.properties:
         return None
     value, lang = self.get_property_and_language(name, language=language)
     if lang:
         return Property(value, lang=lang)
     return Property(value)
Esempio n. 4
0
    def get_property(self, name, language=None):
        property = self.metadata.get_property(name, language=language)
        if property:
            return property

        field = self.get_field(name)
        if field is None:
            return None

        default = field.get_default()
        if field.multiple:
            return [Property(x) for x in default]
        return Property(default)
Esempio n. 5
0
 def reset_register_key(self, username):
     cc_list = self.get_property('cc_list')
     # Filter out username
     cc_list = [cc for cc in cc_list if cc.value != username]
     # Create new dict to force metadata commit
     cc_list.append(Property(username))
     self.set_property('cc_list', cc_list)
Esempio n. 6
0
 def setUp(self):
     metadata = Metadata(cls=WebPage)
     title = Property(u'Hello World', lang='en')
     metadata.set_property('title', title)
     self.metadata = metadata
     # Sandbox
     vfs.make_folder('sandbox')
Esempio n. 7
0
    def _set_value(self, resource, name, value, language=None, **kw):
        if language:
            kw['lang'] = language
        if kw:
            value = Property(value, **kw)

        resource.metadata.set_property(name, value)
Esempio n. 8
0
    def to_ical(self, context):
        """Serialize as an ical file, generally named .ics
        """

        lines = ['BEGIN:VCALENDAR\n',
                'VERSION:2.0\n',
                'PRODID:-//itaapy.com/NONSGML ikaaro icalendar V1.0//EN\n']

        # Calendar components
        for event in self.search_resources(cls=Event):
            lines.append('BEGIN:VEVENT\n')
            for ikaaro_name, ics_name in ikaaro_to_ics:
                property = event.get_property(ikaaro_name)
                lang = property.get_parameter('lang')
                if lang:
                    property = Property(property.value, LANGUAGE=lang)
                    p_schema = {'LANGUAGE': String(multiple=False)}
                else:
                    p_schema = None
                datatype = event.get_field(ikaaro_name).datatype
                line = property_to_str(ics_name, property, datatype, p_schema)
                lines.append(line)

            lines.append('END:VEVENT\n')
        lines.append('END:VCALENDAR\n')

        return ''.join(lines)
Esempio n. 9
0
    def test_component_set_property(self):
        """Test setting a new value to an existant component property.
        """
        cal = self.cal1
        event = cal.get_components('VEVENT')[0]

        name, value = 'SUMMARY', Property('This is a new summary')
        cal.update_component(event.uid, **{name: value})
        self.assertEqual(event.get_property_values(name), value)

        member = '"mailto:[email protected]"'
        value = [
            Property('mailto:[email protected]', MEMBER=[member]),
            Property('mailto:[email protected]'),
            Property('mailto:[email protected]')]
        cal.update_component(event.uid, ATTENDEE=value)
        self.assertEqual(event.get_property_values('ATTENDEE'), value)
Esempio n. 10
0
    def to_ical(self):
        """Serialize as an ical file, generally named .ics
        """
        lines = []

        line = 'BEGIN:VCALENDAR\n'
        lines.append(Unicode.encode(line))

        # Calendar properties
        properties = (('VERSION', u'2.0'),
                      ('PRODID',
                       u'-//itaapy.com/NONSGML ikaaro icalendar V1.0//EN'))
        for name, value in properties:
            value = Property(value)
            line = self.encode_property(name, value)
            lines.append(line[0])

        # Calendar components
        for record in self.records:
            if record is not None:
                seq = 0
                c_type = record.type
                # Ignore some components (like DAYLIGHT, STANDARD, ...)
                # keeping only VEVENT, VTIMEZONE, V.., and x-name ones
                if not c_type.startswith('V') and not c_type.startswith('X'):
                    continue
                for version in record:
                    line = 'BEGIN:%s\n' % c_type
                    lines.append(Unicode.encode(line))
                    line = ''
                    # Properties
                    names = version.keys()
                    names.sort()
                    for name in names:
                        if name in ('id', 'ts', 'type'):
                            continue
                        elif name == 'DTSTAMP':
                            value = version['ts']
                        else:
                            value = version[name]
                        if name == 'SEQUENCE':
                            value.value += seq
                        # Insert inner components
                        elif name == 'inner':
                            line = self.encode_inner_components(name, value)
                        else:
                            name = name.upper()
                            line = self.encode_property(name, value)
                        lines.extend(line)
                    line = 'END:%s\n' % c_type
                    lines.append(Unicode.encode(line))
                    seq += 1

        line = 'END:VCALENDAR\n'
        lines.append(Unicode.encode(line))

        return ''.join(lines)
Esempio n. 11
0
    def new(self):
        properties = (('VERSION', u'2.0'),
                      ('PRODID',
                       u'-//itaapy.com/NONSGML ikaaro icalendar V1.0//EN'))
        for name, value in properties:
            self.properties[name] = Property(value)

        # The encoding
        self.encoding = 'UTF-8'
Esempio n. 12
0
    def test_add_to_calendar(self):
        """Test to add property and component to an empty icalendar object.
        """
        cal = iCalendar()
        cal.add_component('VEVENT')
        self.assertEqual(len(cal.get_components('VEVENT')), 1)

        value = Property('PUBLISH')
        cal.set_property('METHOD', value)
        self.assertEqual(cal.get_property_values('METHOD'), value)
Esempio n. 13
0
    def test_property(self):
        """Test to create, access and encode a property with or without
        parameters.
        """
        # Property without parameter
        expected = ['SUMMARY:This is the summary\n']

        property_value = Property('This is the summary')
        output = self.cal1.encode_property('SUMMARY', property_value)
        self.assertEqual(output, expected)

        # Property with one parameter
        expected = ['ATTENDEE;MEMBER="mailto:[email protected]":'
                    'mailto:[email protected]\n']

        member = 'mailto:[email protected]'
        value = Property('mailto:[email protected]', MEMBER=[member])
        output = self.cal1.encode_property('ATTENDEE', value)
        self.assertEqual(output, expected)
Esempio n. 14
0
    def test_icalendar_set_property(self):
        """Test setting a new value to an existant icalendar property.
        """
        cal = self.cal1

        name, value = 'VERSION', Property('2.1')
        cal.set_property(name, value)
        self.assertEqual(cal.get_property_values(name), value)

        cal.set_property(name, [value, ])
        self.assertEqual(cal.get_property_values(name), value)
Esempio n. 15
0
 def _make_resource(cls, folder, name, *args, **kw):
     OrderedTable._make_resource(cls, folder, name)
     table = BaseCountriesZones()
     zones = []
     csv = ro_database.get_handler(get_abspath('data/countries.csv'),
                                   CSVFile)
     for line in csv.get_rows():
         zone = unicode(line[1], 'utf-8')
         if zone not in zones:
             zones.append(zone)
             table.add_record({'title': Property(zone, language='fr')})
     folder.set_handler(name, table)
Esempio n. 16
0
    def test_add_property(self):
        """Test adding a property to any component.
        """
        cal = self.cal2
        event = cal.get_components('VEVENT')[1]

        # other property (MYADD)
        name, value = 'MYADD', Property(u'Résumé à crêtes')
        cal.update_component(event.uid, **{name: value})

        property = event.get_property_values(name)
        self.assertEqual(property[0], value)
        self.assertEqual(property[0].value, value.value)

        # property DESCRIPTION
        name = 'DESCRIPTION'
        value = Property(u'Property added by calling add_property')
        cal.update_component(event.uid, **{name: value})

        property = event.get_property_values(name)
        self.assertEqual(property, value)

        # property ATTENDEE
        name = 'ATTENDEE'
        value = event.get_property_values(name)
        member = '"mailto:[email protected]"'
        value.append(Property('mailto:[email protected]', MEMBER=[member]))
        cal.update_component(event.uid, **{name: value})

        property = event.get_property_values(name)
        self.assertEqual(str(property[0].value), 'mailto:[email protected]')
        self.assertEqual(property[1].parameters, {'MEMBER': [member]})
        self.assertEqual(property[1], value[1])
Esempio n. 17
0
    def _set_property(self, name, value):
        properties = self.properties

        # Case 1: Remove property
        if value is None:
            if name in properties:
                del properties[name]
            return

        # Case 2: Multiple (replace)
        p_type = type(value)
        if p_type is list:
            properties[name] = [
                x if type(x) is Property else Property(x) for x in value
            ]
            return

        # Case 3: Multilingual
        if p_type is Property:
            if value.parameters and 'lang' in value.parameters:
                language = value.parameters['lang']
                properties.setdefault(name, {})[language] = value
                return
        else:
            value = Property(value)

        # Case 4: Simple
        cls = self.database.get_resource_class(self.format)
        field = cls.get_field(name)
        if field is None or field.multiple is False:
            properties[name] = value
            return

        # Case 5: Multiple (append)
        if not field.datatype.is_empty(value.value):
            properties.setdefault(name, []).append(value)
Esempio n. 18
0
    def add_record(self, kw):
        if 'UID' not in kw:
            type = kw.get('type', 'UNKNOWN')
            kw['UID'] = self.generate_uid(type)

        id = len(self.records)
        record = Record(id, self.record_properties)
        version = self.properties_to_dict(kw)
        version['ts'] = Property(datetime.now())
        record.append(version)
        # Change
        self.set_changed()
        self.added_records.append((id, 0))
        self.records.append(record)
        self.catalog.index_document(record)
        # Back
        return record
Esempio n. 19
0
    def add_version(self, properties):
        # Sequence in properties only if just loading file
        if 'SEQUENCE' in properties:
            sequence = properties.pop('SEQUENCE')
            sequence = sequence.value
        else:
            sequences = self.get_sequences()
            if sequences:
                sequence = sequences[-1] + 1
            else:
                sequence = 0

        # Timestamp
        if 'DTSTAMP' not in properties:
            properties['DTSTAMP'] = Property(datetime.today())

        self.versions[sequence] = properties
Esempio n. 20
0
 def set_register_key(self, username, unregister=False):
     cc_list = self.get_property('cc_list')
     status = 'U' if unregister is True else 'S'
     # Find existing key
     for cc in cc_list:
         key = cc.get_parameter('key')
         if (cc.value == username and cc.get_parameter('status') == status
                 and key is not None):
             # Reuse found key
             return key
     # Generate key
     key = generate_password(30)
     # Filter out username
     cc_list = [cc for cc in cc_list if cc.value != username]
     # Create new dict to force metadata commit
     cc_list.append(Property(username, status=status, key=key))
     self.set_property('cc_list', cc_list)
     return key
Esempio n. 21
0
 def _make_resource(cls, folder, name, *args, **kw):
     Table._make_resource(cls, folder, name)
     # Import CSV with list of countries
     zones = []
     table = BaseCountries()
     csv = ro_database.get_handler(get_abspath('data/countries.csv'),
                                   CSVFile)
     for line in csv.get_rows():
         country = unicode(line[0], 'utf-8')
         zone = unicode(line[1], 'utf-8')
         if zone not in zones:
             zones.append(zone)
         table.add_record({
             'title': Property(country, language='fr'),
             'zone': str(zones.index(zone)),
             'enabled': True
         })
     folder.set_handler(name, table)
Esempio n. 22
0
    def action_upload(self, resource, context, form):
        filename, mimetype, body = form['file']
        name, type, language = FileName.decode(filename)

        # Check the filename is good
        title = form['title'].strip()
        name = checkid(title) or checkid(name)
        if name is None:
            context.message = messages.MSG_BAD_NAME
            return

        # Get the container
        container = context.root.get_resource(form['target_path'])

        # Check the name is free
        if container.get_resource(name, soft=True) is not None:
            context.message = messages.MSG_NAME_CLASH
            return

        # Check it is of the expected type
        cls = context.database.get_resource_class(mimetype)
        if not self.can_upload(cls):
            error = u'The given file is not of the expected type.'
            context.message = ERROR(error)
            return

        kw = {'data': body, 'filename': filename}

        # Add the image to the resource
        child = container.make_resource(name, cls, **kw)
        # The title
        language = resource.get_edit_languages(context)[0]
        title = Property(title, lang=language)
        child.metadata.set_property('title', title)
        # Get the path
        path = child.abspath
        action = self.get_resource_action(context)
        if action:
            path = '%s%s' % (path, action)
        # Return javascript
        scripts = self.get_scripts(context)
        context.add_script(*scripts)
        return self.get_javascript_return(context, path)
Esempio n. 23
0
    def search_events(self, subset=None, **kw):
        """Return a list of Record objects of type 'VEVENT' corresponding to
        the given filters.

        It should be used like this, for example:

            events = cal.search_events(
                STATUS='TENTATIVE',
                PRIORITY=1,
                ATTENDEE=['mailto:[email protected]',
                          'mailto:[email protected]'])

        ** With a list of values, events match if at least one value matches

        It searches into all components or in the provided subset list of
        components.
        """
        res_events = []

        # Get the list of differents property names used to filter
        filters = kw.keys()

        # For each event
        events = subset or self.search(type='VEVENT')
        for event in events:
            if event in res_events:
                continue
            version = self.get_record(id=event.id)[-1]

            # For each filter
            for filter in filters:
                # If filter not in component, go to next one
                if filter not in version:
                    break
                # Test filter
                expected = kw.get(filter)
                value = version[filter]
                datatype = self.get_record_datatype(filter)

                if getattr(datatype, 'multiple', False) is True:
                    value = [
                        isinstance(x, Property) and x or Property(x)
                        for x in value
                    ]
                    if not isinstance(expected, list):
                        expected = [
                            expected,
                        ]
                    for item in value:
                        if item.value in expected:
                            break
                        elif item.value == expected:
                            break
                    else:
                        break
                else:
                    if not isinstance(value, Property):
                        value = Property(value)
                    if value.value != expected:
                        break
            else:
                res_events.append(event)
        return res_events
Esempio n. 24
0
    def _load_state_from_file(self, file):
        # Read the data and figure out the encoding
        data = file.read()
        encoding = guess_encoding(data)
        self.encoding = encoding

        # Parse
        lines = []
        for name, value, parameters in parse_table(data):
            # Deserialize
            datatype = self.get_record_datatype(name)
            if isinstance(datatype, Unicode):
                value = datatype.decode(value, encoding=encoding)
            else:
                value = datatype.decode(value)
            # Build the value (a Property instance)
            deserialize_parameters(parameters, self.record_parameters)
            value = Property(value, **parameters)
            # Append
            lines.append((name, value))

        # Read first line
        first = lines[0]
        if (first[0] != 'BEGIN' or first[1].value != 'VCALENDAR'
            or len(first[1].parameters) != 0):
            raise ValueError, 'icalendar must begin with BEGIN:VCALENDAR'

        lines = lines[1:]

        ###################################################################
        # Read properties
        n_line = 0
        for name, value in lines:
            if name == 'BEGIN':
                break
            elif name == 'END':
                break
            elif name == 'VERSION':
                if 'VERSION' in self.properties:
                    raise ValueError, 'VERSION can appear only one time'
            elif name == 'PRODID':
                if 'PRODID' in self.properties:
                    raise ValueError, 'PRODID can appear only one time'
            # Add the property
            self.properties[name] = value
            n_line += 1

        # The properties VERSION and PRODID are mandatory
        if ('VERSION' not in self.properties or
            'PRODID' not in self.properties):
            raise ValueError, 'PRODID or VERSION parameter missing'

        lines = lines[n_line:]

        ###################################################################
        # Read components
        c_type = None
        c_inner_type = None
        uid = None

        for prop_name, prop_value in lines[:-1]:
            if prop_name in ('PRODID', 'VERSION'):
                raise ValueError, 'PRODID and VERSION must appear before '\
                                  'any component'
            if prop_name == 'BEGIN':
                if c_type is None:
                    c_type = prop_value.value
                    c_properties = {}
                    c_inner_components = []
                else:
                    # Inner component like DAYLIGHT or STANDARD
                    c_inner_type = prop_value.value
                    c_inner_properties = {}
                continue

            if prop_name == 'END':
                value = prop_value.value
                if value == c_type:
                    if uid is None:
                        raise ValueError, 'UID is not present'

                    if uid in self.components:
                        component = self.components[uid]
                        component.add_version(c_properties)
                    else:
                        component = Component(c_type, uid)
                        component.add_version(c_properties)
                        component.c_inner_components = c_inner_components
                        self.components[uid] = component
                    # Next
                    c_type = None
                    uid = None
                # Inner component
                elif value == c_inner_type:
                    inner_component = InnerComponent(c_inner_type)
                    inner_component.add_version(c_inner_properties)
                    c_inner_components.append(inner_component)
                    c_inner_type = None
                else:
                    raise ValueError, 'Component %s found, %s expected' \
                                      % (value, c_inner_type)
            else:
                datatype = self.get_record_datatype(prop_name)
                if c_inner_type is None:
                    if prop_name in ('UID', 'TZID'):
                        uid = prop_value.value
                    else:
                        if getattr(datatype, 'multiple', False) is True:
                            value = c_properties.setdefault(prop_name, [])
                            value.append(prop_value)
                        else:
                            # Check the property has not yet being found
                            if prop_name in c_properties:
                                msg = ('the property %s can be assigned only '
                                       'one value' % prop_name)
                                raise ValueError, msg
                            # Set the property
                            c_properties[prop_name] = prop_value
                else:
                    # Inner component properties
                    if getattr(datatype, 'multiple', False) is True:
                        value = c_inner_properties.setdefault(prop_name, [])
                        value.append(prop_value)
                    else:
                        # Check the property has not yet being found
                        if prop_name in c_inner_properties:
                            msg = ('the property %s can be assigned only one'
                                   ' value' % prop_name)
                            raise ValueError, msg
                        value = prop_value
                    # Set the property
                    c_inner_properties[prop_name] = value

        ###################################################################
        # Index components
        for uid in self.components:
            component = self.components[uid]
            self.catalog.index_document(component)
Esempio n. 25
0
    def load_state_from_ical_file(self, file):
        """Load state from the given ical file.
        """
        self.reset()
        self.set_changed()

        components = {}

        # Read the data
        data = file.read()

        # Parse
        lines = []
        for name, value, parameters in parse_table(data):
            # Timestamp (ts), Schema, or Something else
            datatype = self.get_record_datatype(name)
            value = datatype.decode(value)
            property = Property(value, **parameters)
            # Append
            lines.append((name, property))

        # Read first line
        first = lines[0]
        if (first[0] != 'BEGIN' or first[1].value != 'VCALENDAR'
                or len(first[1].parameters) != 0):
            raise ValueError, 'icalendar must begin with BEGIN:VCALENDAR'

        lines = lines[1:]

        ###################################################################
        # Skip properties
        # TODO Currently tables are not able to handler global properties,
        # we must implement this feature to be able to load from ical files.
        n_line = 0
        for name, value in lines:
            if name == 'BEGIN':
                break
            elif name == 'END':
                break
            n_line += 1

        lines = lines[n_line:]

        ###################################################################
        # Read components
        c_type = None
        c_inner_type = None
        uid = None
        records = self.records
        record_properties = self.record_properties
        id = 0
        uids = {}

        for prop_name, prop_value in lines[:-1]:
            if prop_name in ('PRODID', 'VERSION'):
                raise ValueError, 'PRODID and VERSION must appear before '\
                                  'any component'
            if prop_name == 'BEGIN':
                if c_type is None:
                    c_type = prop_value.value
                    c_properties = {}
                    c_inner_components = []
                else:
                    # Inner component like DAYLIGHT or STANDARD
                    c_inner_type = prop_value.value
                    c_inner_properties = {}
                continue

            if prop_name == 'END':
                value = prop_value.value
                if value == c_type:
                    if uid is None:
                        raise ValueError, 'UID is not present'

                    record = self.get_record(id) or Record(
                        id, record_properties)
                    c_properties['type'] = Property(c_type)
                    c_properties['UID'] = Property(uid)
                    sequence = c_properties.get('SEQUENCE', None)
                    c_properties['SEQUENCE'] = sequence or Property(0)
                    c_properties['ts'] = Property(datetime.now())
                    # Add ids of inner components
                    if c_inner_components:
                        c_inner_components = [
                            Property(x) for x in c_inner_components
                        ]
                        c_properties['inner'] = c_inner_components
                    record.append(c_properties)
                    if uid in uids:
                        n = uids[uid] + 1
                        uids[uid] = n
                    else:
                        n = 0
                        uids[uid] = 0
                    self.added_records.append((id, n))
                    records.append(record)

                    # Next
                    c_type = None
                    uid = None
                    if n == 0:
                        id = id + 1

                # Inner component
                elif value == c_inner_type:
                    record = self.get_record(id) or Record(
                        id, record_properties)
                    c_inner_properties['type'] = Property(c_inner_type)
                    sequence = c_inner_properties.get('SEQUENCE', None)
                    c_inner_properties['SEQUENCE'] = sequence or Property(0)
                    c_inner_properties['ts'] = Property(datetime.now())
                    record.append(c_inner_properties)
                    c_inner_components.append(id)
                    self.added_records.append((id, 0))
                    records.append(record)
                    # Next
                    c_inner_type = None
                    id = id + 1
                else:
                    raise ValueError, 'Component %s found, %s expected' \
                                      % (value, c_inner_type)
            else:
                datatype = self.get_record_datatype(prop_name)
                if c_inner_type is None:
                    if prop_name in ('UID', 'TZID'):
                        uid = prop_value.value
                    else:
                        if getattr(datatype, 'multiple', False) is True:
                            value = c_properties.setdefault(prop_name, [])
                            value.append(prop_value)
                        else:
                            # Check the property has not yet being found
                            if prop_name in c_properties:
                                raise ValueError, \
                                    "property '%s' can occur only once" % name
                            # Set the property
                            c_properties[prop_name] = prop_value
                else:
                    # Inner component properties
                    if getattr(datatype, 'multiple', False) is True:
                        value = c_inner_properties.setdefault(prop_name, [])
                        value.append(prop_value)
                    else:
                        # Check the property has not yet being found
                        if prop_name in c_inner_properties:
                            msg = ('the property %s can be assigned only one'
                                   ' value' % prop_name)
                            raise ValueError, msg
                        # Set the property
                        c_inner_properties[prop_name] = prop_value

        # Index the records
        for record in records:
            if record is not None:
                self.catalog.index_document(record)
Esempio n. 26
0
    def _load_state_from_file(self, file):
        properties = self.properties
        data = file.read()
        parser = parse_table(data)

        # Read the format & version
        name, value, parameters = parser.next()
        if name != 'format':
            raise ValueError, 'unexpected "%s" property' % name
        if 'version' in parameters:
            version = parameters.pop('version')
            if len(version) > 1:
                raise ValueError, 'version parameter cannot be repeated'
            self.version = version[0]
        if parameters:
            raise ValueError, 'unexpected parameters for the format property'
        self.format = value
        # Get the schema
        resource_class = self.database.get_resource_class(value)

        # Parse
        for name, value, parameters in parser:
            if name == 'format':
                raise ValueError, 'unexpected "format" property'

            # 1. Get the field
            field = resource_class.get_field(name)
            if field is None:
                msg = 'unexpected field "%s"' % name
                if resource_class.fields_soft:
                    log_warning(msg, domain='itools.database')
                    field = DefaultField
                else:
                    raise ValueError, msg

            # 2. Deserialize the parameters
            params_schema = field.parameters_schema
            params_default = field.parameters_schema_default
            try:
                deserialize_parameters(parameters, params_schema,
                                       params_default)
            except ValueError, e:
                msg = 'in class "{0}" property "{1}": {2}'
                raise ValueError, msg.format(resource_class, name, e)

            # 3. Get the datatype properties
            if field.multiple and field.multilingual:
                error = 'property "%s" is both multilingual and multiple'
                raise ValueError, error % name

            # 4. Build the property
            datatype = field.datatype
            value = datatype.decode(value)
            property = Property(value, **parameters)

            # Case 1: Multilingual
            if field.multilingual:
                language = parameters.get('lang')
                if language is None:
                    err = 'multilingual property "%s" is missing the language'
                    raise ValueError, err % name
                properties.setdefault(name, {})[language] = property
            # Case 2: multiple
            elif field.multiple:
                properties.setdefault(name, []).append(property)
            # Case 3: simple
            else:
                properties[name] = property
Esempio n. 27
0
    def _load_state_from_file(self, file):
        # Read the data and figure out the encoding
        data = file.read()
        encoding = guess_encoding(data)
        self.encoding = encoding

        # Parse
        lines = []
        for name, value, parameters in parse_table(data):
            # Deserialize
            datatype = self.get_record_datatype(name)
            if isinstance(datatype, Unicode):
                value = datatype.decode(value, encoding=encoding)
            else:
                value = datatype.decode(value)
            # Build the value (a Property instance)
            deserialize_parameters(parameters, self.record_parameters)
            value = Property(value, **parameters)
            # Append
            lines.append((name, value))

        # Read first line
        first = lines[0]
        if (first[0] != 'BEGIN' or first[1].value != 'VCALENDAR'
                or len(first[1].parameters) != 0):
            raise ValueError, 'icalendar must begin with BEGIN:VCALENDAR'

        lines = lines[1:]

        ###################################################################
        # Read properties
        n_line = 0
        for name, value in lines:
            if name == 'BEGIN':
                break
            elif name == 'END':
                break
            elif name == 'VERSION':
                if 'VERSION' in self.properties:
                    raise ValueError, 'VERSION can appear only one time'
            elif name == 'PRODID':
                if 'PRODID' in self.properties:
                    raise ValueError, 'PRODID can appear only one time'
            # Add the property
            self.properties[name] = value
            n_line += 1

        # The properties VERSION and PRODID are mandatory
        if ('VERSION' not in self.properties
                or 'PRODID' not in self.properties):
            raise ValueError, 'PRODID or VERSION parameter missing'

        lines = lines[n_line:]

        ###################################################################
        # Read components
        c_type = None
        c_inner_type = None
        uid = None

        for prop_name, prop_value in lines[:-1]:
            if prop_name in ('PRODID', 'VERSION'):
                raise ValueError, 'PRODID and VERSION must appear before '\
                                  'any component'
            if prop_name == 'BEGIN':
                if c_type is None:
                    c_type = prop_value.value
                    c_properties = {}
                    c_inner_components = []
                else:
                    # Inner component like DAYLIGHT or STANDARD
                    c_inner_type = prop_value.value
                    c_inner_properties = {}
                continue

            if prop_name == 'END':
                value = prop_value.value
                if value == c_type:
                    if uid is None:
                        raise ValueError, 'UID is not present'

                    if uid in self.components:
                        component = self.components[uid]
                        component.add_version(c_properties)
                    else:
                        component = Component(c_type, uid)
                        component.add_version(c_properties)
                        component.c_inner_components = c_inner_components
                        self.components[uid] = component
                    # Next
                    c_type = None
                    uid = None
                # Inner component
                elif value == c_inner_type:
                    inner_component = InnerComponent(c_inner_type)
                    inner_component.add_version(c_inner_properties)
                    c_inner_components.append(inner_component)
                    c_inner_type = None
                else:
                    raise ValueError, 'Component %s found, %s expected' \
                                      % (value, c_inner_type)
            else:
                datatype = self.get_record_datatype(prop_name)
                if c_inner_type is None:
                    if prop_name in ('UID', 'TZID'):
                        uid = prop_value.value
                    else:
                        if getattr(datatype, 'multiple', False) is True:
                            value = c_properties.setdefault(prop_name, [])
                            value.append(prop_value)
                        else:
                            # Check the property has not yet being found
                            if prop_name in c_properties:
                                msg = ('the property %s can be assigned only '
                                       'one value' % prop_name)
                                raise ValueError, msg
                            # Set the property
                            c_properties[prop_name] = prop_value
                else:
                    # Inner component properties
                    if getattr(datatype, 'multiple', False) is True:
                        value = c_inner_properties.setdefault(prop_name, [])
                        value.append(prop_value)
                    else:
                        # Check the property has not yet being found
                        if prop_name in c_inner_properties:
                            msg = ('the property %s can be assigned only one'
                                   ' value' % prop_name)
                            raise ValueError, msg
                        value = prop_value
                    # Set the property
                    c_inner_properties[prop_name] = value

        ###################################################################
        # Index components
        for uid in self.components:
            component = self.components[uid]
            self.catalog.index_document(component)