diff --git a/doc.md b/doc.md
index c5092bf..bf3a7f0 100644
--- a/doc.md
+++ b/doc.md
@@ -31,6 +31,23 @@
Delete file
+
+ User
+
+
+
+ Group
+
+
@@ -429,3 +446,189 @@ None
**Return Type**
A Response Instance
+
+
+## User ##
+
+### Get accounts ###
+**Request Parameters**
+
+None
+
+**Sample Case**
+
+```python
+
+ import seafileapi
+
+ client = seafileapi.connect('http://127.0.0.1:8000', 'test@admin.com', 'password')
+ accounts = client.users.get_accounts()
+```
+
+**Return Type**
+
+A list of dictionnary containing source and email keys.
+
+**Exception**
+
+TBD
+
+### Create account ###
+**Request Parameters**
+
+* email -- email as login name
+* password -- plain text password
+* name -- full text display name
+* groups_names -- list of groups' names to add this user to
+* note -- description / comment / whatever
+* is_staff -- is admin, default False
+* is_active -- can connect, default True
+
+
+**Sample Case**
+
+```python
+
+ import seafileapi
+
+ client = seafileapi.connect('http://127.0.0.1:8000', 'test@admin.com', 'password')
+ accounts = client.users.create_account('test@admin.com', 'password', 'Test user', ['admins'])
+```
+
+**Return Type**
+
+A dictionnary, containing the created user.
+
+**Exception**
+
+TBD
+
+
+### Delete account ###
+**Request Parameters**
+
+* email -- email as login name
+
+
+**Sample Case**
+
+```python
+
+ import seafileapi
+
+ client = seafileapi.connect('http://127.0.0.1:8000', 'test@admin.com', 'password')
+ accounts = client.users.delete_account('test@admin.com')
+```
+
+**Return Type**
+
+TBD
+
+**Exception**
+
+TBD
+
+
+### Add account to group ###
+**Request Parameters**
+
+* username -- email as login name
+* groups_name -- group's name to add this user to
+
+**Sample Case**
+
+```python
+
+ import seafileapi
+
+ client = seafileapi.connect('http://127.0.0.1:8000', 'test@admin.com', 'password')
+ accounts = client.users.add_account_to_group('test@admin.com', 'admins')
+```
+
+**Return Type**
+
+TBD
+
+**Exception**
+
+TBD
+
+
+
+
+## Group ##
+
+### Get groups ###
+**Request Parameters**
+
+None
+
+**Sample Case**
+
+```python
+
+ import seafileapi
+
+ client = seafileapi.connect('http://127.0.0.1:8000', 'test@admin.com', 'password')
+ groups = client.groups.get_groups()
+```
+
+**Return Type**
+
+A list of groups.
+
+**Exception**
+
+TBD
+
+
+
+### Create group ###
+**Request Parameters**
+
+* group_name -- group's name
+
+
+**Sample Case**
+
+```python
+
+ import seafileapi
+
+ client = seafileapi.connect('http://127.0.0.1:8000', 'test@admin.com', 'password')
+ accounts = client.groups.create_group('admins')
+```
+
+**Return Type**
+
+TBD
+
+**Exception**
+
+TBD
+
+
+### Delete group ###
+**Request Parameters**
+
+* group_name -- group's name
+
+
+**Sample Case**
+
+```python
+
+ import seafileapi
+
+ client = seafileapi.connect('http://127.0.0.1:8000', 'test@admin.com', 'password')
+ accounts = client.groups.delete_group('admin')
+```
+
+**Return Type**
+
+TBD
+
+**Exception**
+
+TBD
+
diff --git a/seafileapi/client.py b/seafileapi/client.py
index 9bf79ee..75137de 100644
--- a/seafileapi/client.py
+++ b/seafileapi/client.py
@@ -2,6 +2,9 @@
from seafileapi.utils import urljoin
from seafileapi.exceptions import ClientHttpError
from seafileapi.repos import Repos
+from seafileapi.group import Groups
+from seafileapi.user import Users
+
class SeafileApiClient(object):
"""Wraps seafile web api"""
@@ -15,6 +18,7 @@ def __init__(self, server, username=None, password=None, token=None):
self.repos = Repos(self)
self.groups = Groups(self)
+ self.users = Users(self)
if token is None:
self._get_token()
@@ -43,6 +47,9 @@ def get(self, *args, **kwargs):
def post(self, *args, **kwargs):
return self._send_request('POST', *args, **kwargs)
+ def put(self, *args, **kwargs):
+ return self._send_request('PUT', *args, **kwargs)
+
def delete(self, *args, **kwargs):
return self._send_request('delete', *args, **kwargs)
@@ -57,18 +64,12 @@ def _send_request(self, method, url, *args, **kwargs):
expected = kwargs.pop('expected', 200)
if not hasattr(expected, '__iter__'):
expected = (expected, )
+
resp = requests.request(method, url, *args, **kwargs)
if resp.status_code not in expected:
msg = 'Expected %s, but get %s' % \
(' or '.join(map(str, expected)), resp.status_code)
+ msg += '\n' + resp.content.decode('utf-8')
raise ClientHttpError(resp.status_code, msg)
return resp
-
-
-class Groups(object):
- def __init__(self, client):
- pass
-
- def create_group(self, name):
- pass
diff --git a/seafileapi/files.py b/seafileapi/files.py
index d36f2ea..0ee01de 100644
--- a/seafileapi/files.py
+++ b/seafileapi/files.py
@@ -2,6 +2,7 @@
import os
import posixpath
import re
+import sys
from seafileapi.utils import querystr, utf8lize
ZERO_OBJ_ID = '0000000000000000000000000000000000000000'
@@ -157,12 +158,17 @@ def upload(self, fileobj, filename):
Return a :class:`SeafFile` object of the newly uploaded file.
"""
if isinstance(fileobj, str):
- fileobj = io.BytesIO(fileobj)
+ if sys.version_info.major > 2:
+ fileobj = io.BytesIO(bytes(fileobj, 'UTF-8'))
+ else:
+ fileobj = io.BytesIO(fileobj)
+
upload_url = self._get_upload_link()
files = {
'file': (filename, fileobj),
'parent_dir': self.path,
}
+ # print(files)
self.client.post(upload_url, files=files)
return self.repo.get_file(posixpath.join(self.path, filename))
diff --git a/seafileapi/group.py b/seafileapi/group.py
index 731d7ef..bfeccf1 100644
--- a/seafileapi/group.py
+++ b/seafileapi/group.py
@@ -1,22 +1,87 @@
-
-class Group(object):
- def __init__(self, client, group_id, group_name):
+class Groups(object):
+ def __init__(self, client):
+ """
+ client -- Seafile client object
+ """
self.client = client
- self.group_id = group_id
- self.group_name = group_name
- def list_memebers(self):
- pass
+ def get_groups(self):
+ """
+ Returns list of groups
+ """
+ resp = self.client.get('/api2/groups/')
+ value = resp.json()
+ return value['groups']
+
+# def get_group_members(self, group_name):
+# """
+# Returns list of members of a group
+# """
+# groups = self.get_groups()
+# found = False
+# for i in groups:
+# if i['name'] == group_name:
+# url = '/api2/groups/{}/members/'.format(i['id'])
+# resp = self.client.get(url)
+# found = True
+# break
+# value = resp.json()
+# return value
+
+ def create_group(self, group_name):
+ """
+ Creates group
+
+ group_name -- name
+ """
+ data = {
+ 'group_name': group_name,
+ }
+ resp = self.client.put(
+ '/api2/groups/',
+ data=data,
+ )
+ value = resp.json()
+ return value
+
+ def delete_group(self, group_name):
+ """
+ Delete group
+
+ group_name -- name
+ """
+ url = '/api2/groups/{}'.format(self.get_id_from_group_name(group_name))
+ resp = self.client.delete(url)
+ value = resp.json()
+ return value
- def delete(self):
- pass
+ def get_id_from_group_name(self, group_name):
+ groups = self.get_groups()
+ for i in groups:
+ if i['name'] == group_name:
+ return i['id']
- def add_member(self, username):
- pass
+ raise ValueError('Group {} not found'.format(group_name))
- def remove_member(self, username):
- pass
- def list_group_repos(self):
- pass
+# class Group(object):
+# def __init__(self, client, group_id, group_name):
+# self.client = client
+# self.group_id = group_id
+# self.group_name = group_name
+#
+# def list_memebers(self):
+# pass
+#
+# def delete(self):
+# pass
+#
+# def add_member(self, username):
+# pass
+#
+# def remove_member(self, username):
+# pass
+#
+# def list_group_repos(self):
+# pass
diff --git a/seafileapi/repo.py b/seafileapi/repo.py
index ded895e..ab7dac5 100644
--- a/seafileapi/repo.py
+++ b/seafileapi/repo.py
@@ -1,4 +1,8 @@
-from urllib import urlencode
+import sys
+if sys.version_info.major > 2:
+ from urllib.parse import urlencode
+else:
+ from urllib import urlencode
from seafileapi.utils import utf8lize
from seafileapi.files import SeafDir, SeafFile
from seafileapi.utils import raise_does_not_exist
diff --git a/seafileapi/user.py b/seafileapi/user.py
new file mode 100644
index 0000000..2d1101c
--- /dev/null
+++ b/seafileapi/user.py
@@ -0,0 +1,101 @@
+from group import Group
+
+
+class Users(object):
+ def __init__(self, client):
+ """
+ client -- Seafile client object
+ """
+ self.client = client
+
+ def get_accounts(self):
+ """
+ Returns accounts list such as :
+
+ [{'source': 'DB', 'email': 'test@seafiletest.com'},
+ {'source': 'DB', 'email': 'admin@seafiletest.com'}]
+ """
+ url = '/api2/accounts/'
+ resp = self.client.get(url)
+ return resp.json()
+
+ def create_account(self, email, password, groups_names=[], name='', note='', is_staff=False, is_active=True):
+ """
+ Creates account
+
+ email -- email as login name
+ password -- plain text password
+ name -- full text display name
+ groups_names -- list of groups' names to add this user to
+ note -- description / comment / whatever
+ is_staff -- is admin, default False
+ is_active -- can connect, default True
+ """
+ data = {
+ 'password': password,
+ 'is_staff': is_staff,
+ 'is_active': is_active,
+ 'name': name[0:64],
+ 'note': note,
+ # 'storage': 'DB',
+ }
+ url = '/api2/accounts/{}/'.format(email)
+ resp = self.client.put(
+ url,
+ data=data,
+ expected=[200, 201],
+ )
+ user = resp.json()
+ for group_name in groups_names:
+ self.add_user_to_group(username=email, group_name=group_name)
+
+ return user
+
+ def delete_account(self, email):
+ """
+ Delete account
+
+ email -- email as login name
+ """
+ url = '/api2/accounts/{}/'.format(email)
+ resp = self.client.delete(url)
+ value = resp.json()
+ return value
+
+ def add_account_to_group(self, username, group_name):
+ """
+ Adds given username (email) to group (by group name)
+
+ username -- email / login name
+ group_name -- group to add user to
+ """
+ data = {
+ 'user_name': username,
+ }
+ url = '/api2/groups/{}/members/'.format(self.__get_id_from_group_name__(group_name))
+ resp = self.client.put(
+ url, data=data,
+ )
+
+ return resp.json()
+
+ def __get_groups__(self):
+ manage_group = Group(self.client)
+ return manage_group.get_groups()
+
+ def __get_id_from_group_name__(self, group_name):
+ manage_group = Group(self.client)
+ return manage_group.get_id_from_group_name(group_name)
+
+
+
+"""
+import __init__
+c=__init__.connect('http://127.0.0.1:8000', 'admin@seafiletest.com', 'adminadmin')
+from user import User
+u=User(c)
+u.create_account('none5@xael.org', 'node99', ['test'], 'Alexandre')
+# u.delete_group('TEST2')
+# u.delete_account('none4@xael.org')
+u.get_group_members('test')
+"""
diff --git a/seafileapi/utils.py b/seafileapi/utils.py
index b529880..e4f4583 100644
--- a/seafileapi/utils.py
+++ b/seafileapi/utils.py
@@ -1,7 +1,13 @@
import string
import random
from functools import wraps
-from urllib import urlencode
+
+import sys
+if sys.version_info.major > 2:
+ from urllib.parse import urlencode
+else:
+ from urllib import urlencode
+
from seafileapi.exceptions import ClientHttpError, DoesNotExist
def randstring(length=0):
@@ -28,7 +34,7 @@ def decorator(func):
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
- except ClientHttpError, e:
+ except ClientHttpError as e:
if e.code == 404:
raise DoesNotExist(msg)
else:
@@ -37,8 +43,13 @@ def wrapped(*args, **kwargs):
return decorator
def to_utf8(obj):
- if isinstance(obj, unicode):
- return obj.encode('utf-8')
+ if sys.version_info.major > 2:
+ return obj
+ else:
+ unicode_type = unicode
+ if isinstance(obj, unicode_type):
+ return obj.encode('utf-8')
+
return obj
def querystr(**kwargs):
@@ -46,12 +57,19 @@ def querystr(**kwargs):
def utf8lize(obj):
if isinstance(obj, dict):
- return {k: to_utf8(v) for k, v in obj.iteritems()}
+ if sys.version_info.major > 2:
+ return {k: to_utf8(v) for k, v in obj.items()}
+ else:
+ return {k: to_utf8(v) for k, v in obj.iteritems()}
if isinstance(obj, list):
return [to_utf8(x) for x in ob]
- if instance(obj, unicode):
- return obj.encode('utf-8')
+ if sys.version_info.major > 2:
+ return obj
+ else:
+ unicode_type = unicode
+ if instance(obj, unicode_type):
+ return obj.encode('utf-8')
return obj
diff --git a/setup.py b/setup.py
index d2165df..095c10a 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
-__version__ = '0.1.1'
+__version__ = '0.3.0'
setup(name='seafileapi',
diff --git a/tests/test_files.py b/tests/test_files.py
index 5509da0..39f907e 100644
--- a/tests/test_files.py
+++ b/tests/test_files.py
@@ -1,6 +1,7 @@
#coding: UTF-8
import os
+import sys
import pytest
from tests.utils import randstring, datafile, filesize
@@ -59,10 +60,16 @@ def test_upload_file(repo, parentpath):
fname = 'aliedit.tar.gz'
fpath = datafile(fname)
- with open(fpath, 'r') as fp:
+
+ if sys.version_info.major > 2:
+ mode = 'rb'
+ else:
+ mode = 'r'
+
+ with open(fpath, mode) as fp:
testfile = parentdir.upload(fp, fname)
- with open(fpath, 'r') as fp:
+ with open(fpath, mode) as fp:
fcontent = fp.read()
assert testfile.size == filesize(fpath)
@@ -85,7 +92,11 @@ def test_upload_string_as_file_content(repo):
# test pass as string as file content when upload file
rootdir = repo.get_dir('/')
fname = u'testfile-%s' % randstring()
- fcontent = 'line 1\nline 2\n\r'
+ if sys.version_info.major > 2:
+ fcontent = b'line 1\nline 2\n\r'
+ else:
+ fcontent = 'line 1\nline 2\n\r'
+
f = rootdir.upload(fcontent, fname)
assert f.name == fname
assert f.get_content() == fcontent
diff --git a/tests/utils.py b/tests/utils.py
index 63cc8d6..de0d5ab 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -3,7 +3,7 @@
import random
def randstring(length=12):
- return ''.join(random.choice(string.lowercase) for i in range(length))
+ return ''.join(random.choice(string.ascii_lowercase) for i in range(length))
def datafile(filename):
return os.path.join(os.path.dirname(__file__), 'data', filename)