Hello community, here is the log from the commit of package pycarddav for openSUSE:Factory checked in at 2013-09-09 09:54:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pycarddav (Old) and /work/SRC/openSUSE:Factory/.pycarddav.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pycarddav" Changes: -------- --- /work/SRC/openSUSE:Factory/pycarddav/pycarddav.changes 2013-07-08 12:36:36.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.pycarddav.new/pycarddav.changes 2013-09-09 09:54:04.000000000 +0200 @@ -1,0 +2,6 @@ +Sun Sep 8 11:42:17 UTC 2013 - [email protected] + +- update to version 0.5.1 + - assorted bugfixes, see the git log + +------------------------------------------------------------------- Old: ---- pyCardDAV-0.5.0.tar.gz New: ---- pyCardDAV-0.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pycarddav.spec ++++++ --- /var/tmp/diff_new_pack.6IT2mG/_old 2013-09-09 09:54:05.000000000 +0200 +++ /var/tmp/diff_new_pack.6IT2mG/_new 2013-09-09 09:54:05.000000000 +0200 @@ -16,29 +16,30 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # + %define orig_name pyCardDAV Name: pycarddav -Version: 0.5.0 -Release: 1 -License: MIT +Version: 0.5.1 +Release: 0 Summary: Simple to Use CardDAV CLI Client -Url: http://lostpackets.de/pycarddav/ +License: MIT Group: Productivity/Networking/Other +Url: http://lostpackets.de/pycarddav/ Source: http://lostpackets.de/pycarddav/downloads/%{orig_name}-%{version}.tar.gz BuildRequires: ed BuildRequires: python-devel BuildRequires: python-distribute BuildRequires: python-lxml -BuildRequires: vobject BuildRequires: python-requests BuildRequires: python-urwid BuildRequires: python-xdg +BuildRequires: vobject Requires: python-lxml -Requires: vobject Requires: python-requests Requires: python-urwid Requires: python-xdg +Requires: vobject BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -77,7 +78,7 @@ %files %defattr(-,root,root) -%doc CHANGELOG CONTRIBUTING.txt CONTRIBUTORS.txt COPYING NEWS.txt README.rst pycard.conf.sample +%doc CONTRIBUTING.txt CONTRIBUTORS.txt COPYING NEWS.txt README.rst pycard.conf.sample %{python_sitelib}/%{orig_name}-%{version}-py%{py_ver}.egg-info %{python_sitelib}/%{name} %{_bindir}/pc_query ++++++ pyCardDAV-0.5.0.tar.gz -> pyCardDAV-0.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/CHANGELOG new/pyCardDAV-0.5.1/CHANGELOG --- old/pyCardDAV-0.5.0/CHANGELOG 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/CHANGELOG 1970-01-01 01:00:00.000000000 +0100 @@ -1,21 +0,0 @@ -0.5 -multi account support -support for more contenttypes/carddav servers -all vcards should have a UID (required by RFC 6352 and enforced by Owncloud 5) - -0.4.2 -searching for non ascii characters should work -doing an OPTIONS request now to check for carddav capabilities - this should speed up the syncing process and increase compatibility (SOGo) - -0.4.1 -assorted bugfixes, see the git log - -0.4.0 -experimental write support in the backend -import & export vcards -import directly from mutt -speed increase in (initial) sync due to switching from pycurl to requests -detects removed cards on server and deletes them locally -can delete cards locally and on server -can handle base64 encoded images/sounds etc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/CONTRIBUTING.txt new/pyCardDAV-0.5.1/CONTRIBUTING.txt --- old/pyCardDAV-0.5.0/CONTRIBUTING.txt 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/CONTRIBUTING.txt 2013-09-02 00:15:11.000000000 +0200 @@ -1,6 +1,45 @@ +Submitting a Bug +================ + +If you found a bug or any part of pycarddav isn't working as you +expected, please check if that bug is either already reported at + +https://github.com/geier/pycarddav/issues?state=open + +or is already fixed in the development branch. + +You can check it out and install via: + + git clone -b develop https://github.com/geier/pycarddav + cd pycarddav + python setup.py install + +If the bug persists, always run the command again with the --debug option +and paste the output of that (of course you can edit out any private +details like your username and resource). + +Also, it is often helpful if you include which OS you are on, which +version of python and, in the case the problems occur during sync, which +version of requests you are using. You can just run the file at +https://gist.github.com/geier/5814123#file-debug_helper-py +and paste the +output. + +If the error occurs during sync, please also supply details on your +CardDAV server (which server and version). + + +Hacking +======= + The *master* branch on github should always contain the latest released -stable version. Development mostly happens in the *develop* branch, or -in the next point release *dev*-branch (e.g. *4.2-dev*). So please check -out the *develop* branch before starting to hack on pycarddav. +stable version. Development mostly happens in feature branches (only for +major new features), the *develop* branch, or in the next point release +*dev*-branch (e.g. *4.2-dev*). So please check out the *develop* branch +before starting to hack on pycarddav. + +Before submitting your first patch, please add yourself to +*CONTRIBUTORS.txt*. -Before requesting a pull, please add yourself to *CONTRIBUTORS.txt*. +You can submit patches either via email (pycarddav at lostpackets dot de +)or via github pull requests. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/CONTRIBUTORS.txt new/pyCardDAV-0.5.1/CONTRIBUTORS.txt --- old/pyCardDAV-0.5.0/CONTRIBUTORS.txt 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/CONTRIBUTORS.txt 2013-09-02 00:16:39.000000000 +0200 @@ -3,3 +3,5 @@ Aurélien Gâteau - http://agateau.com Hugo Osvaldo Barrera <[email protected]> Ben Boeckel - mathstuf [at] gmail [dot] com +Thomas Glanzmann - [email protected] - http://thomas.glanzmann.de +Johannes Goetzfried - [email protected] - http://jgoetzfried.de diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/MANIFEST.in new/pyCardDAV-0.5.1/MANIFEST.in --- old/pyCardDAV-0.5.0/MANIFEST.in 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/MANIFEST.in 2013-09-02 00:15:11.000000000 +0200 @@ -1,5 +1,5 @@ include pycard.conf.sample -include README.txt +include README.rst include CONTRIBUTING.txt include CONTRIBUTORS.txt include COPYING diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/NEWS.txt new/pyCardDAV-0.5.1/NEWS.txt --- old/pyCardDAV-0.5.0/NEWS.txt 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/NEWS.txt 2013-09-02 00:16:39.000000000 +0200 @@ -1,6 +1,12 @@ News ==== +02.09.2013: pyCardDAV v.0.5.1 released + + pyCardDAV v0.5.1 is released. This is a bugfix release, if everything works + fine for you, there is no need to upgrade. Database deletion should not be + necessary. + 15.06.2013: pyCardDAV v.0.5.0 released **New** This release brings support for multiple CardDAV accounts. See the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/PKG-INFO new/pyCardDAV-0.5.1/PKG-INFO --- old/pyCardDAV-0.5.0/PKG-INFO 2013-06-15 19:35:41.000000000 +0200 +++ new/pyCardDAV-0.5.1/PKG-INFO 2013-09-02 00:19:35.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pyCardDAV -Version: 0.5.0 +Version: 0.5.1 Summary: A CardDAV based address book tool Home-page: http://lostpackets.de/pycarddav/ Author: Christian Geier @@ -47,7 +47,7 @@ Installation ------------ You can download *pyCardDAV* either from the above download link or check it - out at github_. Then install *pyCardDAV* by executing *python setup.py install*. + out from git (at github). Then install *pyCardDAV* by executing *python setup.py install*. If you feel more adventurous you can always the *develop* branch on github, which *should* always be in a usable state. pyCardDAV is also available on pypi_ and can be installed via pip install pycarddav or easy_install pycarddav. @@ -66,7 +66,7 @@ to work), owncloud and sabredav. .. _pypi: https://pypi.python.org/pypi/pyCardDAV/ - .. _github: http://github.com/geier/pycarddav/ + .. _git: http://github.com/geier/pycarddav/ Usage ----- @@ -141,6 +141,16 @@ In accordance with RFC 6352 all VCards that are imported or changed by pyCadDAV will automatically get a random UID (if they haven't one already), as some CardDAV servers, e.g. Owncloud require these. + + Debian Wheezy Quickstart + ------------------------ + + apt-get install python-requests python-vobject python-pytest python-urwid python-lxml python-pyxdg + sudo python setup.py install + mkdir -p ~/.config/pycard + chmod 700 ~/.config/pycard + cp pycard.conf.sample ~/.config/pycard/pycard.conf + License ------- *pyCardDAV* is released under the Expat/MIT License: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/README.rst new/pyCardDAV-0.5.1/README.rst --- old/pyCardDAV-0.5.0/README.rst 2013-06-15 19:27:03.000000000 +0200 +++ new/pyCardDAV-0.5.1/README.rst 2013-09-02 00:16:39.000000000 +0200 @@ -39,7 +39,7 @@ Installation ------------ You can download *pyCardDAV* either from the above download link or check it -out at github_. Then install *pyCardDAV* by executing *python setup.py install*. +out from git (at github). Then install *pyCardDAV* by executing *python setup.py install*. If you feel more adventurous you can always the *develop* branch on github, which *should* always be in a usable state. pyCardDAV is also available on pypi_ and can be installed via pip install pycarddav or easy_install pycarddav. @@ -58,7 +58,7 @@ to work), owncloud and sabredav. .. _pypi: https://pypi.python.org/pypi/pyCardDAV/ -.. _github: http://github.com/geier/pycarddav/ +.. _git: http://github.com/geier/pycarddav/ Usage ----- @@ -133,6 +133,16 @@ In accordance with RFC 6352 all VCards that are imported or changed by pyCadDAV will automatically get a random UID (if they haven't one already), as some CardDAV servers, e.g. Owncloud require these. + +Debian Wheezy Quickstart +------------------------ + +apt-get install python-requests python-vobject python-pytest python-urwid python-lxml python-pyxdg +sudo python setup.py install +mkdir -p ~/.config/pycard +chmod 700 ~/.config/pycard +cp pycard.conf.sample ~/.config/pycard/pycard.conf + License ------- *pyCardDAV* is released under the Expat/MIT License: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pyCardDAV.egg-info/PKG-INFO new/pyCardDAV-0.5.1/pyCardDAV.egg-info/PKG-INFO --- old/pyCardDAV-0.5.0/pyCardDAV.egg-info/PKG-INFO 2013-06-15 19:35:40.000000000 +0200 +++ new/pyCardDAV-0.5.1/pyCardDAV.egg-info/PKG-INFO 2013-09-02 00:19:35.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pyCardDAV -Version: 0.5.0 +Version: 0.5.1 Summary: A CardDAV based address book tool Home-page: http://lostpackets.de/pycarddav/ Author: Christian Geier @@ -47,7 +47,7 @@ Installation ------------ You can download *pyCardDAV* either from the above download link or check it - out at github_. Then install *pyCardDAV* by executing *python setup.py install*. + out from git (at github). Then install *pyCardDAV* by executing *python setup.py install*. If you feel more adventurous you can always the *develop* branch on github, which *should* always be in a usable state. pyCardDAV is also available on pypi_ and can be installed via pip install pycarddav or easy_install pycarddav. @@ -66,7 +66,7 @@ to work), owncloud and sabredav. .. _pypi: https://pypi.python.org/pypi/pyCardDAV/ - .. _github: http://github.com/geier/pycarddav/ + .. _git: http://github.com/geier/pycarddav/ Usage ----- @@ -141,6 +141,16 @@ In accordance with RFC 6352 all VCards that are imported or changed by pyCadDAV will automatically get a random UID (if they haven't one already), as some CardDAV servers, e.g. Owncloud require these. + + Debian Wheezy Quickstart + ------------------------ + + apt-get install python-requests python-vobject python-pytest python-urwid python-lxml python-pyxdg + sudo python setup.py install + mkdir -p ~/.config/pycard + chmod 700 ~/.config/pycard + cp pycard.conf.sample ~/.config/pycard/pycard.conf + License ------- *pyCardDAV* is released under the Expat/MIT License: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pyCardDAV.egg-info/SOURCES.txt new/pyCardDAV-0.5.1/pyCardDAV.egg-info/SOURCES.txt --- old/pyCardDAV-0.5.0/pyCardDAV.egg-info/SOURCES.txt 2013-06-15 19:35:41.000000000 +0200 +++ new/pyCardDAV-0.5.1/pyCardDAV.egg-info/SOURCES.txt 2013-09-02 00:19:35.000000000 +0200 @@ -1,4 +1,3 @@ -CHANGELOG CONTRIBUTING.txt CONTRIBUTORS.txt COPYING @@ -14,10 +13,12 @@ pyCardDAV.egg-info/PKG-INFO pyCardDAV.egg-info/SOURCES.txt pyCardDAV.egg-info/dependency_links.txt +pyCardDAV.egg-info/requires.txt pyCardDAV.egg-info/top_level.txt pycarddav/__init__.py pycarddav/backend.py pycarddav/carddav.py pycarddav/controllers.py pycarddav/model.py -pycarddav/ui.py \ No newline at end of file +pycarddav/ui.py +pycarddav/version.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pyCardDAV.egg-info/requires.txt new/pyCardDAV-0.5.1/pyCardDAV.egg-info/requires.txt --- old/pyCardDAV-0.5.0/pyCardDAV.egg-info/requires.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/pyCardDAV-0.5.1/pyCardDAV.egg-info/requires.txt 2013-09-02 00:19:35.000000000 +0200 @@ -0,0 +1,5 @@ +lxml +vobject +requests +urwid +pyxdg \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycard.conf.sample new/pyCardDAV-0.5.1/pycard.conf.sample --- old/pyCardDAV-0.5.0/pycard.conf.sample 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/pycard.conf.sample 2013-09-02 00:16:39.000000000 +0200 @@ -7,7 +7,7 @@ # The path to the CardDAV resource. #resource: https://[server]/owncloud/apps/contacts/carddav.php/addressbooks/[user]/[addressbook name]/ -resource: https://carddav.server.tld:443/davical/caldav.php/username/addressbook/ +resource: https://carddav.server.tld:443/davical/caldav.php/username/addresses/ # Authentication Method: possible values are: basic (the default), or digest # (for servers that need HTTP digest authentification) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycarddav/__init__.py new/pyCardDAV-0.5.1/pycarddav/__init__.py --- old/pyCardDAV-0.5.0/pycarddav/__init__.py 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/pycarddav/__init__.py 2013-09-02 00:16:39.000000000 +0200 @@ -31,11 +31,13 @@ import sys import xdg.BaseDirectory +import version + from netrc import netrc from urlparse import urlsplit __productname__ = 'pyCardDAV' -__version__ = '0.5.0' +__version__ = version.__version__ __author__ = 'Christian Geier' __copyright__ = 'Copyright 2011-2013 Christian Geier & contributors' __author_email__ = '[email protected]' @@ -91,10 +93,10 @@ class Section(object): - READERS = { bool: ConfigParser.SafeConfigParser.getboolean, - float: ConfigParser.SafeConfigParser.getfloat, - int: ConfigParser.SafeConfigParser.getint, - str: ConfigParser.SafeConfigParser.get } + READERS = {bool: ConfigParser.SafeConfigParser.getboolean, + float: ConfigParser.SafeConfigParser.getfloat, + int: ConfigParser.SafeConfigParser.getint, + str: ConfigParser.SafeConfigParser.get} def __init__(self, parser, group): self._parser = parser @@ -120,11 +122,13 @@ else: reader = Section.READERS[type(default)] self._parsed[option] = filter_(reader(self._parser, section, option)) - # Remove option once handled (see the check function). self._parser.remove_option(section, option) except ConfigParser.Error: - self._parsed[option] = default + if filter_ is None: + self._parsed[option] = default + else: + self._parsed[option] = filter_(default) return Namespace(self._parsed) @@ -132,7 +136,7 @@ def group(self): return self._group - def _parse_bool_string(self, value): + def _parse_verify(self, value): """if value is either 'True' or 'False' it returns that value as a bool, otherwise it returns the value""" value = value.strip().lower() @@ -152,6 +156,7 @@ else: return False + class AccountSection(Section): def __init__(self, parser): Section.__init__(self, parser, 'accounts') @@ -160,7 +165,7 @@ ('passwd', '', None), ('resource', '', None), ('auth', 'basic', None), - ('verify', 'True', self._parse_bool_string), + ('verify', 'true', self._parse_verify), ('write_support', '', self._parse_write_support), ] @@ -196,7 +201,7 @@ def __init__(self, desc, check_accounts=True): # Set the configuration current schema. - self._sections = [ AccountSection, SQLiteSection ] + self._sections = [AccountSection, SQLiteSection] # Build parsers and set common options. self._check_accounts = check_accounts @@ -339,9 +344,9 @@ for name, value in sorted(dict.copy(conf).iteritems()): if type(value) is list: for o in value: - self.dump(o, '\t'*tab + name + ':', tab + 1) + self.dump(o, '\t' * tab + name + ':', tab + 1) elif type(value) is Namespace: - self.dump(value, '\t'*tab + name + ':', tab + 1) + self.dump(value, '\t' * tab + name + ':', tab + 1) elif name != 'passwd': logging.debug('%s%s: %s', '\t'*tab, name, value) @@ -411,7 +416,7 @@ resource = os.path.join( ConfigurationParser.DEFAULT_PATH, ConfigurationParser.DEFAULT_FILE) paths.extend([os.path.join(path, resource) - for path in xdg.BaseDirectory.xdg_config_dirs]) + for path in xdg.BaseDirectory.xdg_config_dirs]) paths.append(os.path.expanduser(os.path.join('~', '.' + resource))) paths.append(os.path.expanduser(ConfigurationParser.DEFAULT_FILE)) @@ -422,6 +427,7 @@ return None + class SyncConfigurationParser(ConfigurationParser): """A specialized setup tool for synchronization.""" def __init__(self): @@ -439,7 +445,7 @@ if ns.sync.accounts: for name in set(ns.sync.accounts): if not name in [a.name for a in ns.accounts]: - logging.warn('Uknown account %s', name) + logging.warn('Unknown account %s', name) ns.sync.accounts.remove(name) if len(ns.sync.accounts) == 0: logging.error('No valid account selected') @@ -454,4 +460,3 @@ ns.sync.accounts = set(ns.sync.accounts) return result - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycarddav/backend.py new/pyCardDAV-0.5.1/pycarddav/backend.py --- old/pyCardDAV-0.5.0/pycarddav/backend.py 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/pycarddav/backend.py 2013-09-02 00:16:39.000000000 +0200 @@ -101,8 +101,8 @@ result = list() for account in accounts: sql_s = 'SELECT href FROM {0} WHERE vcard LIKE (?)'.format(account) - vrefs = self.sql_ex(sql_s, stuple) - result = result + ([(vref[0], account) for vref in vrefs]) + hrefs = self.sql_ex(sql_s, stuple) + result = result + ([(href[0], account) for href in hrefs]) return result def _dump(self, account_name): @@ -229,27 +229,15 @@ vcard = model.vcard_from_string(vcard) else: vcard_s = vcard.vcf - - if self.href_exists(href, account_name): # existing card - stuple = (etag, vcard.name, vcard.fname, vcard_s, status, href) - sql_s = 'UPDATE {0} SET etag = ?, name = ?, fname = ?, vcard = ?, \ - status = ? WHERE href = ?;'.format(account_name) - self.sql_ex(sql_s, stuple) - - else: - if href == '': - for _ in range(10): - href = get_random_href() - if self.href_exists(href, account_name) is False: - break - # could not find a (random) href that's not yet in the db - # broken random number generator? - #TODO: what's happens now? exception? - stuple = (href, etag, vcard.name, vcard.fname, vcard_s, status) - sql_s = ('INSERT INTO {0} ' - '(href, etag, name, fname, vcard, status) ' - 'VALUES (?,?,?,?,?,?);'.format(account_name)) - self.sql_ex(sql_s, stuple) + if href == '': + href = get_random_href() + stuple = (etag, vcard.name, vcard.fname, vcard_s, status, href, href) + sql_s = ('INSERT OR REPLACE INTO {0} ' + '(etag, name, fname, vcard, status, href) ' + 'VALUES (?, ?, ?, ?, ?, ' + 'COALESCE((SELECT href FROM {0} WHERE href = ?), ?)' + ');'.format(account_name)) + self.sql_ex(sql_s, stuple) def update_href(self, old_href, new_href, account_name, etag='', status=OK): """updates old_href to new_href, can also alter etag and status, @@ -283,37 +271,37 @@ etag = self.sql_ex(sql_s, (href,))[0][0] return etag - def delete_vcard_from_db(self, vref, account_name): + def delete_vcard_from_db(self, href, account_name): """ removes the whole vcard, returns nothing """ - stuple = (vref, ) - logging.debug("locally deleting " + str(vref)) + stuple = (href, ) + logging.debug("locally deleting " + str(href)) self.sql_ex('DELETE FROM {0} WHERE href=(?)'.format(account_name), stuple) - def get_all_vref_from_db(self, accounts): - """returns a list with all vrefs + def get_all_href_from_db(self, accounts): + """returns a list with all hrefs """ result = list() for account in accounts: - vrefs = self.sql_ex('SELECT href FROM {0}'.format(account)) - result = result + [(vref[0], account) for vref in vrefs] + hrefs = self.sql_ex('SELECT href FROM {0} ORDER BY fname COLLATE NOCASE'.format(account)) + result = result + [(href[0], account) for href in hrefs] return result - def get_all_vref_from_db_not_new(self, accounts): - """returns list of all not new vrefs""" + def get_all_href_from_db_not_new(self, accounts): + """returns list of all not new hrefs""" result = list() for account in accounts: sql_s = 'SELECT href FROM {0} WHERE status != (?)'.format(account) stuple = (NEW,) - vrefs = self.sql_ex(sql_s, stuple) - result = result + [(vref[0], account) for vref in vrefs] + hrefs = self.sql_ex(sql_s, stuple) + result = result + [(href[0], account) for href in hrefs] return result -# def get_names_vref_from_db(self, searchstring=None): +# def get_names_href_from_db(self, searchstring=None): # """ -# :return: list of tuples(name, vref) of all entries from the db +# :return: list of tuples(name, href) of all entries from the db # """ # if searchstring is None: # return self.sql_ex('SELECT fname, href FROM {0} ' @@ -334,10 +322,12 @@ def get_vcard_from_db(self, href, account_name): """returns a VCard() """ - sql_s = 'SELECT vcard FROM {0} WHERE href=(?)'.format(account_name) + sql_s = 'SELECT vcard, etag FROM {0} WHERE href=(?)'.format(account_name) result = self.sql_ex(sql_s, (href, )) vcard = model.vcard_from_string(result[0][0]) vcard.href = href + vcard.account = account_name + vcard.etag = result[0][1] return vcard def get_changed(self, account_name): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycarddav/carddav.py new/pyCardDAV-0.5.1/pycarddav/carddav.py --- old/pyCardDAV-0.5.0/pycarddav/carddav.py 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/pycarddav/carddav.py 2013-09-02 00:16:39.000000000 +0200 @@ -71,9 +71,11 @@ def __init__(self, resource, debug='', user='', passwd='', verify=True, write_support=False, auth='basic'): - #shutup url3 + #shutup urllib3 urllog = logging.getLogger('requests.packages.urllib3.connectionpool') urllog.setLevel(logging.CRITICAL) + urllog = logging.getLogger('urllib3.connectionpool') + urllog.setLevel(logging.CRITICAL) split_url = urlparse.urlparse(resource) url_tuple = namedtuple('url', 'resource base path') @@ -97,7 +99,7 @@ self.url.resource, headers=headers, **self._settings) - response.raise_for_status() #raises error on not 2XX HTTP status code + response.raise_for_status() # raises error on not 2XX HTTP status code if response.headers['DAV'].count('addressbook') == 0: raise Exception("URL is not a CardDAV resource") @@ -205,8 +207,7 @@ **self._settings) if response.ok: parsed_url = urlparse.urlparse(remotepath) - - if response.headers['etag'] is None: + if 'etag' not in response.headers.keys() or response.headers['etag'] is None: etag = '' else: etag = response.headers['etag'] @@ -262,8 +263,12 @@ # "text/directory" # "text/vcard; charset=utf-8" CalendarServer if (props.tag == namespace + "getcontenttype" and - props.text.split(';')[0].strip() in ['text/vcard', 'text/x-vcard']): + props.text.split(';')[0].strip() in ['text/vcard', 'text/x-vcard']): insert = True + if (props.tag == namespace + "resourcetype" and + namespace + "collection" in [c.tag for c in props.iterchildren()]): + insert = False + break if (props.tag == namespace + "getetag"): etag = props.text if insert: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycarddav/controllers.py new/pyCardDAV-0.5.1/pycarddav/controllers.py --- old/pyCardDAV-0.5.0/pycarddav/controllers.py 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/pycarddav/controllers.py 2013-09-02 00:16:39.000000000 +0200 @@ -60,10 +60,12 @@ if conf.query.backup: with open(conf.query.backup, 'w') as vcf_file: if search_string == "": - hrefs_account_list = my_dbtool.get_all_vref_from_db(conf.sync.accounts) + href_account_list = my_dbtool.get_all_href_from_db( + conf.sync.accounts) else: - hrefs_account_list = my_dbtool.search(search_string, conf.sync.accounts) - for href, account in hrefs_account_list: + href_account_list = my_dbtool.search(search_string, + conf.sync.accounts) + for href, account in href_account_list: vcard = my_dbtool.get_vcard_from_db(href, account) vcf_file.write(vcard.vcf.encode('utf-8')) sys.exit() @@ -77,32 +79,35 @@ # mark a card for deletion if conf.query.delete: - hrefs_account_list = my_dbtool.search(search_string, conf.sync.accounts) - if len(hrefs_account_list) is 0: + href_account_list = my_dbtool.search(search_string, + conf.sync.accounts) + if len(href_account_list) is 0: sys.exit('Found no matching cards.') - elif len(hrefs_account_list) is 1: - href, account = hrefs_account_list[0] + elif len(href_account_list) is 1: + href, account = href_account_list[0] + card = my_dbtool.get_vcard_from_db(href, account) else: - pane = ui.VCardChooserPane(my_dbtool, hrefs_account_list) + pane = ui.VCardChooserPane(my_dbtool, + href_account_list=href_account_list) ui.start_pane(pane) card = pane._walker.selected_vcard - href = card.href - if href in my_dbtool.get_new(account): + if card.href in my_dbtool.get_new(card.account): # cards not yet on the server get deleted directly, otherwise we # will try to delete them on the server later (where they don't # exist) and this will raise an exception - my_dbtool.delete_vcard_from_db(href, account) + my_dbtool.delete_vcard_from_db(card.href, card.account) else: - my_dbtool.mark_delete(href, account) - print('vcard "%s" deleted from local db, will be deleted ' % href + - 'on the server on the next sync') + my_dbtool.mark_delete(card.href, card.account) + print(u'vcard {0} - "{1}" deleted from local db, ' + 'will be deleted on the server on the next ' + 'sync'.format(card.href, card.fname)) sys.exit() print("searching for " + conf.query.search_string + "...") result = my_dbtool.search(search_string, conf.sync.accounts) - for vref, account in result: - vcard = my_dbtool.get_vcard_from_db(vref, account) + for href, account in result: + vcard = my_dbtool.get_vcard_from_db(href, account) if conf.query.mutt_format: lines = vcard.print_email() elif conf.query.tel: @@ -155,7 +160,9 @@ my_dbtool.reset_flag(href, conf.account.name) remote_changed = True except carddav.NoWriteSupport: - logging.info('failed to upload changed card %s, you need to enable write support, see the documentation', href) + logging.info('failed to upload changed card {0}, ' + 'you need to enable write support, ' + 'see the documentation', href) # uploading hrefs = my_dbtool.get_new(conf.account.name) for href in hrefs: @@ -163,10 +170,15 @@ logging.debug("trying to upload new card %s", href) card = my_dbtool.get_vcard_from_db(href, conf.account.name) (href_new, etag_new) = syncer.upload_new_card(card.vcf) - my_dbtool.update_href(href, href_new, conf.account.name, status=backend.OK) + my_dbtool.update_href(href, + href_new, + conf.account.name, + status=backend.OK) remote_changed = True except carddav.NoWriteSupport: - logging.info('failed to upload card %s, you need to enable write support, see the documentation', href) + logging.info('failed to upload card %s, ' + 'you need to enable write support, ' + 'see the documentation', href) # deleting locally deleted cards on the server hrefs_etags = my_dbtool.get_marked_delete(conf.account.name) @@ -178,7 +190,9 @@ my_dbtool.delete_vcard_from_db(href, conf.account.name) remote_changed = True except carddav.NoWriteSupport: - logging.info('failed to delete card %s, you need to enable write support, see the documentation', href) + logging.info('failed to delete card {0}, ' + 'you need to enable write support, ' + 'see the documentation'.format(href)) # detecting remote-deleted cards # is there a better way to compare a list of unicode() with a list of str() @@ -186,7 +200,8 @@ if remote_changed: abook = syncer.get_abook() # type (abook): dict - r_href_account_list = my_dbtool.get_all_vref_from_db_not_new([conf.account.name]) + r_href_account_list = my_dbtool.get_all_href_from_db_not_new( + [conf.account.name]) delete = set([href for href, account in r_href_account_list]).difference(abook.keys()) for href in delete: my_dbtool.delete_vcard_from_db(href, conf.account.name) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycarddav/model.py new/pyCardDAV-0.5.1/pycarddav/model.py --- old/pyCardDAV-0.5.0/pycarddav/model.py 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/pycarddav/model.py 2013-09-02 00:16:39.000000000 +0200 @@ -157,7 +157,8 @@ [('[email protected]', ['WORK', 'PREF']), ('[email protected]', ['HOME'])] - h_ref: unique id (really just the url) of the VCard + self.href: unique id (really just the url) of the VCard + self.account: account which this card is associated with db_path: database file from which to initialize the VCard self.edited: @@ -173,6 +174,8 @@ else: defaultdict.__init__(self, list, ddict) self.href = '' + self.account = '' + self.etag = '' self.edited = 0 def serialize(self): @@ -241,7 +244,10 @@ def _pretty_base(self, keylist): collector = list() - collector.append('\n' + BTEXT + 'Name: ' + self.fname + NTEXT) + if sys.stdout.isatty(): + collector.append('\n' + BTEXT + 'Name: ' + self.fname + NTEXT) + else: + collector.append('\n' + 'Name: ' + self.fname) for key in keylist: for value in self[key]: try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycarddav/ui.py new/pyCardDAV-0.5.1/pycarddav/ui.py --- old/pyCardDAV-0.5.0/pycarddav/ui.py 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/pycarddav/ui.py 2013-09-02 00:16:39.000000000 +0200 @@ -41,7 +41,7 @@ """A walker to browse a VCard list. This walker returns a selectable Text for each of the passed VCard - references. Either accounts or ref_account_list needs to be supplied. If no + references. Either accounts or href_account_list needs to be supplied. If no list of tuples of references are passed to the constructor, then all cards from the specified accounts are browsed. """ @@ -53,19 +53,19 @@ def keypress(self, _, key): return key - def __init__(self, database, accounts=None, ref_account_list=None): + def __init__(self, database, accounts=None, href_account_list=None): urwid.ListWalker.__init__(self) - if accounts is None and ref_account_list is None: + if accounts is None and href_account_list is None: raise Exception self._db = database - self._refs_account_list = ref_account_list or database.get_all_vref_from_db(accounts) + self._href_account_list = href_account_list or database.get_all_href_from_db(accounts) self._current = 0 @property def selected_vcard(self): """Return the focused VCard.""" - return self._db.get_vcard_from_db(self._refs_account_list[self._current][0], - self._refs_account_list[self._current][1] + return self._db.get_vcard_from_db(self._href_account_list[self._current][0], + self._href_account_list[self._current][1] ) def get_focus(self): @@ -79,7 +79,7 @@ def get_next(self, pos): """Return (widget after pos, position after pos).""" - if pos >= len(self._refs_account_list) - 1: + if pos >= len(self._href_account_list) - 1: return None, None return self._get_at(pos + 1) @@ -91,8 +91,8 @@ def _get_at(self, pos): """Return a textual representation of the VCard at pos.""" - vcard = self._db.get_vcard_from_db(self._refs_account_list[pos][0], - self._refs_account_list[pos][1] + vcard = self._db.get_vcard_from_db(self._href_account_list[pos][0], + self._href_account_list[pos][1] ) label = vcard.fname if vcard['EMAIL']: @@ -159,8 +159,8 @@ VCard can be selected to be used in another pane, like the EditorPane. """ - def __init__(self, database, accounts=None, refs_account_list=None): - self._walker = VCardWalker(database, accounts=accounts, ref_account_list=refs_account_list) + def __init__(self, database, accounts=None, href_account_list=None): + self._walker = VCardWalker(database, accounts=accounts, href_account_list=href_account_list) Pane.__init__(self, urwid.ListBox(self._walker), 'Browse...') def get_keys(self): @@ -271,7 +271,11 @@ [self._fname_edit.edit_text, self._lname_edit.edit_text]) for i, edit in enumerate(self._email_edits): self._vcard['EMAIL'][i] = (edit.edit_text, self._vcard['EMAIL'][i][1]) - self._db.update(self._vcard, self._account, self._vcard.href, status=pycarddav.backend.NEW) + self._db.update(self._vcard, + self._account, + self._vcard.href, + etag=self._vcard.etag, + status=pycarddav.backend.NEW) class Window(urwid.Frame): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/pycarddav/version.py new/pyCardDAV-0.5.1/pycarddav/version.py --- old/pyCardDAV-0.5.0/pycarddav/version.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyCardDAV-0.5.1/pycarddav/version.py 2013-09-02 00:19:35.000000000 +0200 @@ -0,0 +1 @@ +__version__ = '0.5.1' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyCardDAV-0.5.0/setup.py new/pyCardDAV-0.5.1/setup.py --- old/pyCardDAV-0.5.0/setup.py 2013-06-15 19:25:35.000000000 +0200 +++ new/pyCardDAV-0.5.1/setup.py 2013-09-02 00:17:32.000000000 +0200 @@ -1,9 +1,56 @@ #!/usr/bin/env python2 +import os +import string +import subprocess import sys +import warnings + #from distutils.core import setup from setuptools import setup +MAJOR = 0 +MINOR = 5 +PATCH = 1 + +RELEASE = True + +VERSION = "{0}.{1}.{2}".format(MAJOR, MINOR, PATCH) + +if not RELEASE: + try: + try: + pipe = subprocess.Popen(["git", "describe", "--dirty", "--tags"], + stdout=subprocess.PIPE) + except EnvironmentError: + warnings.warn("WARNING: git not installed or failed to run") + + revision = pipe.communicate()[0].strip().lstrip('v') + if pipe.returncode != 0: + warnings.warn("WARNING: couldn't get git revision") + + if revision != VERSION: + revision = revision.lstrip(string.digits + '.') + VERSION += '.dev' + revision + except: + VERSION += '.dev' + warnings.warn("WARNING: git not installed or failed to run") + + +def write_version(): + """writes the pycarddav/version.py file""" + template = """\ +__version__ = '{0}' +""" + filename = os.path.join( + os.path.dirname(__file__), 'pycarddav', 'version.py') + with open(filename, 'w') as versionfile: + versionfile.write(template.format(VERSION)) + print("wrote pycarddav/version.py with version={0}".format(VERSION)) + +write_version() + + requirements = [ 'lxml', 'vobject', @@ -17,7 +64,7 @@ setup( name='pyCardDAV', - version='0.5.0', + version=VERSION, description='A CardDAV based address book tool', long_description=open('README.rst').read(), author='Christian Geier', @@ -27,6 +74,7 @@ packages=['pycarddav'], scripts=['bin/pycardsyncer', 'bin/pc_query', 'bin/pycard-import'], requires=requirements, + install_requires=requirements, classifiers=[ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
