[pkg-fso-commits] [SCM] FSO frameworkd Debian packaging branch, debian, updated. upstream/0.9.5.5-717-g0f98819

Sebastian Krzyszkowiak seba.dos1 at gmail.com
Sat Aug 6 08:17:44 UTC 2011


The following commit has been merged in the debian branch:
commit cc1ea05aaae9b1866cdd27b9d2149b17efdeabd1
Merge: d1a6e562781fc6a306ba459c37fc5f6f24601612 e96a204768744130859ab091162ec5c976854d49
Author: Sebastian Krzyszkowiak <seba.dos1 at gmail.com>
Date:   Fri Aug 7 22:52:48 2009 +0200

    Merge branch 'master' of git at git.freesmartphone.org:framework into dos/opimd-tracking
    
    Conflicts:
    	framework/subsystems/opimd/pimd_contacts.py

diff --combined framework/subsystems/opimd/pimd_generic.py
index ac515ed,cf067af..dd8fc75
--- a/framework/subsystems/opimd/pimd_generic.py
+++ b/framework/subsystems/opimd/pimd_generic.py
@@@ -3,21 -3,17 +3,21 @@@
  """
  Open PIM Daemon
  
 -(C) 2008 by Soeren Apel <abraxa at dar-clan.de>
 +(C) 2008 Soeren Apel <abraxa at dar-clan.de>
  (C) 2008 Openmoko, Inc.
  (C) 2009 Michael 'Mickey' Lauer <mlauer at vanille-media.de>
  (C) 2009 Sebastian Krzyszkowiak <seba.dos1 at gmail.com>
  GPLv2 or later
  
 -Contacts Domain Plugin
 +Generic Domain
  
 -Establishes the 'contacts' PIM domain and handles all related requests
 +From this domain class others inherit.
  """
  
 +DBUS_BUS_NAME_FSO = "org.freesmartphone.opimd"
 +DBUS_PATH_BASE_FSO = "/org/freesmartphone/PIM"
 +DIN_BASE_FSO = "org.freesmartphone.PIM"
 +
  from dbus.service import FallbackObject as DBusFBObject
  from dbus.service import signal as dbus_signal
  from dbus.service import method as dbus_method
@@@ -27,51 -23,104 +27,51 @@@ import r
  import logging
  logger = logging.getLogger('opimd')
  
 +from query_manager import QueryMatcher
 +
  from backend_manager import BackendManager
  from backend_manager import PIMB_CAN_ADD_ENTRY, PIMB_CAN_DEL_ENTRY, PIMB_CAN_UPD_ENTRY, PIMB_CAN_UPD_ENTRY_WITH_NEW_FIELD, PIMB_NEEDS_SYNC
  
 -from domain_manager import DomainManager, Domain
 +from domain_manager import Domain
  from helpers import *
 -from opimd import *
  
  from framework.config import config, busmap
  
  #----------------------------------------------------------------------------#
  
 -_DOMAIN_NAME = "Contacts"
 -
 -_DBUS_PATH_CONTACTS = DBUS_PATH_BASE_FSO + '/' + _DOMAIN_NAME
 -_DIN_CONTACTS_BASE = DIN_BASE_FSO
 -
 -_DBUS_PATH_QUERIES = _DBUS_PATH_CONTACTS + '/Queries'
 -
 -_DIN_CONTACTS = _DIN_CONTACTS_BASE + '.' + 'Contacts'
 -_DIN_ENTRY = _DIN_CONTACTS_BASE + '.' + 'Contact'
 -_DIN_QUERY = _DIN_CONTACTS_BASE + '.' + 'ContactQuery'
 -
 -#----------------------------------------------------------------------------#
 -class ContactQueryMatcher(object):
 -#----------------------------------------------------------------------------#
 -    query_obj = None
 -
 -    def __init__(self, query):
 -        """Evaluates a query
 -
 -        @param query Query to evaluate, must be a dict"""
 -
 -        self.query_obj = query
 -
 -    def single_contact_matches(self, contact):
 -        assert(self.query_obj, "Query object is empty, cannot match!")
 -
 -        if contact:
 -            return contact.match_query(self.query_obj)
 -        else:
 -            return False
 -
 -    def match(self, contacts):
 -        """Tries to match a given set of contacts to the current query
 +#_DOMAIN_NAME = "Generic"
  
 -        @param contacts List of Contact objects
 -        @return List of contact IDs that match"""
 +#_DBUS_PATH_DOMAIN = DBUS_PATH_BASE_FSO + '/' + _DOMAIN_NAME
 +_DIN_DOMAIN_BASE = DIN_BASE_FSO
  
 -        assert(self.query_obj, "Query object is empty, cannot match!")
 -
 -        matches = []
 -        results = []
 -
 -        # Match all contacts
 -        for (contact_id, contact) in enumerate(contacts):
 -            match = self.single_contact_matches(contact)
 -            if match:
 -                matches.append((match, contact_id))
 -
 -        result_count = len(matches)
 -        # Sort matches by relevance and return the best hits
 -        if result_count > 0:
 -            matches.sort(reverse = True)
 -
 -            limit = result_count
 -            if self.query_obj.has_key("_limit"):
 -                limit = self.query_obj["_limit"]
 -                if limit > result_count:
 -                    limit = result_count
 -
 -            # Append the contact IDs to the result list in the order of the sorted list
 -            for i in range(limit):
 -                results.append(matches[i][1])
 -
 -        return results
 +#_DBUS_PATH_QUERIES = _DBUS_PATH_DOMAIN + '/Queries'
  
 +_DIN_ENTRIES = _DIN_DOMAIN_BASE + '.' + 'Entries'
 +_DIN_ENTRY = _DIN_DOMAIN_BASE + '.' + 'Entry'
 +_DIN_QUERY = _DIN_DOMAIN_BASE + '.' + 'EntryQuery'
  
  
  #----------------------------------------------------------------------------#
 -class Contact():
 +class GenericEntry(object):
  #----------------------------------------------------------------------------#
 -    """Represents one single contact with all the data fields it consists of.
 +    """Represents one single entry with all the data fields it consists of.
  
      _fields[n] = [field_name, field_value, value_used_for_comparison, source]
  
      Best way to explain the usage of _fields and _field_idx is by example:
      _fields[3] = ["EMail", "foo at bar.com", "", "CSV-Contacts"]
 -    _fields[4] = ["EMail", "moo at cow.com", "", "LDAP-Contacts"]
 +    _fields[4] = ["EMail", "moo at cow.com", "", "SQLite-Contacts"]
      _field_idx["EMail"] = [3, 4]"""
  
      _fields = None
      _field_idx = None
      _used_backends = None
 +    domain_name = 'Generic'
  
      def __init__(self, path):
 -        """Creates a new Contact instance
 +        """Creates a new entry instance
  
 -        @param path Path of the contact itself"""
 +        @param path Path of the entry itself"""
  
          self._fields = []
          self._field_idx = {}
@@@ -135,28 -184,28 +135,28 @@@
                  self._field_idx[field_name] = [field_idx]
  
  
 -    def import_fields(self, contact_data, backend_name):
 -        """Adds an array of contact data fields to this contact
 +    def import_fields(self, entry_data, backend_name):
 +        """Adds an array of entry data fields to this entry
  
 -        @param contact_data Contact data; format: ((Key,Value), (Key,Value), ...)
 +        @param entry_data entry data; format: {Key:Value, Key:Value, ...}
          @param backend_name Name of the backend to which those fields belong"""
  
          if backend_name!='':
              if not backend_name in self._used_backends:
                  self._used_backends.append(backend_name)
  
 -        for field_name in contact_data:
 +        for field_name in entry_data:
              try:
                  if field_name.startswith('_'):
                      raise KeyError
                  for field in self._field_idx[field_name]:
                      if self._fields[field][3]==backend_name:
 -                        self._fields[field][1]=contact_data[field_name]
 +                        self._fields[field][1]=entry_data[field_name]
                      else:
 -                        self._fields.append([field_name, contact_data[field_name], '', backend_name])
 +                        self._fields.append([field_name, entry_data[field_name], '', backend_name])
                          self._field_idx[field_name].append(len(self._fields)-1)
              except KeyError:
 -                field_value = contact_data[field_name]
 +                field_value = entry_data[field_name]
  
                  # We only generate compare values for specific fields
                  compare_value = ""
@@@ -238,11 -287,11 +238,11 @@@
  
  
      def get_content(self):
 -        """Creates and returns a complete representation of the contact
 +        """Creates and returns a complete representation of the entry
          @note Backend information is omitted.
          @note Fields that have more than one occurence are concatenated using a separation character of ','.
  
 -        @return Contact data, in {Field_name:Field_value} notation"""
 +        @return entry data, in {Field_name:Field_value} notation"""
  
          fields = self.get_fields(self._field_idx)
          content = {}
@@@ -251,17 -300,18 +251,17 @@@
                  content[field] = fields[field]
          return content
  
 +    def attempt_merge(self, entry_fields, backend_name):
 +        """Attempts to merge the given entry into the entry list and returns its ID
  
 -    def attempt_merge(self, contact_fields, backend_name):
 -        """Attempts to merge the given contact into the contact list and returns its ID
 -
 -        @param contact_fields Contact data; format: ((Key,Value), (Key,Value), ...)
 -        @param backend_name Backend that owns the contact data
 +        @param entry_fields entry data; format: {Key:Value, Key:Value, ...}
 +        @param backend_name Backend that owns the entry data
          @return True on successful merge, False otherwise"""
  
          duplicated = True
 -        for field_name in contact_fields:
 +        for field_name in entry_fields:
              try:
 -                if self[field_name]!=contact_fields[field_name]:
 +                if self[field_name]!=entry_fields[field_name]:
                      duplicated = False
                      break
              except KeyError:
@@@ -269,17 -319,17 +269,17 @@@
                  break
  
          if duplicated:
 -            return True # That contacts exists, so we doesn't have to do anything to have it merged.
 +            return True # That entry exists, so we doesn't have to do anything to have it merged.
  
 -        # Don't merge if we already have data from $backend_name as one backend can't contain two mergeable contacts
 +        # Don't merge if we already have data from $backend_name as one backend can't contain two mergeable entries
          if backend_name in self._used_backends:
              return False
  
          merge = [1, 0]
 -        for field_name in contact_fields:
 +        for field_name in entry_fields:
              if not field_name.startswith('_'):
                  if field_name!='Path':
 -                    field_value=contact_fields[field_name]
 +                    field_value=entry_fields[field_name]
                      try:
                          if self[field_name]!=field_value:
                              merge[0] = 0
@@@ -291,7 -341,7 +291,7 @@@
  
          if merge[0]:
              if merge[1]:
 -                self.import_fields(contact_fields, backend_name)
 +                self.import_fields(entry_fields, backend_name)
                  return True
              else:
                  return False
@@@ -300,7 -350,7 +300,7 @@@
  
  
      def incorporates_data_from(self, backend_name):
 -        """Determines whether this contact entry has data from a specific backend saved
 +        """Determines whether this entry has data from a specific backend saved
  
          @param backend_name Name of backend to look for
          @return True if we have data belonging to that backend, False otherwise"""
@@@ -309,7 -359,7 +309,7 @@@
  
  
      def match_query(self, query_obj):
 -        """Checks whether this contact matches the given query
 +        """Checks whether this entry matches the given query
  
          @param query_obj Dict containing key/value pairs of the required matches
          @return Accuracy of the match, ranging from 0.0 (no match) to 1.0 (complete match)"""
@@@ -324,9 -374,8 +324,8 @@@
              best_field_match = 0.0
  
              matcher = re.compile(field_value)
-             seq2_len = len(field_value)
  
 -            # Check if field value(s) of this contact match(es) the query field
 +            # Check if field value(s) of this entry match(es) the query field
              try:
                  field_ids = self._field_idx[field_name]
  
@@@ -345,16 -394,16 +344,16 @@@
                      else:
                          match_len = 0
  
-                     if seq2_len==0:
-                         field_match = 0.0
-                     else:
+                     if field_value and comp_value:
                          field_match = float(match_len) / len(comp_value)
+                     else:
+                         field_match = 0.0
  
                      if field_match > best_field_match: best_field_match = field_match
 -                    logger.debug("Contacts: Field match for %s / %s: %f", comp_value, field_value, field_match)
 +                    logger.debug("%s: Field match for %s / %s: %f", self.domain_name, comp_value, field_value, field_match)
  
              except KeyError:
 -                # Contact has no data for this field contained in the query, so this entry cannot match
 +                # entry has no data for this field contained in the query, so this entry cannot match
                  return 0.0
  
              # Aggregate the field match value into the overall match
@@@ -367,33 -416,213 +366,33 @@@
  
          return overall_match
  
 -
 -
 -#----------------------------------------------------------------------------#
 -class SingleQueryHandler(object):
 -#----------------------------------------------------------------------------#
 -    _contacts = None
 -    query = None      # The query this handler is processing
 -    entries = None
 -    cursors = None    # The next entry we'll serve, depending on the client calling us
 -
 -    def __init__(self, query, contacts, dbus_sender):
 -        """Creates a new SingleQueryHandler instance
 -
 -        @param query Query to evaluate
 -        @param contacts Set of Contact objects to use
 -        @param dbus_sender Sender's unique name on the bus"""
 -
 -        self.query = query
 -        self.sanitize_query()
 -
 -        matcher = ContactQueryMatcher(self.query)
 -
 -        self._contacts = contacts
 -        self.entries = matcher.match(self._contacts)
 -        self.cursors = {}
 -
 -        # TODO Register with all contacts to receive updates
 -
 -
 -    def dispose(self):
 -        """Unregisters from all contact entries to allow this instance to be eaten by GC"""
 -        # TODO Unregister from all contacts
 -        pass
 -
 -
 -    def sanitize_query(self):
 -        """Makes sure the query meets the criteria that related code uses to omit wasteful sanity checks"""
 -
 -        # For get_result_and_advance():
 -        # Make sure the _result_fields list has no whitespaces, e.g. "a, b, c" should be "a,b,c"
 -        # Reasoning: Contact.get_fields() has no fuzzy matching for performance reasons
 -        # Also, we remove any empty list elements created by e.g. "a, b, c,"
 -        try:
 -            field_list = self.query['_result_fields']
 -            fields = field_list.split(',')
 -            new_field_list = []
 -
 -            for field_name in fields:
 -                field_name = field_name.strip()
 -                if field_name: new_field_list.append(field_name)
 -
 -            self.query['_result_fields'] = ','.join(new_field_list)
 -        except KeyError:
 -            # There's no _result_fields entry to sanitize
 -            pass
 -
 -
 -    def get_result_count(self):
 -        """Determines the number of results for this query
 -
 -        @return Number of result entries"""
 -
 -        return len(self.entries)
 -
 -
 -    def rewind(self, dbus_sender):
 -        """Resets the cursor for a given d-bus sender to the first result entry
 -
 -        @param dbus_sender Sender's unique name on the bus"""
 -
 -        self.cursors[dbus_sender] = 0
 -
 -
 -    def skip(self, dbus_sender, num_entries):
 -        """Skips n result entries of the result set
 -
 -        @param dbus_sender Sender's unique name on the bus
 -        @param num_entries Number of result entries to skip"""
 -
 -        if not self.cursors.has_key(dbus_sender): self.cursors[dbus_sender] = 0
 -        self.cursors[dbus_sender] += num_entries
 -
 -
 -    def get_contact_path(self, dbus_sender):
 -        """Determines the Path of the next contact that the cursor points at and advances to the next result entry
 -
 -        @param dbus_sender Sender's unique name on the bus
 -        @return Path of the contact"""
 -
 -        # If the sender is not in the list of cursors it just means that it is starting to iterate
 -        if not self.cursors.has_key(dbus_sender): self.cursors[dbus_sender] = 0
 -
 -        # Check whether we've reached the end of the entry list
 -        try:
 -            result = self.entries[self.cursors[dbus_sender]]
 -        except IndexError:
 -            raise NoMoreContacts( "All results have been submitted" )
 -
 -        contact_id = self.entries[self.cursors[dbus_sender]]
 -        contact = self._contacts[contact_id]
 -        self.cursors[dbus_sender] += 1
 -
 -        return contact['Path']
 -
 -
 -    def get_result(self, dbus_sender):
 -        """Extracts the requested fields from the next contact entry in the result set and advances the cursor
 -
 -        @param dbus_sender Sender's unique name on the bus
 -        @return Dict containing field_name/field_value pairs"""
 -
 -        # If the sender is not in the list of cursors it just means that it is starting to iterate
 -        if not self.cursors.has_key(dbus_sender): self.cursors[dbus_sender] = 0
 -
 -        # Check whether we've reached the end of the entry list
 -        try:
 -            result = self.entries[self.cursors[dbus_sender]]
 -        except IndexError:
 -            raise NoMoreContacts( "All results have been submitted" )
 -
 -        contact_id = self.entries[self.cursors[dbus_sender]]
 -        contact = self._contacts[contact_id]
 -        self.cursors[dbus_sender] += 1
 -
 -        try:
 -            fields = self.query['_result_fields']
 -            field_list = fields.split(',')
 -            result = contact.get_fields(field_list)
 -        except KeyError:
 -            result = contact.get_content()
 -
 -        return result
 -
 -
 -    def get_multiple_results(self, dbus_sender, num_entries):
 -        """Creates a list containing n dicts which represent the corresponding entries from the result set
 -        @note If there are less entries than num_entries, only the available entries will be returned
 -
 -        @param dbus_sender Sender's unique name on the bus
 -        @param num_entries Number of result set entries to return
 -        @return List of dicts with field_name/field_value pairs"""
 -
 -        result = []
 -
 -        for i in range(num_entries):
 -            try:
 -                entry = self.get_result(dbus_sender)
 -                result.append(entry)
 -            except NoMoreContacts:
 -                """Don't want to raise an error in that case"""
 -                break
 -
 -        return result
 -
 -
 -    def check_new_contact(self, contact_id):
 -        """Checks whether a newly added contact matches this so it can signal clients
 -
 -        @param contact_id Contact ID of the contact that was added
 -        @return True if contact matches this query, False otherwise
 -
 -        @todo Currently this messes up the order of the result set if a specific order was desired"""
 -
 -        result = False
 -
 -        matcher = ContactQueryMatcher(self.query)
 -        if matcher.single_contact_matches(self._contacts[contact_id]):
 -            self.entries = matcher.match(self._contacts)
 -
 -            # TODO Register with the new contact to receive changes
 -
 -            # We *should* reset all cursors *if* the result set is ordered, however
 -            # in order to prevent confusion, this is left for the client to do.
 -            # Rationale: clients with unordered queries can just use get_result()
 -            # and be done with it. For those, theres's no need to re-read all results.
 -
 -            # Let clients know that this result set changed
 -            result = True
 -
 -        return result
 -
 -
 -
  #----------------------------------------------------------------------------#
  class QueryManager(DBusFBObject):
  #----------------------------------------------------------------------------#
      _queries = None
 -    _contacts = None
 +    _entries = None
      _next_query_id = None
 +    domain_name = None
  
      # Note: _queries must be a dict so we can remove queries without messing up query IDs
  
 -    def __init__(self, contacts):
 +    def __init__(self, entries, domain_name):
          """Creates a new QueryManager instance
  
 -        @param contacts Set of Contact objects to use"""
 +        @param entries Set of entry objects to use"""
  
 -        self._contacts = contacts
 +        self._entries = entries
          self._queries = {}
          self._next_query_id = 0
  
 +        self.domain_name = domain_name
 +
          # Initialize the D-Bus-Interface
 -        DBusFBObject.__init__( self, conn=busmap["opimd"], object_path=_DBUS_PATH_QUERIES )
 +        DBusFBObject.__init__( self, conn=busmap["opimd"], object_path=DBUS_PATH_BASE_FSO + '/' + self.domain_name + '/Queries' )
  
          # Still necessary?
 -        self.interface = _DIN_CONTACTS
 -        self.path = _DBUS_PATH_QUERIES
 +        #self.interface = _DIN_ENTRIES
 +        #self.path = DBUS_PATH_BASE_FSO + '/' + self.domain_name + '/Queries'
  
  
      def process_query(self, query, dbus_sender):
@@@ -403,26 -632,26 +402,26 @@@
          @param dbus_sender Sender's unique name on the bus
          @return dbus path of the query result"""
  
 -        query_handler = SingleQueryHandler(query, self._contacts, dbus_sender)
 +        query_handler = SingleQueryHandler(query, self._entries, dbus_sender)
  
          query_id = self._next_query_id
          self._next_query_id += 1
  
          self._queries[query_id] = query_handler
  
 -        return _DBUS_PATH_QUERIES + '/' + str(query_id)
 +        return DBUS_PATH_BASE_FSO + '/' + self.domain_name + '/Queries/' + str(query_id)
  
  
 -    def check_new_contact(self, contact_id):
 -        """Checks whether a newly added contact matches one or more queries so they can signal clients
 +    def check_new_entry(self, entry_id):
 +        """Checks whether a newly added entry matches one or more queries so they can signal clients
  
 -        @param contact_id Contact ID of the contact that was added"""
 +        @param entry_id entry ID of the entry that was added"""
  
          for (query_id, query_handler) in self._queries.items():
 -            if query_handler.check_new_contact(contact_id):
 -                contact = self._contacts[contact_id]
 -                contact_path = contact['Path']
 -                self.ContactAdded(contact_path, rel_path='/' + str(query_id))
 +            if query_handler.check_new_entry(entry_id):
 +                entry = self._entries[entry_id]
 +                entry_path = entry['Path']
 +                self.EntryAdded(entry_path, rel_path='/' + str(query_id))
  
      def check_query_id_ok( self, num_id ):
          """
@@@ -431,8 -660,8 +430,8 @@@
          if not num_id in self._queries:
              raise InvalidQueryID( "Existing query IDs: %s" % self._queries.keys() )
  
 -    @dbus_signal(_DIN_QUERY, "s", rel_path_keyword="rel_path")
 -    def ContactAdded(self, path, rel_path=None):
 +    @dbus_signal(_DIN_QUERY, "o", rel_path_keyword="rel_path")
 +    def EntryAdded(self, path, rel_path=None):
          pass
  
      @dbus_method(_DIN_QUERY, "", "i", rel_path_keyword="rel_path")
@@@ -459,12 -688,12 +458,12 @@@
          self._queries[num_id].skip(sender, num_entries)
  
  
 -    @dbus_method(_DIN_QUERY, "", "s", rel_path_keyword="rel_path", sender_keyword="sender")
 -    def GetContactPath(self, rel_path, sender):
 +    @dbus_method(_DIN_QUERY, "", "o", rel_path_keyword="rel_path", sender_keyword="sender")
 +    def GetEntryPath(self, rel_path, sender):
          num_id = int(rel_path[1:])
          self.check_query_id_ok( num_id )
  
 -        return self._queries[num_id].get_contact_path(sender)
 +        return self._queries[num_id].get_entry_path(sender)
  
  
      @dbus_method(_DIN_QUERY, "", "a{sv}", rel_path_keyword="rel_path", sender_keyword="sender")
@@@ -494,29 -723,27 +493,29 @@@
          self._queries.__delitem__(num_id)
  
  #----------------------------------------------------------------------------#
 -class ContactDomain(Domain):
 +class GenericDomain():
  #----------------------------------------------------------------------------#
 -    name = _DOMAIN_NAME
 +    name = 'Generic'
  
 +    #_dbus_path = _DBUS_PATH_DOMAIN
      _backends = None
 -    _contacts = None
 +    _entries = None
      query_manager = None
 +    Entry = GenericEntry
  
      def __init__(self):
 -        """Creates a new ContactDomain instance"""
 +        """Creates a new GenericDomain instance"""
  
          self._backends = {}
 -        self._contacts = []
 -        self.query_manager = QueryManager(self._contacts)
 +        self._entries = []
 +        self.query_manager = QueryManager(self._entries)
  
          # Initialize the D-Bus-Interface
 -        super(ContactDomain, self).__init__( conn=busmap["opimd"], object_path=_DBUS_PATH_CONTACTS )
 +        super(GenericDomain, self).__init__( conn=busmap["opimd"], object_path=DBUS_PATH_BASE_FSO + '/' + self.name )
  
 -        # Keep frameworkd happy, pyneo won't care
 -        self.interface = _DIN_CONTACTS
 -        self.path = _DBUS_PATH_CONTACTS
 +        # Keep frameworkd happy
 +        self.interface = _DIN_ENTRIES
 +        self.path = _DBUS_PATH_ENTRIES
  
  
      def get_dbus_objects(self):
@@@ -535,195 -762,106 +534,195 @@@
          self._backends[backend.name] = backend
  
  
 -    def register_contact(self, backend, contact_data):
 -        """Merges/inserts the given contact into the contact list and returns its ID
 +    def register_entry(self, backend, entry_data):
 +        """Merges/inserts the given entry into the entry list and returns its ID
  
          @param backend Backend objects that requests the registration
 -        @param contact_data Contact data; format: [Key:Value, Key:Value, ...]"""
 +        @param entry_data entry data; format: {Key:Value, Key:Value, ...}"""
  
 -        contact_id = -1
 +        entry_id = -1
          merged = 0
  
 -        # Check if the contact can be merged with one we already know of
 -        if int(config.getValue('opimd', 'contacts_merging_enabled', default='1')):
 -            for entry in self._contacts:
 +        # Check if the entry can be merged with one we already know of
 +        if int(config.getValue('opimd', name.lower()+'_merging_enabled', default='1')):
 +            for entry in self._entries:
                  if entry:
 -                    if entry.attempt_merge(contact_data, backend.name):
 +                    if entry.attempt_merge(entry_data, backend.name):
  
                          # Find that entry's ID
 -                        for (contact_idx, contact) in enumerate(self._contacts):
 -                            if contact == entry: contact_id = contact_idx
 +                        for (entry_idx, ent) in enumerate(self._entries):
 +                            if ent == entry: entry_id = entry_idx
                              break
  
                          # Stop trying to merge
                          merged = 1
                          break
          if not merged:
 -            # Merging failed, so create a new contact entry and append it to the list
 -            contact_id = len(self._contacts)
 -
 -            path = _DBUS_PATH_CONTACTS+ '/' + str(contact_id)
 -            contact = Contact(path)
 -            contact.import_fields(contact_data, backend.name)
 +            # Merging failed, so create a new entry and append it to the list
 +            entry_id = len(self._entries)
  
 -            self._contacts.append(contact)
 +            path = self._dbus_path+ '/' + str(entry_id)
 +            entry = Entry(path)
 +            entry.import_fields(entry_data, backend.name)
  
 -            self.NewContact(path)
 +            self._entries.append(entry)
  
 -        return contact_id
 +            self.NewEntry(path)
  
 +        return entry_id
  
      def enumerate_items(self, backend):
 -        """Enumerates all contact data belonging to a specific backend
 -
 -        @param backend Backend object whose contacts should be enumerated
 -        @return Lists of (field_name,field_value) tuples of all contacts that have data from this particular backend"""
 -
 -        for contact in self._contacts:
 -            if contact:
 -                if contact.incorporates_data_from(backend.name):
 -                    yield contact.export_fields(backend.name)
 +        """Enumerates all entry data belonging to a specific backend
  
 +        @param backend Backend object whose entries should be enumerated
 +        @return Lists of (field_name,field_value) tuples of all entries that have data from this particular backend"""
  
 -    @dbus_signal(_DIN_CONTACTS, "s")
 -    def NewContact(self, path):
 -        pass
 -
 -    @dbus_method(_DIN_CONTACTS, "a{sv}", "s")
 -    def Add(self, contact_data):
 -        """Adds a contact to the list, assigning it to the default backend and saving it
 +        for entry in self._entries:
 +            if entry:
 +                if entry.incorporates_data_from(backend.name):
 +                    yield entry.export_fields(backend.name)
  
 -        @param contact_data List of fields; format is [Key:Value, Key:Value, ...]
 -        @return Path of the newly created d-bus contact object"""
 +    def check_entry_id( self, num_id ):
 +        """
 +        Checks whether the given entry id is valid. Raises InvalidEntryID, if not.
 +        """
 +        if num_id >= len(self._entries) or self._entries[num_id]==None:
 +            raise InvalidEntryID()
  
 +    def add(self, entry_data):
          # We use the default backend for now
 -        backend = BackendManager.get_default_backend(_DOMAIN_NAME)
 +        backend = BackendManager.get_default_backend(self.name)
          result = ""
  
          if not PIMB_CAN_ADD_ENTRY in backend.properties:
              raise InvalidBackend( "Backend properties not including PIMB_CAN_ADD_ENTRY" )
  
          try:
 -            contact_id = backend.add_contact(contact_data)
 +            entry_id = backend.add_entry(entry_data)
          except AttributeError:
 -            raise InvalidBackend( "Backend does not feature add_contact" )
 +            raise InvalidBackend( "Backend does not feature add_entry" )
  
 -        contact = self._contacts[contact_id]
 -        result = contact['Path']
 +        entry = self._entries[entry_id]
 +        result = entry['Path']
  
 -        # As we just added a new contact, we check it against all queries to see if it matches
 -        self.query_manager.check_new_contact(contact_id)
 +        # As we just added a new entry, we check it against all queries to see if it matches
 +        self.query_manager.check_new_entry(entry_id)
  
          return result
  
 -    @dbus_method(_DIN_CONTACTS, "a{sv}s", "s")
 -    def GetSingleContactSingleField(self, query, field_name):
 -        """Returns the first contact found for a query, making it real easy to query simple things
 +    def update(self, num_id, data):
 +        # Make sure the requested entry exists
 +        self.check_entry_id(num_id)
  
 -        @param query The query object
 -        @param field_name The name of the field to return
 -        @return The requested data"""
 +        entryif = self._entries[num_id]
 +        entry = entryif.get_fields(entryif._field_idx)
 +
 +        default_backend = BackendManager.get_default_backend(self.name)
 +        
 +        # Search for backend in which we can store new fields
 +        backend = ''
 +        if default_backend.name in entryif._used_backends:
 +            backend = default_backend.name
 +        else:
 +            for backend_name in entryif._used_backends:
 +                if PIMB_CAN_UPD_ENTRY_WITH_NEW_FIELD in self._backends[backend_name].properties:
 +                    backend = self._backends[backend_name]
 +                    break
 +
 +        # TODO: implement adding new data to backend, which doesn't incorporate entry data
 +        # For instance: we have SIM contact with Name and Phone. We want to add "Birthday" field.
 +        # opimd should then try to add "Birthday" field to default backend and then merge contacts.
  
 +        for field_name in data:
 +            if not field_name in entryif._field_idx:
 +                if backend!='':
 +                    entryif.import_fields({field_name:data[field_name]}, backend)
 +                else:
 +                    raise InvalidBackend( "There is no backend which can store new field" )
 +            elif not field_name.startswith('_'):
 +                for field_nr in entryif._field_idx[field_name]:
 +                    if entry[field_name]!=data[field_name]:
 +                        entryif._fields[field_nr][1]=data[field_name]
 +
 +        for backend_name in entryif._used_backends:
 +            backend = self._backends[backend_name]
 +            if not PIMB_CAN_UPD_ENTRY in backend.properties:
 +                raise InvalidBackend( "Backend properties not including PIMB_CAN_UPD_ENTRY" )
 +            try:
 +                backend.upd_entry(entryif.export_fields(backend_name))
 +            except AttributeError:
 +                raise InvalidBackend( "Backend does not feature upd_entry" )
 +
 +            if PIMB_NEEDS_SYNC in backend.properties:
 +                backend.sync() # If backend needs - sync entries
 +
 +
 +        self.EntryUpdated(data, rel_path=rel_path)
 +
 +    def delete(self, num_id):
 +        # Make sure the requested entry exists
 +        self.check_entry_id(num_id)
 +
 +        backends = self._entries[num_id]._used_backends
 +
 +        for backend_name in backends:
 +            backend = self._backends[backend_name]
 +            if not PIMB_CAN_DEL_ENTRY in backend.properties:
 +                raise InvalidBackend( "Backend properties not including PIMB_CAN_DEL_ENTRY" )
 +
 +            try:
 +                backend.del_entry(self._entries[num_id].export_fields(backend_name))
 +            except AttributeError:
 +                raise InvalidBackend( "Backend does not feature del_entry" )
 +
 +        #del self._entries[num_id]
 +        # Experimental: it may introduce some bugs.
 +#        entry = self._entries[num_id]
 +        self._entries[num_id] = None
 +#        del entry
 +
 +        # update Path fields, as IDs may be changed - UGLYYYY!!! */me spanks himself*
 +        # Not needed with that "experimental" code above.
 +        #for id in range(0,len(self._entries)):
 +        #    path = _DBUS_PATH_ENTRIES+ '/' + str(id)
 +        #    for field in self._entries[id]._fields:
 +        #        if field[0]=='Path':
 +        #            field[1]=path
 +
 +        for backend_name in backends:
 +            backend = self._backends[backend_name]
 +            if PIMB_NEEDS_SYNC in backend.properties:
 +                backend.sync() # If backend needs - sync entries
 +
 +        self.EntryDeleted(rel_path=rel_path)
 +
 +    def get_multiple_fields(self, num_id, field_list):
 +        # Make sure the requested entry exists
 +        self.check_entry_id(num_id)
 +
 +        # Break the string up into a list
 +        fields = field_list.split(',')
 +        new_field_list = []
 +
 +        for field_name in fields:
 +            # Make sure the field list entries contain no spaces and aren't empty
 +            field_name = field_name.strip()
 +            if field_name: new_field_list.append(field_name)
 +
 +        return self._entries[num_id].get_fields(new_field_list)
 +
 +    def get_single_entry_single_field(self, query, field_name):
          result = ""
  
 -        # Only return one contact
 +        # Only return one entry
          query['_limit'] = 1
 -        matcher = ContactQueryMatcher(query)
 -        res = matcher.match(self._contacts)
 +        matcher = QueryMatcher(query)
 +        res = matcher.match(self._entries)
  
          # Copy all requested fields if we got a result
          if len(res) > 0:
 -            contact = self._contacts[res[0]]
 -            result = contact[field_name]
 +            entry = self._entries[res[0]]
 +            result = entry[field_name]
  
              # Merge results if we received multiple results
              if isinstance(result, list):
@@@ -731,40 -869,14 +730,40 @@@
  
          return result
  
 +    #---------------------------------------------------------------------#
 +    # dbus methods and signals starts here                                #
 +    #---------------------------------------------------------------------#
 +
 +    @dbus_signal(_DIN_ENTRIES, "o")
 +    def NewEntry(self, path):
 +        pass
 +
 +    @dbus_method(_DIN_ENTRIES, "a{sv}", "o")
 +    def Add(self, entry_data):
 +        """Adds a entry to the list, assigning it to the default backend and saving it
 +
 +        @param entry_data List of fields; format is [Key:Value, Key:Value, ...]
 +        @return Path of the newly created d-bus entry object"""
 +
 +        return self.add(entry_data)
  
 -    @dbus_method(_DIN_CONTACTS, "a{sv}", "s", sender_keyword="sender")
 +    @dbus_method(_DIN_ENTRIES, "a{sv}s", "s")
 +    def GetSingleEntrySingleField(self, query, field_name):
 +        """Returns the first entry found for a query, making it real easy to query simple things
 +
 +        @param query The query object
 +        @param field_name The name of the field to return
 +        @return The requested data"""
 +
 +        return self.get_single_entry_single_field(query, field_name)
 +
 +    @dbus_method(_DIN_ENTRIES, "a{sv}", "o", sender_keyword="sender")
      def Query(self, query, sender):
          """Processes a query and returns the dbus path of the resulting query object
  
          @param query Query
          @param sender Unique name of the query sender on the bus
 -        @return dbus path of the query object, e.g. /org.pyneo.PIM/Contacts/Queries/4"""
 +        @return dbus path of the query object, e.g. /org.freesmartphone.PIM/Entries/Queries/4"""
  
          return self.query_manager.process_query(query, sender)
  
@@@ -773,42 -885,140 +772,42 @@@
      def GetContent(self, rel_path):
          num_id = int(rel_path[1:])
  
 -        # Make sure the requested contact exists
 -        if num_id >= len(self._contacts) or self._contacts[num_id]==None:
 -            raise InvalidContactID()
 +        # Make sure the requested entry exists
 +        self.check_entry_id(num_id)
  
 -        return self._contacts[num_id].get_content()
 +        return self._entries[num_id].get_content()
  
      @dbus_method(_DIN_ENTRY, "", "as", rel_path_keyword="rel_path")
      def GetUsedBackends(self, rel_path):
          num_id = int(rel_path[1:])
                  
 -        # Make sure the requested contact exists
 -        if num_id >= len(self._contacts) or self._contacts[num_id]==None:
 -            raise InvalidContactID()
 +        # Make sure the requested entry exists
 +        self.check_entry_id(num_id)
          
 -        return self._contacts[num_id]._used_backends
 -
 +        return self._entries[num_id]._used_backends
  
      @dbus_method(_DIN_ENTRY, "s", "a{sv}", rel_path_keyword="rel_path")
      def GetMultipleFields(self, field_list, rel_path):
          num_id = int(rel_path[1:])
  
 -        # Make sure the requested contact exists
 -        if num_id >= len(self._contacts) or self._contacts[num_id]==None:
 -            raise InvalidContactID()
 -
 -        # Break the string up into a list
 -        fields = field_list.split(',')
 -        new_field_list = []
 -
 -        for field_name in fields:
 -            # Make sure the field list entries contain no spaces and aren't empty
 -            field_name = field_name.strip()
 -            if field_name: new_field_list.append(field_name)
 -
 -        return self._contacts[num_id].get_fields(new_field_list)
 +        return self.get_multiple_fields(num_id, field_list)
  
      @dbus_signal(_DIN_ENTRY, "", rel_path_keyword="rel_path")
 -    def ContactDeleted(self, rel_path=None):
 +    def EntryDeleted(self, rel_path=None):
          pass
  
      @dbus_method(_DIN_ENTRY, "", "", rel_path_keyword="rel_path")
      def Delete(self, rel_path):
          num_id = int(rel_path[1:])
  
 -        # Make sure the requested contact exists
 -        if num_id >= len(self._contacts) or self._contacts[num_id]==None:
 -            raise InvalidContactID()
 -
 -        backends = self._contacts[num_id]._used_backends
 -
 -        for backend_name in backends:
 -            backend = self._backends[backend_name]
 -            if not PIMB_CAN_DEL_ENTRY in backend.properties:
 -                raise InvalidBackend( "Backend properties not including PIMB_CAN_DEL_ENTRY" )
 -
 -            try:
 -                backend.del_contact(self._contacts[num_id].export_fields(backend_name))
 -            except AttributeError:
 -                raise InvalidBackend( "Backend does not feature del_contact" )
 -
 -        #del self._contacts[num_id]
 -        # Experimental: it may introduce some bugs.
 -        contact = self._contacts[num_id]
 -        self._contacts[num_id] = None
 -        del contact
 -
 -        # update Path fields, as IDs may be changed - UGLYYYY!!! */me spanks himself*
 -        # Not needed with that "experimental" code above.
 -        #for id in range(0,len(self._contacts)):
 -        #    path = _DBUS_PATH_CONTACTS+ '/' + str(id)
 -        #    for field in self._contacts[id]._fields:
 -        #        if field[0]=='Path':
 -        #            field[1]=path
 -
 -        for backend_name in backends:
 -            backend = self._backends[backend_name]
 -            if PIMB_NEEDS_SYNC in backend.properties:
 -                backend.sync() # If backend needs - sync entries
 -
 -        self.ContactDeleted(rel_path=rel_path)
 +        self.delete(num_id)
  
      @dbus_signal(_DIN_ENTRY, "a{sv}", rel_path_keyword="rel_path")
 -    def ContactUpdated(self, data, rel_path=None):
 +    def EntryUpdated(self, data, rel_path=None):
          pass
  
      @dbus_method(_DIN_ENTRY, "a{sv}", "", rel_path_keyword="rel_path")
      def Update(self, data, rel_path):
          num_id = int(rel_path[1:])
  
 -        # Make sure the requested contact exists
 -        if num_id >= len(self._contacts) or self._contacts[num_id]==None:
 -            raise InvalidContactID()
 -
 -        contact = self._contacts[num_id]
 -
 -        default_backend = BackendManager.get_default_backend(_DOMAIN_NAME)
 -        
 -        # Search for backend in which we can store new fields
 -        backend = ''
 -        if default_backend.name in contact._used_backends:
 -            backend = default_backend.name
 -        else:
 -            for backend_name in contact._used_backends:
 -                if PIMB_CAN_UPD_ENTRY_WITH_NEW_FIELD in self._backends[backend_name].properties:
 -                    backend = self._backends[backend_name]
 -                    break
 -
 -        # TODO: implement adding new data to backend, which doesn't incorporate contact data
 -        # For instance: we have SIM contact with Name and Phone. We want to add "Birthday" field.
 -        # opimd should then try to add "Birthday" field to default backend and then merge contacts.
 -
 -        for field_name in data:
 -            if not field_name in contact._field_idx:
 -                if backend!='':
 -                    contact.import_fields({field_name:data[field_name]}, backend)
 -                else:
 -                    raise InvalidBackend( "There is no backend which can store new field" )
 -            elif not field_name.startswith('_'):
 -                for field_nr in contact._field_idx[field_name]:
 -                    if contact[field_name]!=data[field_name]:
 -                        contact._fields[field_nr][1]=data[field_name]
 -
 -        for backend_name in contact._used_backends:
 -            backend = self._backends[backend_name]
 -            if not PIMB_CAN_UPD_ENTRY in backend.properties:
 -                raise InvalidBackend( "Backend properties not including PIMB_CAN_UPD_ENTRY" )
 -            try:
 -                backend.upd_contact(contact.export_fields(backend_name))
 -            except AttributeError:
 -                raise InvalidBackend( "Backend does not feature upd_contact" )
 -
 -            if PIMB_NEEDS_SYNC in backend.properties:
 -                backend.sync() # If backend needs - sync entries
 -
 -
 -        self.ContactUpdated(data, rel_path=rel_path)
 -
 +        self.update(num_id, data)

-- 
FSO frameworkd Debian packaging



More information about the pkg-fso-commits mailing list