Copyright headers, more docstrings

This commit is contained in:
Markus Unterwaditzer 2014-02-15 17:05:19 +01:00
parent 220f921ab6
commit ca92d9a428
14 changed files with 183 additions and 41 deletions

19
LICENSE Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2013 Markus Unterwaditzer
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
setup.cfg Normal file
View file

@ -0,0 +1,2 @@
[wheel]
universal = 1

29
setup.py Normal file
View file

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer
~~~~~~~~~~
vdirsyncer is a syncronization tool for vdir. See the README for more
details.
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
from setuptools import setup, find_packages
setup(
name='vdirsyncer',
version='0.1.0',
author='Markus Unterwaditzer',
author_email='markus@unterwaditzer.net',
url='https://github.com/untitaker/vdirsyncer',
description='A syncronization tool for vdir',
long_description=open('README.md').read(),
packages=find_packages(),
include_package_data=True,
entry_points={
'console_scripts': ['vdirsyncer = vdirsyncer.cli:main']
},
install_requires=['argvard']
)

View file

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer
~~~~~~~~~~
vdirsyncer is a syncronization tool for vdir. See the README for more
details.
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
__version__ = '0.1.0'

View file

@ -1,10 +1,23 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.cli
~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
import os
import ConfigParser
from vdirsyncer.cli_utils import path
from vdirsyncer.sync import sync_classes
def _path(p):
p = os.path.expanduser(p)
p = os.path.abspath(p)
return p
def get_config_parser(env):
fname = env.get('VDIRSYNCER_CONFIG', path('~/.vdirsyncer/config'))
fname = env.get('VDIRSYNCER_CONFIG', _path('~/.vdirsyncer/config'))
c = ConfigParser.SafeConfigParser()
c.read(fname)
return dict((c, c.items(c)) for c in c.sections())

View file

@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
'''
watdo.cli_utils
~~~~~~~~~
This module contains helper functions that should be useful for arbitrary
CLI interfaces.
:copyright: (c) 2013 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
import os
import sys
def bail_out(msg):
print(msg)
sys.exit(1)
def check_directory(path):
if not os.path.exists(path):
os.makedirs(path)
def path(p):
p = os.path.expanduser(p)
p = os.path.abspath(p)
return p
def confirm(message='Are you sure? (Y/n)'):
inp = raw_input(message).lower().strip()
if not inp or inp == 'y':
return True
return False

View file

@ -1,11 +1,25 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.exceptions
~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
class Error(Exception):
'''Baseclass for all errors.'''
pass
class NotFoundError(Error):
'''The item does not exist (anymore).'''
pass
class AlreadyExistingError(Error):
'''The item exists although it shouldn't, possible race condition.'''
pass
class WrongEtagError(Error):
'''The given etag doesn't match the etag from the storage, possible race
condition.'''
pass

View file

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.storage
~~~~~~~~~~~~~~~~~~
There are storage classes which control the access to one vdir-collection
and offer basic CRUD-ish methods for modifying those collections. The exact
interface is described in `vdirsyncer.storage.base`, the `Storage` class
should be a superclass of all storage classes.
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''

View file

@ -1,3 +1,12 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.storage.base
~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
class Item(object):
'''should-be-immutable wrapper class for VCALENDAR and VCARD'''
def __init__(self, raw):
@ -14,6 +23,8 @@ class Item(object):
class Storage(object):
'''Superclass of all storages, mainly useful to summarize the interface to
implement.'''
def __init__(self, fileext='', item_class=Item):
self.fileext = fileext
self.item_class = item_class

View file

@ -1,9 +1,22 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.storage.filesystem
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
import os
from vdirsyncer.storage.base import Storage, Item
import vdirsyncer.exceptions as exceptions
class FilesystemStorage(Storage):
'''Saves data in vdir collection, mtime is etag.'''
def __init__(self, path, **kwargs):
'''
:param path: Absolute path to a *collection* inside a vdir.
'''
self.path = path
super(FilesystemStorage, self).__init__(**kwargs)

View file

@ -1,8 +1,20 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.storage.memory
~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
import datetime
from vdirsyncer.storage.base import Item, Storage
import vdirsyncer.exceptions as exceptions
class MemoryStorage(Storage):
'''
Saves data in RAM, only useful for testing.
'''
def __init__(self, **kwargs):
self.items = {} # uid => (etag, object)
super(MemoryStorage, self).__init__(**kwargs)

View file

@ -1,9 +1,31 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.sync
~~~~~~~~~~~~~~~
The function in `vdirsyncer.sync` can be called on two instances of
`Storage` to syncronize them. Due to the abstract API storage classes are
implementing, the two given instances don't have to be of the same exact
type. This allows us not only to syncronize a local vdir with a CalDAV
server, but also syncronize two CalDAV servers or two local vdirs.
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
def sync(storage_a, storage_b, status):
'''Syncronizes two storages.
:param storage_a: The first storage
:type storage_a: :class:`vdirsyncer.storage.base.Storage`
:param storage_b: The second storage
:param status: {uid: (etag_a, etag_b)}
:type storage_b: :class:`vdirsyncer.storage.base.Storage`
:param status:
{uid: (etag_a, etag_b)}, metadata about the two storages for detection
of changes. Will be modified by the function and should be passed to it
at the next sync. If this is the first sync, an empty dictionary should
be provided.
'''
list_a = dict(storage_a.list_items())
list_b = dict(storage_b.list_items())
@ -15,7 +37,7 @@ def sync(storage_a, storage_b, status):
for uid in set(list_a).union(set(list_b)):
if uid not in status:
if uid in list_a and uid in list_b: # missing status
status[uid] = (list_a[uid], list_b[uid]) # TODO: might need etag diffing too?
status[uid] = (list_a[uid], list_b[uid]) # TODO: might need some kind of diffing too?
elif uid in list_a and uid not in list_b: # new item in a
prefetch_items_from_a.append(uid)
actions.append(('upload', uid, 'a', 'b'))

View file

@ -1,3 +1,13 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.tests.test_storage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
__version__ = '0.1.0'
from unittest import TestCase
import os
import tempfile

View file

@ -1,3 +1,12 @@
# -*- coding: utf-8 -*-
'''
vdirsyncer.tests.test_sync
~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
from unittest import TestCase
from vdirsyncer.storage.base import Item
from vdirsyncer.storage.memory import MemoryStorage