1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-04-27 02:51:00 +00:00

Python3 master (#4076)

* delete thridpart/social_django

* delete social_django in seahub/urls.py

* delete social_django in seahub/settings.py

* delete seahub/notifications/management/commands/send_wxwork_notices.py

* delete social_django in code annotation

* delete seahub/social_core

* delete tests/seahub/social_core

* delete social_core in seahub/urls.py

* delete social_core in seahub/settings.py

* change app_label to auth in SocialAuthUser model

* 2to3 asserts

* 2to3 basestring

* 2to3 dict

* 2to3 except

* 2to3 filter

* 2to3 future

* 2to3 has_key

* 2to3 idioms

* 2to3 import

* 2to3 imports

* 2to3 long

* 2to3 map

* 2to3 next

* 2to3 numliterals

* 2to3 print

* 2to3 raise

* 2to3 raw_input

* 2to3 reduce

* 2to3 reload

* 2to3 set_literal

* 2to3 unicode

* 2to3 urllib

* 2to3 ws_comma

* 2to3 xrange

* 2to3 zip

* add pymysql in __init__.py

* fix encode and decode in seahub/cconvert.py

* fix seafserv_rpc.is_passwd_set in seahub/views/__init__.py

* fix smart_unicode to smart_text

* fix force_unicode to force_text

* delete seaserv.get_session_info

* delete seaserv.ccnet_rpc

* fix indent error in seahub/auth/middleware.py

* update dev-requirements

* update test-requirements

* update requirements

* fix StringIO to BytesIO in thumbnail

* fix seaserv.list_inner_pub_repos to seafile_api.get_inner_pub_repo_list

* fix seaserv.list_org_inner_pub_repos to seafile_api.list_org_inner_pub_repos

* add logger in seahub/utils/__init__.py

* fix sort cmp in seahub/views/__init__.py

* fix sort cmp in seahub/base/management/commands/export_file_access_log.py

* fix sort cmp in seahub/api2/endpoints/repo_trash.py

* fix sort cmp in seahub/api2/endpoints/shared_repos.py

* fix sort cmp in seahub/api2/endpoints/shared_folders.py

* fix sort cmp in seahub/wiki/views.py

* fix sort cmp in seahub/api2/endpoints/wiki_pages.py

* fix sort cmp in seahub/api2/endpoints/group_libraries.py

* fix sort cmp in seahub/base/models.py

* fix sort cmp in seahub/api2/endpoints/upload_links.py

* fix sort cmp in seahub/views/ajax.py

* fix sort cmp in seahub/api2/views.py

* fix sort cmp in seahub/views/wiki.py

* fix sort cmp in seahub/api2/endpoints/repos.py

* fix sort cmp in seahub/api2/endpoints/starred_items.py

* fix sort cmp in seahub/views/file.py

* fix sort cmp in seahub/api2/endpoints/dir.py

* fix sort cmp in seahub/api2/endpoints/share_links.py

* fix cmp to cmp_to_key in seahub/api2/endpoints/admin/device_trusted_ip.py

* fix cmp to cmp_to_key in tests/api/endpoints/admin/test_device_trusted_ip.py

* delete encode('utf-8') in seafile_api.list_dir_by_commit_and_path

* delete encode('utf-8') in is_file_starred

* delete encode('utf-8') in seafile_api.list_dir_by_path

* delete path.encode('utf-8') in seahub/views/file.py

* fix os.write to add encode('utf-8')

* add encode('utf-8') for hashlib

* add encode('utf-8') for hmac

* fix with open(file, 'wb') for binary file

* fix encode and decode in seahub/utils/hasher.py

* fix next in thirdpart/shibboleth/views.py

* fix next in seahub/profile/views.py

* fix next in seahub/notifications/views.py

* fix next in seahub/institutions/views.py

* fix next in seahub/options/views.py

* fix next in seahub/share/views.py

* fix next in seahub/avatar/views.py

* fix next in seahub/views/__init__.py

* fix next in seahub/group/views.py

* fix next in seahub/views/wiki.py

* fix next in seahub/views/sysadmin.py

* fix next in seahub/views/file.py

* fix string.lowercase to string.ascii_lowercase in test

* fix open file add 'rb' in test

* fix self.user.username in test

* add migrations in file_participants

* fix list_org_inner_pub_repos to list_org_inner_pub_repos_by_owner

* fix from seaserv import is_passwd_set to seafile_api.is_password_set

* fix assert bytes resp.content in test

* fix seafile_api.get_inner_pub_repo_list to seafile_api.list_inner_pub_repos_by_owner

* fix seafile_api.is_passwd_set to seafile_api.is_password_set

* fix AccountsApiTest assert length

* rewrite sort_devices cmp to operator.lt

* fix bytes + str in seahub/api2/views.py

* fix assert bytes resp.content in test

* fix hashlib encode in seahub/thirdpart/registration/models.py

* change app_label to base in SocialAuthUser

* fix base64 encode in seahub/base/database_storage/database_storage.py

* fix assert bytes resp.content

* remove path.decode in def mkstemp()

* remove path.decode in FpathToLinkTest

* remove str decode in FileTagTest

* remove mock_write_xls.assert_called_once() in SysUserAdminExportExcelTest

* fix urllib assert in FilesApiTest

* fix link fields in FileCommentsTest

* fix get_related_users_by_repo()

* fix assert list in GetRepoSharedUsersTest

* fix create user in AccountTest

* fix repeated key in dict seahub/api2/views.py

* add drone.yml

* update nginx conf in test

* update test conf in test

* update dist and push after test success

* update drone conf to dist and push

* fix assert in BeSharedReposTest

* fix seafile_api.list_org_inner_pub_repos_by_owner(org_id, username) to seafile_api.list_org_inner_pub_repos(org_id)

* fix seafile_api.list_inner_pub_repos_by_owner(username) to seafile_api.get_inner_pub_repo_list()

* update pyjwt requirement

* update dist branch in drone

* add SKIP in dist and push

* fix StringIO to BytesIO in seahub/avatar/models.py

* fix if org_id > 0 to if org_id and org_id > 0

* remove payment

* fix StringIO to BytesIO in seahub/base/database_storage/database_storage.py

* fix send_message to seafile_api.publish_event in seahub/drafts/utils.py

* fix send_message to seafile_api.publish_event in seahub/api2/views.py

* fix send_message to seafile_api.publish_event in seahub/api2/endpoints/repos.py

* fix send_message to seafile_api.publish_event in seahub/views/file.py

* fix send_message to seafile_api.publish_event in seahub/utils/__init__.py

* fix image_file.read encode in seahub/base/database_storage/database_storage.py

* fix DatabaseStorageTest

* remove .travis.yml

* drone branch include master
This commit is contained in:
sniper-py 2019-09-11 11:46:43 +08:00 committed by Daniel Pan
parent 835015c3a8
commit 99a9ece04e
364 changed files with 1983 additions and 4138 deletions

21
.drone.yml Normal file
View File

@ -0,0 +1,21 @@
pipeline:
build:
image: docker.seafile.top/drone/seafile-pro-builder:v4
pull: true
secrets: [ github_token, npm_token, travis ]
when:
branch:
event: [ push, pull_request ]
include: [ master, python3-master ]
exclude: []
commands:
- cd /tmp/seafile-test-deploy && git fetch origin python3:python3 && git checkout python3
- ./bootstrap.sh && cd -
- export CCNET_CONF_DIR=/tmp/ccnet SEAFILE_CONF_DIR=/tmp/seafile-data
- echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
- cd /drone/src/github.com/haiwen/seahub
- ./tests/install-deps.sh
- pip install -r test-requirements.txt
- .travis/test_seahub_changes.sh; rc=$?; if test "$rc" -eq 0; then ./tests/seahubtests.sh init && ./tests/seahubtests.sh runserver && ./tests/seahubtests.sh test; else true; fi
- if test $DRONE_COMMIT_BRANCH = "master"; then .travis/dist_and_push.sh; else true; fi

View File

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
: ${PYTHON=python} : ${PYTHON=python3}
set -e set -e
if [[ ${TRAVIS} != "" ]]; then if [[ ${TRAVIS} != "" ]]; then
@ -7,23 +7,25 @@ if [[ ${TRAVIS} != "" ]]; then
fi fi
set -x set -x
SEAHUB_TESTSDIR=$(python -c "import os; print os.path.dirname(os.path.realpath('$0'))") SEAHUB_TESTSDIR=$(python -c "import os; print(os.path.dirname(os.path.realpath('$0')))")
SEAHUB_SRCDIR=$(dirname "${SEAHUB_TESTSDIR}") SEAHUB_SRCDIR=$(dirname "${SEAHUB_TESTSDIR}")
export PYTHONPATH="/usr/local/lib/python2.7/site-packages:/usr/lib/python2.7/site-packages:${SEAHUB_SRCDIR}/thirdpart:${PYTHONPATH}" export PYTHONPATH="/usr/local/lib/python3.7/site-packages:/usr/local/lib/python3.7/dist-packages:/usr/lib/python3.7/site-packages:/usr/lib/python3.7/dist-packages:${SEAHUB_SRCDIR}/thirdpart:${PYTHONPATH}"
cd "$SEAHUB_SRCDIR" cd "$SEAHUB_SRCDIR"
set +x set +x
function commit_dist_files() { function commit_dist_files() {
git checkout -b dist-$TRAVIS_BRANCH git checkout -b dist-$DRONE_COMMIT_BRANCH
git add -u . && git add -A media/assets && git add -A static/scripts && git add -A frontend && git add -A locale git add -u . && git add -A media/assets && git add -A static/scripts && git add -A frontend && git add -A locale
git commit -m "[dist] Travis build: #$TRAVIS_BUILD_NUMBER, based on commit $TRAVIS_COMMIT." -m "$TRAVIS_COMMIT_MESSAGE" git config --global user.email "drone@seafile.com"
git config --global user.name "Drone CI"
git commit -m "[dist][CI SKIP] Drone CI build: #$DRONE_BUILD_NUMBER, based on commit $DRONE_COMMIT." -m "$DRONE_COMMIT_MESSAGE"
} }
function upload_files() { function upload_files() {
echo 'push dist to seahub' echo 'push dist to seahub'
git remote add token-origin https://imwhatiam:${GITHUB_PERSONAL_ACCESS_TOKEN}@github.com/haiwen/seahub.git git remote add token-origin https://$GITHUB_TOKEN@github.com/haiwen/seahub.git
git push -f token-origin dist-$TRAVIS_BRANCH git push -f token-origin dist-$DRONE_COMMIT_BRANCH
} }
function make_dist() { function make_dist() {

View File

@ -5,5 +5,5 @@ transifex-client
raven==5.0.0 raven==5.0.0
mysqlclient==1.3.12 mysqlclient==1.3.12
pycryptodome==3.7.2 pycryptodome
psd-tools==1.4 psd-tools==1.4

View File

@ -19,15 +19,15 @@ def check(path):
def do_update(filename): def do_update(filename):
if 'migrations' in filename: if 'migrations' in filename:
print 'skip migration file: %s' % filename print('skip migration file: %s' % filename)
return return
with open(filename) as f: with open(filename) as f:
# try read first line of file # try read first line of file
try: try:
head = [next(f) for x in xrange(1)] head = [next(f) for x in range(1)]
except StopIteration: except StopIteration:
print '%s is empty, skip' % filename print('%s is empty, skip' % filename)
return return
copy_str = '# Copyright (c) 2012-2016 Seafile Ltd.' copy_str = '# Copyright (c) 2012-2016 Seafile Ltd.'
@ -39,11 +39,11 @@ def do_update(filename):
need_update = False need_update = False
if not need_update: if not need_update:
print '%s is ok.' % filename print('%s is ok.' % filename)
return return
line_prepender(filename, copy_str) line_prepender(filename, copy_str)
print '%s Done.' % filename print('%s Done.' % filename)
def path_to_pyfile_list(path): def path_to_pyfile_list(path):
is_dir = False is_dir = False
@ -78,7 +78,7 @@ def do_check(filename):
with open(filename) as f: with open(filename) as f:
# try read first line of file # try read first line of file
try: try:
head = [next(f) for x in xrange(1)] head = [next(f) for x in range(1)]
except StopIteration: except StopIteration:
return return
@ -89,4 +89,4 @@ def do_check(filename):
need_update = False need_update = False
if need_update: if need_update:
print 'No copyright info in %s.' % filename print('No copyright info in %s.' % filename)

View File

@ -18,7 +18,7 @@ def make(default=True, lang='en'):
b2 = f.readline() b2 = f.readline()
if b1 != b2: if b1 != b2:
print 'Error: inconsistent Git branch names.' print('Error: inconsistent Git branch names.')
return return
@ -63,7 +63,7 @@ def compile():
def _inplace_change(filename, old_string, new_string): def _inplace_change(filename, old_string, new_string):
s = open(filename).read() s = open(filename).read()
if old_string in s: if old_string in s:
print(green('Changing "{old_string}" to "{new_string}" in "{filename}"'.format(**locals()))) print((green('Changing "{old_string}" to "{new_string}" in "{filename}"'.format(**locals()))))
s = s.replace(old_string, new_string) s = s.replace(old_string, new_string)
f = open(filename, 'w') f = open(filename, 'w')
f.write(s) f.write(s)
@ -71,4 +71,4 @@ def _inplace_change(filename, old_string, new_string):
f.close() f.close()
def _debug(msg): def _debug(msg):
print(red('Running: {msg}'.format(**locals()))) print((red('Running: {msg}'.format(**locals()))))

View File

@ -1,23 +1,20 @@
python-dateutil==2.7.0 Django==1.11.23
python-memcached==1.57 future
chardet==3.0.4 captcha
six==1.11.0 django-compressor
Pillow==4.3.0 django-statici18n
Django==1.11.15 django-constance
django-compressor==2.2 django-post_office
git+git://github.com/haiwen/django-post_office.git@2312cf240363721f737b5ac8eb86ab8cb255938f#egg=django-post_office django-webpack_loader
django-statici18n==1.7.0 gunicorn
djangorestframework==3.3.3 pymysql
git+git://github.com/haiwen/django-constance.git@8508ff29141732190faff51d5c2b5474da297732#egg=django-constance[database] django-picklefield
openpyxl==2.3.0 openpyxl
pytz==2015.7 qrcode
django-formtools==2.1 django-formtools
qrcode==5.3 django-simple-captcha
requests==2.20.1 djangorestframework
requests_oauthlib==0.8.0 python-dateutil
django-simple-captcha==0.5.6 requests
gunicorn==19.8.1 pillow
django-webpack-loader==0.6.0 pyjwt
git+git://github.com/haiwen/python-cas.git@ffc49235fd7cc32c4fdda5acfa3707e1405881df#egg=python_cas
futures==3.2.0
social-auth-core==1.7.0

View File

@ -1,7 +1,9 @@
# Copyright (c) 2012-2016 Seafile Ltd. # Copyright (c) 2012-2016 Seafile Ltd.
from signals import repo_created, repo_deleted, clean_up_repo_trash, \ import pymysql
pymysql.install_as_MySQLdb()
from .signals import repo_created, repo_deleted, clean_up_repo_trash, \
repo_restored repo_restored
from handlers import repo_created_cb, repo_deleted_cb, clean_up_repo_trash_cb, \ from .handlers import repo_created_cb, repo_deleted_cb, clean_up_repo_trash_cb, \
repo_restored_cb repo_restored_cb
repo_created.connect(repo_created_cb) repo_created.connect(repo_created_cb)

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models
import datetime import datetime

View File

@ -52,7 +52,7 @@ class AddressBookGroupsSearchMember(APIView):
email_list += search_user_from_ccnet(q) email_list += search_user_from_ccnet(q)
email_list += search_user_from_profile(q) email_list += search_user_from_profile(q)
# remove duplicate emails # remove duplicate emails
email_list = {}.fromkeys(email_list).keys() email_list = list({}.fromkeys(email_list).keys())
try: try:
# get all members in current group and its sub groups # get all members in current group and its sub groups
@ -64,7 +64,7 @@ class AddressBookGroupsSearchMember(APIView):
group_email_list = [m.user_name for m in all_members] group_email_list = [m.user_name for m in all_members]
# remove duplicate emails # remove duplicate emails
group_email_list = {}.fromkeys(group_email_list).keys() group_email_list = list({}.fromkeys(group_email_list).keys())
email_result = [] email_result = []
for email in group_email_list: for email in group_email_list:

View File

@ -192,11 +192,11 @@ class Account(APIView):
if name is not None: if name is not None:
if len(name) > 64: if len(name) > 64:
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u'Name is too long (maximum is 64 characters)')) _('Name is too long (maximum is 64 characters)'))
if "/" in name: if "/" in name:
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u"Name should not include '/'.")) _("Name should not include '/'."))
# argument check for list_in_address_book # argument check for list_in_address_book
list_in_address_book = request.data.get("list_in_address_book", None) list_in_address_book = request.data.get("list_in_address_book", None)
@ -211,18 +211,18 @@ class Account(APIView):
loginid = loginid.strip() loginid = loginid.strip()
if loginid == "": if loginid == "":
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u"Login id can't be empty")) _("Login id can't be empty"))
usernamebyloginid = Profile.objects.get_username_by_login_id(loginid) usernamebyloginid = Profile.objects.get_username_by_login_id(loginid)
if usernamebyloginid is not None: if usernamebyloginid is not None:
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u"Login id %s already exists." % loginid)) _("Login id %s already exists." % loginid))
# argument check for department # argument check for department
department = request.data.get("department", None) department = request.data.get("department", None)
if department is not None: if department is not None:
if len(department) > 512: if len(department) > 512:
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u'Department is too long (maximum is 512 characters)')) _('Department is too long (maximum is 512 characters)'))
# argument check for institution # argument check for institution
institution = request.data.get("institution", None) institution = request.data.get("institution", None)
@ -256,7 +256,7 @@ class Account(APIView):
get_file_size_unit('MB') get_file_size_unit('MB')
if space_quota_mb > org_quota_mb: if space_quota_mb > org_quota_mb:
return api_error(status.HTTP_400_BAD_REQUEST, \ return api_error(status.HTTP_400_BAD_REQUEST, \
_(u'Failed to set quota: maximum quota is %d MB' % org_quota_mb)) _('Failed to set quota: maximum quota is %d MB' % org_quota_mb))
# argument check for is_trial # argument check for is_trial
is_trial = request.data.get("is_trial", None) is_trial = request.data.get("is_trial", None)

View File

@ -77,14 +77,14 @@ class AdminAddressBookGroups(APIView):
# Check whether group name is validate. # Check whether group name is validate.
if not validate_group_name(group_name): if not validate_group_name(group_name):
error_msg = _(u'Name can only contain letters, numbers, blank, hyphen or underscore.') error_msg = _('Name can only contain letters, numbers, blank, hyphen or underscore.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# Check whether group name is duplicated. # Check whether group name is duplicated.
pattern_matched_groups = ccnet_api.search_groups(group_name, -1, -1) pattern_matched_groups = ccnet_api.search_groups(group_name, -1, -1)
for group in pattern_matched_groups: for group in pattern_matched_groups:
if group.group_name == group_name: if group.group_name == group_name:
error_msg = _(u'There is already a group with that name.') error_msg = _('There is already a group with that name.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# Group owner is 'system admin' # Group owner is 'system admin'
@ -228,11 +228,11 @@ class AdminAddressBookGroup(APIView):
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if has_repo: if has_repo:
error_msg = _(u'There are libraries in this department.') error_msg = _('There are libraries in this department.')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
if len(child_groups) > 0: if len(child_groups) > 0:
error_msg = _(u'There are sub-departments in this department.') error_msg = _('There are sub-departments in this department.')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try: try:

View File

@ -1,4 +1,5 @@
# Copyright (c) 2012-2016 Seafile Ltd. # Copyright (c) 2012-2016 Seafile Ltd.
from functools import cmp_to_key
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAdminUser from rest_framework.permissions import IsAdminUser
@ -83,7 +84,7 @@ class AdminDeviceTrustedIP(APIView):
@check_parameter @check_parameter
def get(self, request, format=None): def get(self, request, format=None):
ip_list = [ip.to_dict() for ip in TrustedIP.objects.all()] ip_list = [ip.to_dict() for ip in TrustedIP.objects.all()]
ip_list = sorted(ip_list, cmp=cmp_ip) ip_list = sorted(ip_list, key=cmp_to_key(cmp_ip))
return Response(ip_list) return Response(ip_list)
@check_parameter @check_parameter

View File

@ -56,7 +56,7 @@ class AdminFavicon(APIView):
CUSTOM_FAVICON_PATH) CUSTOM_FAVICON_PATH)
# save favicon file to custom dir # save favicon file to custom dir
with open(custom_favicon_file, 'w') as fd: with open(custom_favicon_file, 'wb') as fd:
fd.write(favicon_file.read()) fd.write(favicon_file.read())
custom_symlink = os.path.join(MEDIA_ROOT, custom_symlink = os.path.join(MEDIA_ROOT,

View File

@ -55,7 +55,7 @@ class AdminFileScanRecords(APIView):
else: else:
record["repo_name"] = repo.name record["repo_name"] = repo.name
record_detail = json.loads(record['detail']) record_detail = json.loads(record['detail'])
detail_dict = record_detail.values()[0] detail_dict = list(record_detail.values())[0]
detail = dict() detail = dict()
detail["suggestion"] = detail_dict["suggestion"] detail["suggestion"] = detail_dict["suggestion"]
detail["label"] = detail_dict["label"] detail["label"] = detail_dict["label"]

View File

@ -100,7 +100,7 @@ class AdminGroupOwnedLibraries(APIView):
storage_id=storage_id) storage_id=storage_id)
else: else:
# STORAGE_CLASS_MAPPING_POLICY == 'REPO_ID_MAPPING' # STORAGE_CLASS_MAPPING_POLICY == 'REPO_ID_MAPPING'
if org_id > 0: if org_id and org_id > 0:
repo_id = seafile_api.org_add_group_owned_repo( repo_id = seafile_api.org_add_group_owned_repo(
org_id, group_id, repo_name, permission, password, org_id, group_id, repo_name, permission, password,
ENCRYPTED_LIBRARY_VERSION) ENCRYPTED_LIBRARY_VERSION)
@ -109,7 +109,7 @@ class AdminGroupOwnedLibraries(APIView):
group_id, repo_name, permission, password, group_id, repo_name, permission, password,
ENCRYPTED_LIBRARY_VERSION) ENCRYPTED_LIBRARY_VERSION)
else: else:
if org_id > 0: if org_id and org_id > 0:
repo_id = seafile_api.org_add_group_owned_repo( repo_id = seafile_api.org_add_group_owned_repo(
org_id, group_id, repo_name, permission, password, org_id, group_id, repo_name, permission, password,
ENCRYPTED_LIBRARY_VERSION) ENCRYPTED_LIBRARY_VERSION)

View File

@ -117,14 +117,14 @@ class AdminGroups(APIView):
group_name = group_name.strip() group_name = group_name.strip()
# Check whether group name is validate. # Check whether group name is validate.
if not validate_group_name(group_name): if not validate_group_name(group_name):
error_msg = _(u'Group name can only contain letters, numbers, blank, hyphen, dot, single quote or underscore') error_msg = _('Group name can only contain letters, numbers, blank, hyphen, dot, single quote or underscore')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# Check whether group name is duplicated. # Check whether group name is duplicated.
pattern_matched_groups = ccnet_api.search_groups(group_name, -1, -1) pattern_matched_groups = ccnet_api.search_groups(group_name, -1, -1)
for group in pattern_matched_groups: for group in pattern_matched_groups:
if group.group_name == group_name: if group.group_name == group_name:
error_msg = _(u'There is already a group with that name.') error_msg = _('There is already a group with that name.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
group_owner = request.data.get('group_owner', '') group_owner = request.data.get('group_owner', '')
@ -200,7 +200,7 @@ class AdminGroup(APIView):
old_owner = group.creator_name old_owner = group.creator_name
if new_owner == old_owner: if new_owner == old_owner:
error_msg = _(u'User %s is already group owner.') % new_owner error_msg = _('User %s is already group owner.') % new_owner
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# transfer a group # transfer a group

View File

@ -138,8 +138,8 @@ class AdminLibraries(APIView):
has_next_page = False has_next_page = False
default_repo_id = get_system_default_repo_id() default_repo_id = get_system_default_repo_id()
repos_all = filter(lambda r: not r.is_virtual, repos_all) repos_all = [r for r in repos_all if not r.is_virtual]
repos_all = filter(lambda r: r.repo_id != default_repo_id, repos_all) repos_all = [r for r in repos_all if r.repo_id != default_repo_id]
return_results = [] return_results = []
@ -253,7 +253,7 @@ class AdminLibrary(APIView):
try: try:
org_id = seafile_api.get_org_id_by_repo_id(repo_id) org_id = seafile_api.get_org_id_by_repo_id(repo_id)
related_usernames = get_related_users_by_repo(repo_id, related_usernames = get_related_users_by_repo(repo_id,
org_id if org_id > 0 else None) org_id if org_id and org_id > 0 else None)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
org_id = -1 org_id = -1
@ -342,7 +342,7 @@ class AdminLibrary(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not new_owner_obj.permissions.can_add_repo(): if not new_owner_obj.permissions.can_add_repo():
error_msg = _(u'Transfer failed: role of %s is %s, can not add library.') % \ error_msg = _('Transfer failed: role of %s is %s, can not add library.') % \
(new_owner, new_owner_obj.role) (new_owner, new_owner_obj.role)
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
@ -363,7 +363,7 @@ class AdminLibrary(APIView):
repo_owner = seafile_api.get_repo_owner(repo_id) repo_owner = seafile_api.get_repo_owner(repo_id)
if new_owner == repo_owner: if new_owner == repo_owner:
error_msg = _(u"Library can not be transferred to owner.") error_msg = _("Library can not be transferred to owner.")
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# get repo shared to user/group list # get repo shared to user/group list

View File

@ -46,7 +46,7 @@ class AdminLicense(APIView):
error_msg = 'path %s invalid.' % LICENSE_PATH error_msg = 'path %s invalid.' % LICENSE_PATH
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
with open(LICENSE_PATH, 'w') as fd: with open(LICENSE_PATH, 'wb') as fd:
fd.write(license_file.read()) fd.write(license_file.read())
ccnet_api.reload_license() ccnet_api.reload_license()

View File

@ -56,7 +56,7 @@ class AdminLoginBgImage(APIView):
custom_login_bg_image_file = os.path.join(SEAHUB_DATA_ROOT, custom_login_bg_image_file = os.path.join(SEAHUB_DATA_ROOT,
custom_login_bg_image_path) custom_login_bg_image_path)
# save login background image file to custom dir # save login background image file to custom dir
with open(custom_login_bg_image_file, 'w') as fd: with open(custom_login_bg_image_file, 'wb') as fd:
fd.write(image_file.read()) fd.write(image_file.read())
custom_symlink = os.path.join(MEDIA_ROOT, custom_symlink = os.path.join(MEDIA_ROOT,

View File

@ -27,7 +27,7 @@ class AdminOrgStatsTraffic(APIView):
'link-file-upload', 'link-file-download'] 'link-file-upload', 'link-file-download']
init_count = [0] * 6 init_count = [0] * 6
init_data = get_init_data(start_time, end_time, init_data = get_init_data(start_time, end_time,
dict(zip(op_type_list, init_count))) dict(list(zip(op_type_list, init_count))))
for e in get_org_traffic_by_day(org_id, start_time, end_time, for e in get_org_traffic_by_day(org_id, start_time, end_time,
get_time_offset()): get_time_offset()):
@ -35,7 +35,7 @@ class AdminOrgStatsTraffic(APIView):
init_data[dt].update({op_type: count}) init_data[dt].update({op_type: count})
res_data = [] res_data = []
for k, v in init_data.items(): for k, v in list(init_data.items()):
res = {'datetime': datetime_to_isoformat_timestr(k)} res = {'datetime': datetime_to_isoformat_timestr(k)}
res.update(v) res.update(v)
res_data.append(res) res_data.append(res)

View File

@ -177,7 +177,7 @@ class AdminShares(APIView):
if repo_owner == email: if repo_owner == email:
result['failed'].append({ result['failed'].append({
'user_email': email, 'user_email': email,
'error_msg': _(u'User %s is already library owner.') % email 'error_msg': _('User %s is already library owner.') % email
}) })
continue continue
@ -203,7 +203,7 @@ class AdminShares(APIView):
if has_shared_to_user(repo.repo_id, path, email): if has_shared_to_user(repo.repo_id, path, email):
result['failed'].append({ result['failed'].append({
'email': email, 'email': email,
'error_msg': _(u'This item has been shared to %s.') % email 'error_msg': _('This item has been shared to %s.') % email
}) })
continue continue
@ -260,7 +260,7 @@ class AdminShares(APIView):
if has_shared_to_group(repo.repo_id, path, group_id): if has_shared_to_group(repo.repo_id, path, group_id):
result['failed'].append({ result['failed'].append({
'group_name': group.group_name, 'group_name': group.group_name,
'error_msg': _(u'This item has been shared to %s.') % group.group_name 'error_msg': _('This item has been shared to %s.') % group.group_name
}) })
continue continue

View File

@ -98,7 +98,7 @@ class FileOperationsView(APIView):
ops_modified_dict[e[0]] = e[2] ops_modified_dict[e[0]] = e[2]
res_data = [] res_data = []
for k, v in ops_added_dict.items(): for k, v in list(ops_added_dict.items()):
res_data.append({'datetime': datetime_to_isoformat_timestr(k), res_data.append({'datetime': datetime_to_isoformat_timestr(k),
'added': v, 'added': v,
'visited': ops_visited_dict[k], 'visited': ops_visited_dict[k],
@ -120,7 +120,7 @@ class TotalStorageView(APIView):
init_data = get_init_data(start_time, end_time) init_data = get_init_data(start_time, end_time)
for e in data: for e in data:
init_data[e[0]] = e[1] init_data[e[0]] = e[1]
for k, v in init_data.items(): for k, v in list(init_data.items()):
res_data.append({'datetime': datetime_to_isoformat_timestr(k), 'total_storage': v}) res_data.append({'datetime': datetime_to_isoformat_timestr(k), 'total_storage': v})
return Response(sorted(res_data, key=lambda x: x['datetime'])) return Response(sorted(res_data, key=lambda x: x['datetime']))
@ -139,7 +139,7 @@ class ActiveUsersView(APIView):
init_data = get_init_data(start_time, end_time) init_data = get_init_data(start_time, end_time)
for e in data: for e in data:
init_data[e[0]] = e[1] init_data[e[0]] = e[1]
for k, v in init_data.items(): for k, v in list(init_data.items()):
res_data.append({'datetime': datetime_to_isoformat_timestr(k), 'count': v}) res_data.append({'datetime': datetime_to_isoformat_timestr(k), 'count': v})
return Response(sorted(res_data, key=lambda x: x['datetime'])) return Response(sorted(res_data, key=lambda x: x['datetime']))
@ -157,7 +157,7 @@ class SystemTrafficView(APIView):
'link-file-upload', 'link-file-download'] 'link-file-upload', 'link-file-download']
init_count = [0] * 6 init_count = [0] * 6
init_data = get_init_data(start_time, end_time, init_data = get_init_data(start_time, end_time,
dict(zip(op_type_list, init_count))) dict(list(zip(op_type_list, init_count))))
for e in get_system_traffic_by_day(start_time, end_time, for e in get_system_traffic_by_day(start_time, end_time,
get_time_offset()): get_time_offset()):
@ -165,7 +165,7 @@ class SystemTrafficView(APIView):
init_data[dt].update({op_type: count}) init_data[dt].update({op_type: count})
res_data = [] res_data = []
for k, v in init_data.items(): for k, v in list(init_data.items()):
res = {'datetime': datetime_to_isoformat_timestr(k)} res = {'datetime': datetime_to_isoformat_timestr(k)}
res.update(v) res.update(v)
res_data.append(res) res_data.append(res)

View File

@ -272,7 +272,7 @@ class AdminUsers(APIView):
if IS_EMAIL_CONFIGURED and SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER: if IS_EMAIL_CONFIGURED and SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER:
c = {'user': request.user.username, 'email': email, 'password': password} c = {'user': request.user.username, 'email': email, 'password': password}
try: try:
send_html_email(_(u'You are invited to join %s') % get_site_name(), send_html_email(_('You are invited to join %s') % get_site_name(),
'sysadmin/user_add_email.html', c, None, [email]) 'sysadmin/user_add_email.html', c, None, [email])
except Exception as e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
@ -343,7 +343,7 @@ class AdminUser(APIView):
username_by_login_id = Profile.objects.get_username_by_login_id(login_id) username_by_login_id = Profile.objects.get_username_by_login_id(login_id)
if username_by_login_id is not None: if username_by_login_id is not None:
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u"Login id %s already exists." % login_id)) _("Login id %s already exists." % login_id))
contact_email = request.data.get("contact_email", None) contact_email = request.data.get("contact_email", None)
if contact_email is not None and contact_email.strip() != '': if contact_email is not None and contact_email.strip() != '':

View File

@ -33,7 +33,6 @@ DEPARTMENT_OWNER = 'system admin'
# # uid = corpid + '_' + userid # # uid = corpid + '_' + userid
# from social_django.models import UserSocialAuth
# get departments: https://work.weixin.qq.com/api/doc#90000/90135/90208 # get departments: https://work.weixin.qq.com/api/doc#90000/90135/90208
# get members: https://work.weixin.qq.com/api/doc#90000/90135/90200 # get members: https://work.weixin.qq.com/api/doc#90000/90135/90200

View File

@ -147,7 +147,7 @@ class CopyMoveTaskView(APIView):
# check if above quota for dst repo # check if above quota for dst repo
if seafile_api.check_quota(dst_repo_id, current_size) < 0: if seafile_api.check_quota(dst_repo_id, current_size) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
new_dirent_name = check_filename_with_rename(dst_repo_id, new_dirent_name = check_filename_with_rename(dst_repo_id,
dst_parent_dir, src_dirent_name) dst_parent_dir, src_dirent_name)
@ -162,7 +162,7 @@ class CopyMoveTaskView(APIView):
if dirent_type == 'dir' and src_repo_id == dst_repo_id and \ if dirent_type == 'dir' and src_repo_id == dst_repo_id and \
dst_parent_dir.startswith(src_dirent_path + '/'): dst_parent_dir.startswith(src_dirent_path + '/'):
error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \ error_msg = _('Can not move directory %(src)s to its subdirectory %(des)s') \
% {'src': escape(src_dirent_path), 'des': escape(dst_parent_dir)} % {'src': escape(src_dirent_path), 'des': escape(dst_parent_dir)}
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

View File

@ -83,8 +83,8 @@ def get_dir_file_info_list(username, request_type, repo_obj, parent_dir,
# Use dict to reduce memcache fetch cost in large for-loop. # Use dict to reduce memcache fetch cost in large for-loop.
nickname_dict = {} nickname_dict = {}
contact_email_dict = {} contact_email_dict = {}
modifier_set = set([x.modifier for x in file_list]) modifier_set = {x.modifier for x in file_list}
lock_owner_set = set([x.lock_owner for x in file_list]) lock_owner_set = {x.lock_owner for x in file_list}
for e in modifier_set | lock_owner_set: for e in modifier_set | lock_owner_set:
if e not in nickname_dict: if e not in nickname_dict:
nickname_dict[e] = email2nickname(e) nickname_dict[e] = email2nickname(e)
@ -167,8 +167,8 @@ def get_dir_file_info_list(username, request_type, repo_obj, parent_dir,
file_info_list.append(file_info) file_info_list.append(file_info)
dir_info_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) dir_info_list.sort(key=lambda x: x['name'].lower())
file_info_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) file_info_list.sort(key=lambda x: x['name'].lower())
return dir_info_list, file_info_list return dir_info_list, file_info_list
@ -445,7 +445,7 @@ class DirView(APIView):
dir_info = self.get_dir_info(repo_id, new_dir_path) dir_info = self.get_dir_info(repo_id, new_dir_path)
resp = Response(dir_info) resp = Response(dir_info)
return resp return resp
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

View File

@ -313,7 +313,7 @@ class DirSharedItemsEndpoint(APIView):
if not is_valid_username(to_user): if not is_valid_username(to_user):
result['failed'].append({ result['failed'].append({
'email': to_user, 'email': to_user,
'error_msg': _(u'username invalid.') 'error_msg': _('username invalid.')
}) })
continue continue
@ -322,14 +322,14 @@ class DirSharedItemsEndpoint(APIView):
except User.DoesNotExist: except User.DoesNotExist:
result['failed'].append({ result['failed'].append({
'email': to_user, 'email': to_user,
'error_msg': _(u'User %s not found.') % to_user 'error_msg': _('User %s not found.') % to_user
}) })
continue continue
if self.has_shared_to_user(request, repo_id, path, to_user): if self.has_shared_to_user(request, repo_id, path, to_user):
result['failed'].append({ result['failed'].append({
'email': to_user, 'email': to_user,
'error_msg': _(u'This item has been shared to %s.') % email2nickname(to_user) 'error_msg': _('This item has been shared to %s.') % email2nickname(to_user)
}) })
continue continue
@ -428,7 +428,7 @@ class DirSharedItemsEndpoint(APIView):
if self.has_shared_to_group(request, repo_id, path, gid): if self.has_shared_to_group(request, repo_id, path, gid):
result['failed'].append({ result['failed'].append({
'group_name': group.group_name, 'group_name': group.group_name,
'error_msg': _(u'This item has been shared to %s.') % group.group_name 'error_msg': _('This item has been shared to %s.') % group.group_name
}) })
continue continue

View File

@ -67,7 +67,7 @@ class DraftReviewerView(APIView):
if not is_valid_username(reviewer): if not is_valid_username(reviewer):
result['failed'].append({ result['failed'].append({
'email': reviewer, 'email': reviewer,
'error_msg': _(u'username invalid.') 'error_msg': _('username invalid.')
}) })
continue continue
@ -76,7 +76,7 @@ class DraftReviewerView(APIView):
except User.DoesNotExist: except User.DoesNotExist:
result['failed'].append({ result['failed'].append({
'email': reviewer, 'email': reviewer,
'error_msg': _(u'User %s not found.') % reviewer 'error_msg': _('User %s not found.') % reviewer
}) })
continue continue
@ -93,7 +93,7 @@ class DraftReviewerView(APIView):
origin_file_path = posixpath.join(uuid.parent_path, uuid.filename) origin_file_path = posixpath.join(uuid.parent_path, uuid.filename)
# check perm # check perm
if seafile_api.check_permission_by_path(d.origin_repo_id, origin_file_path, reviewer) != 'rw': if seafile_api.check_permission_by_path(d.origin_repo_id, origin_file_path, reviewer) != 'rw':
error_msg = _(u'Permission denied.') error_msg = _('Permission denied.')
result['failed'].append({ result['failed'].append({
'email': reviewer, 'email': reviewer,
'error_msg': error_msg 'error_msg': error_msg
@ -101,7 +101,7 @@ class DraftReviewerView(APIView):
continue continue
if DraftReviewer.objects.filter(draft=d, reviewer=reviewer): if DraftReviewer.objects.filter(draft=d, reviewer=reviewer):
error_msg = u'Reviewer %s has existed.' % reviewer error_msg = 'Reviewer %s has existed.' % reviewer
result['failed'].append({ result['failed'].append({
'email': reviewer, 'email': reviewer,
'error_msg': error_msg 'error_msg': error_msg

View File

@ -50,7 +50,7 @@ class WorkspacesView(APIView):
if is_org_context(request): if is_org_context(request):
org_id = request.user.org.org_id org_id = request.user.org.org_id
if org_id > 0: if org_id and org_id > 0:
groups = ccnet_api.get_org_groups_by_user(org_id, username) groups = ccnet_api.get_org_groups_by_user(org_id, username)
else: else:
groups = ccnet_api.get_groups(username, return_ancestors=True) groups = ccnet_api.get_groups(username, return_ancestors=True)
@ -80,7 +80,7 @@ class WorkspacesView(APIView):
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try: try:
if org_id > 0: if org_id and org_id > 0:
repo_id = seafile_api.create_org_repo( repo_id = seafile_api.create_org_repo(
_("My Workspace"), _("My Workspace"),
_("My Workspace"), _("My Workspace"),
@ -166,7 +166,7 @@ class DTablesView(APIView):
org_id = request.user.org.org_id org_id = request.user.org.org_id
try: try:
if org_id > 0: if org_id and org_id > 0:
repo_id = seafile_api.create_org_repo( repo_id = seafile_api.create_org_repo(
_("My Workspace"), _("My Workspace"),
_("My Workspace"), _("My Workspace"),

View File

@ -199,7 +199,7 @@ class FileView(APIView):
try: try:
seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, username) seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, username)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
@ -572,7 +572,7 @@ class FileView(APIView):
expire = request.data.get('expire', FILE_LOCK_EXPIRATION_DAYS) expire = request.data.get('expire', FILE_LOCK_EXPIRATION_DAYS)
try: try:
seafile_api.lock_file(repo_id, path, username, expire) seafile_api.lock_file(repo_id, path, username, expire)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
@ -587,7 +587,7 @@ class FileView(APIView):
# unlock file # unlock file
try: try:
seafile_api.unlock_file(repo_id, path) seafile_api.unlock_file(repo_id, path)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
@ -605,7 +605,7 @@ class FileView(APIView):
# refresh lock file # refresh lock file
try: try:
seafile_api.refresh_file_lock(repo_id, path) seafile_api.refresh_file_lock(repo_id, path)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

View File

@ -253,7 +253,7 @@ class FileTagsView(APIView):
name_list = [name.strip() for name in names.split(",")] name_list = [name.strip() for name in names.split(",")]
for name in name_list: for name in name_list:
if not check_tagname(name): if not check_tagname(name):
error_msg = _(u'Tag can only contain letters, numbers, dot, hyphen or underscore.') error_msg = _('Tag can only contain letters, numbers, dot, hyphen or underscore.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
FileTag.objects.delete_all_filetag_by_path(repo_id, parent_path, FileTag.objects.delete_all_filetag_by_path(repo_id, parent_path,
@ -277,7 +277,7 @@ class FileTagsView(APIView):
name_list = [name.strip() for name in names.split(",")] name_list = [name.strip() for name in names.split(",")]
for name in name_list: for name in name_list:
if not check_tagname(name): if not check_tagname(name):
error_msg = _(u'Tag can only contain letters, numbers, dot, hyphen or underscore.') error_msg = _('Tag can only contain letters, numbers, dot, hyphen or underscore.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
res_tag_list = [] res_tag_list = []
@ -297,10 +297,10 @@ class FileTagView(APIView):
@check_parameter @check_parameter
def delete(self, request, repo_id, parent_path, filename, name, is_dir): def delete(self, request, repo_id, parent_path, filename, name, is_dir):
if not name or not check_tagname(name): if not name or not check_tagname(name):
error_msg = _(u'Tag can only contain letters, numbers, dot, hyphen or underscore.') error_msg = _('Tag can only contain letters, numbers, dot, hyphen or underscore.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if FileTag.objects.delete_file_tag_by_path(repo_id, if FileTag.objects.delete_file_tag_by_path(repo_id,
parent_path,filename,is_dir,name): parent_path, filename, is_dir, name):
return Response({"success": True}, status=status.HTTP_200_OK) return Response({"success": True}, status=status.HTTP_200_OK)
else: else:
return Response({"success": True}, status=status.HTTP_202_ACCEPTED) return Response({"success": True}, status=status.HTTP_202_ACCEPTED)

View File

@ -82,7 +82,7 @@ class GroupLibraries(APIView):
else: else:
group_repos = seafile_api.get_repos_by_group(group_id) group_repos = seafile_api.get_repos_by_group(group_id)
group_repos.sort(lambda x, y: cmp(y.last_modified, x.last_modified)) group_repos.sort(key=lambda x: x.last_modified, reverse=True)
# get repo id owner dict # get repo id owner dict
all_repo_owner = [] all_repo_owner = []

View File

@ -91,13 +91,13 @@ class GroupMembers(APIView):
try: try:
if is_group_member(group_id, email): if is_group_member(group_id, email):
error_msg = _(u'User %s is already a group member.') % email2nickname(email) error_msg = _('User %s is already a group member.') % email2nickname(email)
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if is_org_context(request): if is_org_context(request):
org_id = request.user.org.org_id org_id = request.user.org.org_id
if not ccnet_api.org_user_exists(org_id, email): if not ccnet_api.org_user_exists(org_id, email):
error_msg = _(u'User %s not found in organization.') % email2nickname(email) error_msg = _('User %s not found in organization.') % email2nickname(email)
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
ccnet_api.group_add_member(group_id, username, email) ccnet_api.group_add_member(group_id, username, email)
@ -290,7 +290,7 @@ class GroupMembersBulk(APIView):
result['failed'].append({ result['failed'].append({
'email': email, 'email': email,
'email_name': email_name, 'email_name': email_name,
'error_msg': _(u'User %s is already a group member.') % email_name 'error_msg': _('User %s is already a group member.') % email_name
}) })
continue continue
@ -300,7 +300,7 @@ class GroupMembersBulk(APIView):
result['failed'].append({ result['failed'].append({
'email': email, 'email': email,
'email_name': email_name, 'email_name': email_name,
'error_msg': _(u'User %s not found in organization.') % email_name 'error_msg': _('User %s not found in organization.') % email_name
}) })
continue continue

View File

@ -369,7 +369,7 @@ class GroupOwnedLibraryUserFolderPermission(APIView):
if permission: if permission:
result['failed'].append({ result['failed'].append({
'user_email': user, 'user_email': user,
'error_msg': _(u'Permission already exists.') 'error_msg': _('Permission already exists.')
}) })
continue continue
@ -641,7 +641,7 @@ class GroupOwnedLibraryGroupFolderPermission(APIView):
if permission: if permission:
result['failed'].append({ result['failed'].append({
'group_id': group_id, 'group_id': group_id,
'error_msg': _(u'Permission already exists.') 'error_msg': _('Permission already exists.')
}) })
continue continue
@ -914,7 +914,7 @@ class GroupOwnedLibraryUserShare(APIView):
if not is_valid_username(to_user): if not is_valid_username(to_user):
result['failed'].append({ result['failed'].append({
'email': to_user, 'email': to_user,
'error_msg': _(u'username invalid.') 'error_msg': _('username invalid.')
}) })
continue continue
@ -923,14 +923,14 @@ class GroupOwnedLibraryUserShare(APIView):
except User.DoesNotExist: except User.DoesNotExist:
result['failed'].append({ result['failed'].append({
'email': to_user, 'email': to_user,
'error_msg': _(u'User %s not found.') % to_user 'error_msg': _('User %s not found.') % to_user
}) })
continue continue
if self.has_shared_to_user(request, repo_id, path, to_user): if self.has_shared_to_user(request, repo_id, path, to_user):
result['failed'].append({ result['failed'].append({
'email': to_user, 'email': to_user,
'error_msg': _(u'This item has been shared to %s.') % to_user 'error_msg': _('This item has been shared to %s.') % to_user
}) })
continue continue
@ -1198,7 +1198,7 @@ class GroupOwnedLibraryGroupShare(APIView):
if self.has_shared_to_group(request, repo_id, path, gid): if self.has_shared_to_group(request, repo_id, path, gid):
result['failed'].append({ result['failed'].append({
'group_name': group.group_name, 'group_name': group.group_name,
'error_msg': _(u'This item has been shared to %s.') % group.group_name 'error_msg': _('This item has been shared to %s.') % group.group_name
}) })
continue continue

View File

@ -41,7 +41,7 @@ logger = logging.getLogger(__name__)
def get_group_admins(group_id): def get_group_admins(group_id):
members = seaserv.get_group_members(group_id) members = seaserv.get_group_members(group_id)
admin_members = filter(lambda m: m.is_staff, members) admin_members = [m for m in members if m.is_staff]
admins = [] admins = []
for u in admin_members: for u in admin_members:
@ -208,12 +208,12 @@ class Groups(APIView):
# Check whether group name is validate. # Check whether group name is validate.
if not validate_group_name(group_name): if not validate_group_name(group_name):
error_msg = _(u'Group name can only contain letters, numbers, blank, hyphen, dot, single quote or underscore') error_msg = _('Group name can only contain letters, numbers, blank, hyphen, dot, single quote or underscore')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# Check whether group name is duplicated. # Check whether group name is duplicated.
if check_group_name_conflict(request, group_name): if check_group_name_conflict(request, group_name):
error_msg = _(u'There is already a group with that name.') error_msg = _('There is already a group with that name.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# create group. # create group.
@ -284,12 +284,12 @@ class Group(APIView):
# Check whether group name is validate. # Check whether group name is validate.
if not validate_group_name(new_group_name): if not validate_group_name(new_group_name):
error_msg = _(u'Group name can only contain letters, numbers, blank, hyphen or underscore') error_msg = _('Group name can only contain letters, numbers, blank, hyphen or underscore')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# Check whether group name is duplicated. # Check whether group name is duplicated.
if check_group_name_conflict(request, new_group_name): if check_group_name_conflict(request, new_group_name):
error_msg = _(u'There is already a group with that name.') error_msg = _('There is already a group with that name.')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
seaserv.ccnet_threaded_rpc.set_group_name(group_id, new_group_name) seaserv.ccnet_threaded_rpc.set_group_name(group_id, new_group_name)
@ -314,7 +314,7 @@ class Group(APIView):
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if is_group_owner(group_id, new_owner): if is_group_owner(group_id, new_owner):
error_msg = _(u'User %s is already group owner.') % new_owner error_msg = _('User %s is already group owner.') % new_owner
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# transfer a group # transfer a group

View File

@ -169,7 +169,7 @@ class MoveFolderMergeView(APIView):
src_repo.version, dir_id) src_repo.version, dir_id)
if seafile_api.check_quota(dst_repo_id, current_size) < 0: if seafile_api.check_quota(dst_repo_id, current_size) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
username = request.user.username username = request.user.username
move_folder_with_merge(username, move_folder_with_merge(username,

View File

@ -44,7 +44,7 @@ class QueryCopyMoveProgressView(APIView):
# res can be None # res can be None
if not res: if not res:
error_msg = _(u'Error') error_msg = _('Error')
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
result = {} result = {}

View File

@ -215,7 +215,7 @@ class RelatedFileView(APIView):
# permission check # permission check
if check_folder_permission(request, repo_id, '/') != PERMISSION_READ_WRITE: if check_folder_permission(request, repo_id, '/') != PERMISSION_READ_WRITE:
print check_folder_permission(request, repo_id, file_path) print(check_folder_permission(request, repo_id, file_path))
error_msg = 'Permission denied.' error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)

View File

@ -129,14 +129,14 @@ class RepoHistory(APIView):
revision_tags = [] revision_tags = []
for tag in revision_tags: for tag in revision_tags:
if commit_tag_dict.has_key(tag.revision_id): if tag.revision_id in commit_tag_dict:
commit_tag_dict[tag.revision_id].append(tag.tag.name) commit_tag_dict[tag.revision_id].append(tag.tag.name)
else: else:
commit_tag_dict[tag.revision_id] = [tag.tag.name] commit_tag_dict[tag.revision_id] = [tag.tag.name]
for item in items: for item in items:
item['tags'] = [] item['tags'] = []
for commit_id, tags in commit_tag_dict.items(): for commit_id, tags in list(commit_tag_dict.items()):
if commit_id == item['commit_id']: if commit_id == item['commit_id']:
item['tags'] = tags item['tags'] = tags

View File

@ -41,7 +41,7 @@ class RepoSendNewPassword(APIView):
if not ENABLE_RESET_ENCRYPTED_REPO_PASSWORD or \ if not ENABLE_RESET_ENCRYPTED_REPO_PASSWORD or \
not IS_EMAIL_CONFIGURED: not IS_EMAIL_CONFIGURED:
error_msg = _(u'Feature disabled.') error_msg = _('Feature disabled.')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# resource check # resource check
@ -62,14 +62,14 @@ class RepoSendNewPassword(APIView):
secret_key = RepoSecretKey.objects.get_secret_key(repo_id) secret_key = RepoSecretKey.objects.get_secret_key(repo_id)
if not secret_key: if not secret_key:
error_msg = _(u"Can not reset this library's password.") error_msg = _("Can not reset this library's password.")
return api_error(HTTP_520_OPERATION_FAILED, error_msg) return api_error(HTTP_520_OPERATION_FAILED, error_msg)
new_password = get_random_string(10) new_password = get_random_string(10)
try: try:
seafile_api.reset_repo_passwd(repo_id, username, secret_key, new_password) seafile_api.reset_repo_passwd(repo_id, username, secret_key, new_password)
content = {'repo_name': repo.name, 'password': new_password,} content = {'repo_name': repo.name, 'password': new_password,}
send_html_email(_(u'New password of library %s') % repo.name, send_html_email(_('New password of library %s') % repo.name,
'snippets/reset_repo_password.html', content, 'snippets/reset_repo_password.html', content,
None, [email2contact_email(username)]) None, [email2contact_email(username)])
except Exception as e: except Exception as e:

View File

@ -64,13 +64,13 @@ class RepoSetPassword(APIView):
error_msg = 'Bad arguments' error_msg = 'Bad arguments'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
elif e.msg == 'Incorrect password': elif e.msg == 'Incorrect password':
error_msg = _(u'Wrong password') error_msg = _('Wrong password')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
elif e.msg == 'Internal server error': elif e.msg == 'Internal server error':
error_msg = _(u'Internal server error') error_msg = _('Internal server error')
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
else: else:
error_msg = _(u'Decrypt library error') error_msg = _('Decrypt library error')
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if ENABLE_RESET_ENCRYPTED_REPO_PASSWORD: if ENABLE_RESET_ENCRYPTED_REPO_PASSWORD:
@ -124,7 +124,7 @@ class RepoSetPassword(APIView):
seafile_api.change_repo_passwd(repo_id, old_password, new_password, username) seafile_api.change_repo_passwd(repo_id, old_password, new_password, username)
except Exception as e: except Exception as e:
if e.msg == 'Incorrect password': if e.msg == 'Incorrect password':
error_msg = _(u'Wrong old password') error_msg = _('Wrong old password')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
else: else:
logger.error(e) logger.error(e)
@ -157,7 +157,7 @@ class RepoSetPassword(APIView):
secret_key = RepoSecretKey.objects.get_secret_key(repo_id) secret_key = RepoSecretKey.objects.get_secret_key(repo_id)
if not secret_key: if not secret_key:
error_msg = _(u"Can not reset this library's password.") error_msg = _("Can not reset this library's password.")
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
try: try:

View File

@ -70,7 +70,7 @@ class RepoTagsView(APIView):
for repo_tag in repo_tag_list: for repo_tag in repo_tag_list:
res = repo_tag.to_dict() res = repo_tag.to_dict()
repo_tag_id = res["repo_tag_id"] repo_tag_id = res["repo_tag_id"]
if files_count.has_key(repo_tag_id): if repo_tag_id in files_count:
res["files_count"] = files_count[repo_tag_id] res["files_count"] = files_count[repo_tag_id]
else: else:
res["files_count"] = 0 res["files_count"] = 0

View File

@ -112,8 +112,8 @@ class RepoTrash(APIView):
entries_without_scan_stat = deleted_entries[0:-1] entries_without_scan_stat = deleted_entries[0:-1]
# sort entry by delete time # sort entry by delete time
entries_without_scan_stat.sort(lambda x, y : cmp(y.delete_time, entries_without_scan_stat.sort(
x.delete_time)) key=lambda x: x.delete_time, reverse=True)
for item in entries_without_scan_stat: for item in entries_without_scan_stat:
item_info = self.get_item_info(item) item_info = self.get_item_info(item)

View File

@ -28,7 +28,7 @@ from seahub.utils.repo import get_repo_owner, is_repo_admin, \
from seahub.settings import ENABLE_STORAGE_CLASSES from seahub.settings import ENABLE_STORAGE_CLASSES
from seaserv import seafile_api, send_message from seaserv import seafile_api
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -56,7 +56,7 @@ class ReposView(APIView):
request_type_list = request.GET.getlist('type', "") request_type_list = request.GET.getlist('type', "")
if not request_type_list: if not request_type_list:
# set all to True, no filter applied # set all to True, no filter applied
filter_by = filter_by.fromkeys(filter_by.iterkeys(), True) filter_by = filter_by.fromkeys(iter(filter_by.keys()), True)
for request_type in request_type_list: for request_type in request_type_list:
request_type = request_type.strip() request_type = request_type.strip()
@ -90,14 +90,14 @@ class ReposView(APIView):
ret_corrupted=True) ret_corrupted=True)
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
modifiers_set = set([x.last_modifier for x in owned_repos]) modifiers_set = {x.last_modifier for x in owned_repos}
for e in modifiers_set: for e in modifiers_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
if e not in nickname_dict: if e not in nickname_dict:
nickname_dict[e] = email2nickname(e) nickname_dict[e] = email2nickname(e)
owned_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) owned_repos.sort(key=lambda x: x.last_modify, reverse=True)
for r in owned_repos: for r in owned_repos:
# do not return virtual repos # do not return virtual repos
@ -141,15 +141,15 @@ class ReposView(APIView):
get_repos_with_admin_permission(email) get_repos_with_admin_permission(email)
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
owners_set = set([x.user for x in shared_repos]) owners_set = {x.user for x in shared_repos}
modifiers_set = set([x.last_modifier for x in shared_repos]) modifiers_set = {x.last_modifier for x in shared_repos}
for e in owners_set | modifiers_set: for e in owners_set | modifiers_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
if e not in nickname_dict: if e not in nickname_dict:
nickname_dict[e] = email2nickname(e) nickname_dict[e] = email2nickname(e)
shared_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) shared_repos.sort(key=lambda x: x.last_modify, reverse=True)
for r in shared_repos: for r in shared_repos:
owner_email = r.user owner_email = r.user
@ -198,11 +198,11 @@ class ReposView(APIView):
else: else:
group_repos = seafile_api.get_group_repos_by_user(email) group_repos = seafile_api.get_group_repos_by_user(email)
group_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) group_repos.sort(key=lambda x: x.last_modify, reverse=True)
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
share_from_set = set([x.user for x in group_repos]) share_from_set = {x.user for x in group_repos}
modifiers_set = set([x.last_modifier for x in group_repos]) modifiers_set = {x.last_modifier for x in group_repos}
for e in modifiers_set | share_from_set: for e in modifiers_set | share_from_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
@ -243,8 +243,8 @@ class ReposView(APIView):
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
owner_set = set(all_repo_owner) owner_set = set(all_repo_owner)
share_from_set = set([x.user for x in public_repos]) share_from_set = {x.user for x in public_repos}
modifiers_set = set([x.last_modifier for x in public_repos]) modifiers_set = {x.last_modifier for x in public_repos}
for e in modifiers_set | share_from_set | owner_set: for e in modifiers_set | share_from_set | owner_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
@ -276,7 +276,7 @@ class ReposView(APIView):
timestamp = utc_dt.strftime('%Y-%m-%d %H:%M:%S') timestamp = utc_dt.strftime('%Y-%m-%d %H:%M:%S')
org_id = request.user.org.org_id if is_org_context(request) else -1 org_id = request.user.org.org_id if is_org_context(request) else -1
try: try:
send_message('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id)) seafile_api.publish_event('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id))
except Exception as e: except Exception as e:
logger.error('Error when sending user-login message: %s' % str(e)) logger.error('Error when sending user-login message: %s' % str(e))

View File

@ -488,7 +488,7 @@ class ReposBatchCopyDirView(APIView):
# check if above quota for dst repo # check if above quota for dst repo
if seafile_api.check_quota(dst_repo_id, total_size) < 0: if seafile_api.check_quota(dst_repo_id, total_size) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
result = {} result = {}
result['failed'] = [] result['failed'] = []
@ -1249,18 +1249,18 @@ class ReposAsyncBatchMoveItemView(APIView):
locked_files = get_locked_files_by_dir(request, src_repo_id, src_parent_dir) locked_files = get_locked_files_by_dir(request, src_repo_id, src_parent_dir)
for dirent in src_dirents: for dirent in src_dirents:
# file is locked and lock owner is not current user # file is locked and lock owner is not current user
if dirent in locked_files.keys() and \ if dirent in list(locked_files.keys()) and \
locked_files[dirent] != username: locked_files[dirent] != username:
error_msg = _(u'File %s is locked.') % dirent error_msg = _('File %s is locked.') % dirent
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check sub folder permission # check sub folder permission
folder_permission_dict = get_sub_folder_permission_by_dir(request, folder_permission_dict = get_sub_folder_permission_by_dir(request,
src_repo_id, src_parent_dir) src_repo_id, src_parent_dir)
for dirent in src_dirents: for dirent in src_dirents:
if dirent in folder_permission_dict.keys() and \ if dirent in list(folder_permission_dict.keys()) and \
folder_permission_dict[dirent] != 'rw': folder_permission_dict[dirent] != 'rw':
error_msg = _(u"Can't move folder %s, please check its permission.") % dirent error_msg = _("Can't move folder %s, please check its permission.") % dirent
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# move file # move file
@ -1468,18 +1468,18 @@ class ReposSyncBatchMoveItemView(APIView):
locked_files = get_locked_files_by_dir(request, src_repo_id, src_parent_dir) locked_files = get_locked_files_by_dir(request, src_repo_id, src_parent_dir)
for dirent in src_dirents: for dirent in src_dirents:
# file is locked and lock owner is not current user # file is locked and lock owner is not current user
if dirent in locked_files.keys() and \ if dirent in list(locked_files.keys()) and \
locked_files[dirent] != username: locked_files[dirent] != username:
error_msg = _(u'File %s is locked.') % dirent error_msg = _('File %s is locked.') % dirent
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check sub folder permission # check sub folder permission
folder_permission_dict = get_sub_folder_permission_by_dir(request, folder_permission_dict = get_sub_folder_permission_by_dir(request,
src_repo_id, src_parent_dir) src_repo_id, src_parent_dir)
for dirent in src_dirents: for dirent in src_dirents:
if dirent in folder_permission_dict.keys() and \ if dirent in list(folder_permission_dict.keys()) and \
folder_permission_dict[dirent] != 'rw': folder_permission_dict[dirent] != 'rw':
error_msg = _(u"Can't move folder %s, please check its permission.") % dirent error_msg = _("Can't move folder %s, please check its permission.") % dirent
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# move file # move file
@ -1557,17 +1557,17 @@ class ReposBatchDeleteItemView(APIView):
locked_files = get_locked_files_by_dir(request, repo_id, parent_dir) locked_files = get_locked_files_by_dir(request, repo_id, parent_dir)
for dirent in dirents: for dirent in dirents:
# file is locked and lock owner is not current user # file is locked and lock owner is not current user
if dirent in locked_files.keys() and \ if dirent in list(locked_files.keys()) and \
locked_files[dirent] != username: locked_files[dirent] != username:
error_msg = _(u'File %s is locked.') % dirent error_msg = _('File %s is locked.') % dirent
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check sub folder permission # check sub folder permission
folder_permission_dict = get_sub_folder_permission_by_dir(request, repo_id, parent_dir) folder_permission_dict = get_sub_folder_permission_by_dir(request, repo_id, parent_dir)
for dirent in dirents: for dirent in dirents:
if dirent in folder_permission_dict.keys() and \ if dirent in list(folder_permission_dict.keys()) and \
folder_permission_dict[dirent] != 'rw': folder_permission_dict[dirent] != 'rw':
error_msg = _(u"Can't delete folder %s, please check its permission.") % dirent error_msg = _("Can't delete folder %s, please check its permission.") % dirent
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# delete file # delete file

View File

@ -120,7 +120,7 @@ class SearchUser(APIView):
## search finished, now filter out some users ## search finished, now filter out some users
# remove duplicate emails # remove duplicate emails
email_list = {}.fromkeys(email_list).keys() email_list = list({}.fromkeys(email_list).keys())
email_result = [] email_result = []

View File

@ -30,7 +30,7 @@ class SendShareLinkView(APIView):
def post(self, request): def post(self, request):
if not IS_EMAIL_CONFIGURED: if not IS_EMAIL_CONFIGURED:
error_msg = _(u'Sending shared link failed. Email service is not properly configured, please contact administrator.') error_msg = _('Sending shared link failed. Email service is not properly configured, please contact administrator.')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check args # check args
@ -97,11 +97,11 @@ class SendShareLinkView(APIView):
template = 'shared_link_email.html' template = 'shared_link_email.html'
if link.s_type == 'f': if link.s_type == 'f':
c['file_shared_type'] = _(u"file") c['file_shared_type'] = _("file")
title = _(u'A file is shared to you on %s') % get_site_name() title = _('A file is shared to you on %s') % get_site_name()
else: else:
c['file_shared_type'] = _(u"directory") c['file_shared_type'] = _("directory")
title = _(u'A directory is shared to you on %s') % get_site_name() title = _('A directory is shared to you on %s') % get_site_name()
# send email # send email
try: try:

View File

@ -29,7 +29,7 @@ class SendUploadLinkView(APIView):
def post(self, request): def post(self, request):
if not IS_EMAIL_CONFIGURED: if not IS_EMAIL_CONFIGURED:
error_msg = _(u'Sending shared link failed. Email service is not properly configured, please contact administrator.') error_msg = _('Sending shared link failed. Email service is not properly configured, please contact administrator.')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check args # check args
@ -70,7 +70,7 @@ class SendUploadLinkView(APIView):
if not is_valid_email(to_email): if not is_valid_email(to_email):
failed_info['email'] = to_email failed_info['email'] = to_email
failed_info['error_msg'] = _(u'email invalid.') failed_info['error_msg'] = _('email invalid.')
result['failed'].append(failed_info) result['failed'].append(failed_info)
continue continue
@ -92,7 +92,7 @@ class SendUploadLinkView(APIView):
reply_to = None reply_to = None
c['shared_upload_link'] = gen_shared_upload_link(token) c['shared_upload_link'] = gen_shared_upload_link(token)
title = _(u'An upload link is shared to you on %s') % get_site_name() title = _('An upload link is shared to you on %s') % get_site_name()
template = 'shared_upload_link_email.html' template = 'shared_upload_link_email.html'
# send email # send email
@ -102,7 +102,7 @@ class SendUploadLinkView(APIView):
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
failed_info['email'] = to_email failed_info['email'] = to_email
failed_info['error_msg'] = _(u'Internal Server Error') failed_info['error_msg'] = _('Internal Server Error')
result['failed'].append(failed_info) result['failed'].append(failed_info)
return Response(result) return Response(result)

View File

@ -93,7 +93,7 @@ def check_permissions_arg(request):
if permissions is not None: if permissions is not None:
if isinstance(permissions, dict): if isinstance(permissions, dict):
perm_dict = permissions perm_dict = permissions
elif isinstance(permissions, basestring): elif isinstance(permissions, str):
import json import json
try: try:
perm_dict = json.loads(permissions) perm_dict = json.loads(permissions)
@ -164,7 +164,7 @@ class ShareLinks(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# filter share links by repo # filter share links by repo
fileshares = filter(lambda fs: fs.repo_id == repo_id, fileshares) fileshares = [fs for fs in fileshares if fs.repo_id == repo_id]
path = request.GET.get('path', None) path = request.GET.get('path', None)
if path: if path:
@ -189,7 +189,7 @@ class ShareLinks(APIView):
if s_type == 'd' and path[-1] != '/': if s_type == 'd' and path[-1] != '/':
path = path + '/' path = path + '/'
fileshares = filter(lambda fs: fs.path == path, fileshares) fileshares = [fs for fs in fileshares if fs.path == path]
links_info = [] links_info = []
for fs in fileshares: for fs in fileshares:
@ -199,11 +199,11 @@ class ShareLinks(APIView):
if len(links_info) == 1: if len(links_info) == 1:
result = links_info result = links_info
else: else:
dir_list = filter(lambda x: x['is_dir'], links_info) dir_list = [x for x in links_info if x['is_dir']]
file_list = filter(lambda x: not x['is_dir'], links_info) file_list = [x for x in links_info if not x['is_dir']]
dir_list.sort(lambda x, y: cmp(x['obj_name'], y['obj_name'])) dir_list.sort(key=lambda x: x['obj_name'])
file_list.sort(lambda x, y: cmp(x['obj_name'], y['obj_name'])) file_list.sort(key=lambda x: x['obj_name'])
result = dir_list + file_list result = dir_list + file_list
@ -297,7 +297,7 @@ class ShareLinks(APIView):
if s_type == 'f': if s_type == 'f':
fs = FileShare.objects.get_file_link_by_path(username, repo_id, path) fs = FileShare.objects.get_file_link_by_path(username, repo_id, path)
if fs: if fs:
error_msg = _(u'Share link %s already exists.' % fs.token) error_msg = _('Share link %s already exists.' % fs.token)
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
fs = FileShare.objects.create_file_link(username, repo_id, path, fs = FileShare.objects.create_file_link(username, repo_id, path,
password, expire_date, password, expire_date,
@ -306,7 +306,7 @@ class ShareLinks(APIView):
elif s_type == 'd': elif s_type == 'd':
fs = FileShare.objects.get_dir_link_by_path(username, repo_id, path) fs = FileShare.objects.get_dir_link_by_path(username, repo_id, path)
if fs: if fs:
error_msg = _(u'Share link %s already exists.' % fs.token) error_msg = _('Share link %s already exists.' % fs.token)
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
fs = FileShare.objects.create_dir_link(username, repo_id, path, fs = FileShare.objects.create_dir_link(username, repo_id, path,
password, expire_date, password, expire_date,
@ -454,7 +454,7 @@ class ShareLinkOnlineOfficeLock(APIView):
# refresh lock file # refresh lock file
try: try:
seafile_api.refresh_file_lock(repo_id, path) seafile_api.refresh_file_lock(repo_id, path)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

View File

@ -49,7 +49,7 @@ class SharedFolders(APIView):
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
returned_result = [] returned_result = []
shared_repos.sort(lambda x, y: cmp(x.repo_name, y.repo_name)) shared_repos.sort(key=lambda x: x.repo_name)
for repo in shared_repos: for repo in shared_repos:
if not repo.is_virtual: if not repo.is_virtual:
continue continue

View File

@ -55,7 +55,7 @@ class SharedRepos(APIView):
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
returned_result = [] returned_result = []
shared_repos.sort(lambda x, y: cmp(x.repo_name, y.repo_name)) shared_repos.sort(key=lambda x: x.repo_name)
usernames = [] usernames = []
gids = [] gids = []
for repo in shared_repos: for repo in shared_repos:
@ -309,10 +309,10 @@ class SharedRepo(APIView):
if share_type == 'public': if share_type == 'public':
pub_repos = [] pub_repos = []
if org_id: if org_id:
pub_repos = seaserv.list_org_inner_pub_repos(org_id, username) pub_repos = seafile_api.list_org_inner_pub_repos(org_id)
if not request.cloud_mode: if not request.cloud_mode:
pub_repos = seaserv.list_inner_pub_repos(username) pub_repos = seafile_api.get_inner_pub_repo_list()
try: try:
if org_id: if org_id:

View File

@ -105,9 +105,9 @@ class StarredItems(APIView):
else: else:
starred_files.append(item_info) starred_files.append(item_info)
starred_repos.sort(lambda x, y: cmp(y['mtime'], x['mtime'])) starred_repos.sort(key=lambda x: x['mtime'], reverse=True)
starred_folders.sort(lambda x, y: cmp(y['mtime'], x['mtime'])) starred_folders.sort(key=lambda x: x['mtime'], reverse=True)
starred_files.sort(lambda x, y: cmp(y['mtime'], x['mtime'])) starred_files.sort(key=lambda x: x['mtime'], reverse=True)
return Response({'starred_item_list': starred_repos + \ return Response({'starred_item_list': starred_repos + \
starred_folders + starred_files}) starred_folders + starred_files})

View File

@ -95,7 +95,7 @@ class UploadLinks(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# filter share links by repo # filter share links by repo
upload_link_shares = filter(lambda ufs: ufs.repo_id==repo_id, upload_link_shares) upload_link_shares = [ufs for ufs in upload_link_shares if ufs.repo_id==repo_id]
path = request.GET.get('path', None) path = request.GET.get('path', None)
if path: if path:
@ -114,7 +114,7 @@ class UploadLinks(APIView):
path = path + '/' path = path + '/'
# filter share links by path # filter share links by path
upload_link_shares = filter(lambda ufs: ufs.path==path, upload_link_shares) upload_link_shares = [ufs for ufs in upload_link_shares if ufs.path==path]
result = [] result = []
for uls in upload_link_shares: for uls in upload_link_shares:
@ -124,7 +124,7 @@ class UploadLinks(APIView):
if len(result) == 1: if len(result) == 1:
result = result result = result
else: else:
result.sort(lambda x, y: cmp(x['obj_name'], y['obj_name'])) result.sort(key=lambda x: x['obj_name'])
return Response(result) return Response(result)

View File

@ -54,7 +54,7 @@ class User(APIView):
# update account telephone # update account telephone
if info_dict['telephone']: if info_dict['telephone']:
DetailedProfile.objects.add_or_update(email, department=None , telephone=info_dict['telephone']) DetailedProfile.objects.add_or_update(email, department=None, telephone=info_dict['telephone'])
# update user list_in_address_book # update user list_in_address_book
if info_dict['list_in_address_book']: if info_dict['list_in_address_book']:
@ -70,7 +70,7 @@ class User(APIView):
email = request.user.username email = request.user.username
if not ENABLE_UPDATE_USER_INFO: if not ENABLE_UPDATE_USER_INFO:
error_msg = _(u'Feature disabled.') error_msg = _('Feature disabled.')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# argument check for name # argument check for name
@ -78,11 +78,11 @@ class User(APIView):
if name: if name:
name = name.strip() name = name.strip()
if len(name) > 64: if len(name) > 64:
error_msg = _(u'Name is too long (maximum is 64 characters)') error_msg = _('Name is too long (maximum is 64 characters)')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if "/" in name: if "/" in name:
error_msg = _(u"Name should not include '/'.") error_msg = _("Name should not include '/'.")
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# argument check for contact_email # argument check for contact_email
@ -90,7 +90,7 @@ class User(APIView):
if contact_email: if contact_email:
if not ENABLE_USER_SET_CONTACT_EMAIL: if not ENABLE_USER_SET_CONTACT_EMAIL:
error_msg = _(u'Feature disabled.') error_msg = _('Feature disabled.')
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
profile = Profile.objects.get_profile_by_contact_email(contact_email) profile = Profile.objects.get_profile_by_contact_email(contact_email)

View File

@ -46,17 +46,17 @@ class UserAvatarView(APIView):
(root, ext) = os.path.splitext(image_file.name.lower()) (root, ext) = os.path.splitext(image_file.name.lower())
if AVATAR_ALLOWED_FILE_EXTS and ext not in AVATAR_ALLOWED_FILE_EXTS: if AVATAR_ALLOWED_FILE_EXTS and ext not in AVATAR_ALLOWED_FILE_EXTS:
error_msg = _(u"%(ext)s is an invalid file extension. Authorized extensions are : %(valid_exts_list)s") % {'ext' : ext, 'valid_exts_list' : ", ".join(AVATAR_ALLOWED_FILE_EXTS)} error_msg = _("%(ext)s is an invalid file extension. Authorized extensions are : %(valid_exts_list)s") % {'ext' : ext, 'valid_exts_list' : ", ".join(AVATAR_ALLOWED_FILE_EXTS)}
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if image_file.size > AVATAR_MAX_SIZE: if image_file.size > AVATAR_MAX_SIZE:
error_msg = _(u"Your file is too big (%(size)s), the maximum allowed size is %(max_valid_size)s") % { 'size' : filesizeformat(image_file.size), 'max_valid_size' : filesizeformat(AVATAR_MAX_SIZE)} error_msg = _("Your file is too big (%(size)s), the maximum allowed size is %(max_valid_size)s") % { 'size' : filesizeformat(image_file.size), 'max_valid_size' : filesizeformat(AVATAR_MAX_SIZE)}
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
username = request.user.username username = request.user.username
count = Avatar.objects.filter(emailuser=username).count() count = Avatar.objects.filter(emailuser=username).count()
if AVATAR_MAX_AVATARS_PER_USER > 1 and count >= AVATAR_MAX_AVATARS_PER_USER: if AVATAR_MAX_AVATARS_PER_USER > 1 and count >= AVATAR_MAX_AVATARS_PER_USER:
error_msg = _(u"You already have %(nb_avatars)d avatars, and the maximum allowed is %(nb_max_avatars)d.") % { 'nb_avatars' : count, 'nb_max_avatars' : AVATAR_MAX_AVATARS_PER_USER} error_msg = _("You already have %(nb_avatars)d avatars, and the maximum allowed is %(nb_max_avatars)d.") % { 'nb_avatars' : count, 'nb_max_avatars' : AVATAR_MAX_AVATARS_PER_USER}
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
try: try:

View File

@ -2,7 +2,7 @@
import re import re
import datetime import datetime
import time import time
import urllib import urllib.request, urllib.parse, urllib.error
import logging import logging
from rest_framework import status from rest_framework import status
@ -79,7 +79,7 @@ def get_user_contact_email_dict(email_list):
email_list = set(email_list) email_list = set(email_list)
user_contact_email_dict = {} user_contact_email_dict = {}
for email in email_list: for email in email_list:
if not user_contact_email_dict.has_key(email): if email not in user_contact_email_dict:
user_contact_email_dict[email] = email2contact_email(email) user_contact_email_dict[email] = email2contact_email(email)
return user_contact_email_dict return user_contact_email_dict
@ -88,7 +88,7 @@ def get_user_name_dict(email_list):
email_list = set(email_list) email_list = set(email_list)
user_name_dict = {} user_name_dict = {}
for email in email_list: for email in email_list:
if not user_name_dict.has_key(email): if email not in user_name_dict:
user_name_dict[email] = email2nickname(email) user_name_dict[email] = email2nickname(email)
return user_name_dict return user_name_dict
@ -97,7 +97,7 @@ def get_repo_dict(repo_id_list):
repo_id_list = set(repo_id_list) repo_id_list = set(repo_id_list)
repo_dict = {} repo_dict = {}
for repo_id in repo_id_list: for repo_id in repo_id_list:
if not repo_dict.has_key(repo_id): if repo_id not in repo_dict:
repo_dict[repo_id] = '' repo_dict[repo_id] = ''
repo = seafile_api.get_repo(repo_id) repo = seafile_api.get_repo(repo_id)
if repo: if repo:
@ -110,10 +110,10 @@ def get_group_dict(group_id_list):
group_id_list = set(group_id_list) group_id_list = set(group_id_list)
group_dict = {} group_dict = {}
for group_id in group_id_list: for group_id in group_id_list:
if not group_dict.has_key(group_id): if group_id not in group_dict:
group_dict[group_id] = '' group_dict[group_id] = ''
group = ccnet_api.get_group(int(group_id)) group = ccnet_api.get_group(int(group_id))
print group print(group)
if group: if group:
group_dict[group_id] = group group_dict[group_id] = group
@ -154,29 +154,29 @@ def generate_links_header_for_paginator(base_url, page, per_page, total_count, o
else: else:
return False return False
if type(option_dict) is not dict: if not isinstance(option_dict, dict):
return '' return ''
query_dict = {'page': 1, 'per_page': per_page} query_dict = {'page': 1, 'per_page': per_page}
query_dict.update(option_dict) query_dict.update(option_dict)
# generate first page url # generate first page url
first_page_url = base_url + '?' + urllib.urlencode(query_dict) first_page_url = base_url + '?' + urllib.parse.urlencode(query_dict)
# generate last page url # generate last page url
last_page_query_dict = {'page': (total_count / per_page) + 1} last_page_query_dict = {'page': (total_count / per_page) + 1}
query_dict.update(last_page_query_dict) query_dict.update(last_page_query_dict)
last_page_url = base_url + '?' + urllib.urlencode(query_dict) last_page_url = base_url + '?' + urllib.parse.urlencode(query_dict)
# generate next page url # generate next page url
next_page_query_dict = {'page': page + 1} next_page_query_dict = {'page': page + 1}
query_dict.update(next_page_query_dict) query_dict.update(next_page_query_dict)
next_page_url = base_url + '?' + urllib.urlencode(query_dict) next_page_url = base_url + '?' + urllib.parse.urlencode(query_dict)
# generate prev page url # generate prev page url
prev_page_query_dict = {'page': page - 1} prev_page_query_dict = {'page': page - 1}
query_dict.update(prev_page_query_dict) query_dict.update(prev_page_query_dict)
prev_page_url = base_url + '?' + urllib.urlencode(query_dict) prev_page_url = base_url + '?' + urllib.parse.urlencode(query_dict)
# generate `Links` header # generate `Links` header
links_header = '' links_header = ''

View File

@ -2,7 +2,7 @@
import os import os
import logging import logging
import urllib2 import urllib.request, urllib.error, urllib.parse
import posixpath import posixpath
from rest_framework import status from rest_framework import status
@ -61,13 +61,13 @@ class WikiPagesView(APIView):
pages = get_wiki_pages(repo) pages = get_wiki_pages(repo)
wiki_pages_object = [] wiki_pages_object = []
for _, page_name in pages.iteritems(): for _, page_name in pages.items():
wiki_page_object = get_wiki_page_object(wiki, page_name) wiki_page_object = get_wiki_page_object(wiki, page_name)
wiki_pages_object.append(wiki_page_object) wiki_pages_object.append(wiki_page_object)
# sort pages by name # sort pages by name
wiki_pages_object.sort(lambda x, y: cmp(x['name'].lower(), wiki_pages_object.sort(
y['name'].lower())) key=lambda x: x['name'].lower())
return Response({ return Response({
"data": wiki_pages_object "data": wiki_pages_object
@ -161,7 +161,7 @@ class WikiPageView(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
url = get_inner_file_url(repo, wiki_dirent.obj_id, wiki_dirent.obj_name) url = get_inner_file_url(repo, wiki_dirent.obj_id, wiki_dirent.obj_name)
file_response = urllib2.urlopen(url) file_response = urllib.request.urlopen(url)
content = file_response.read() content = file_response.read()
wiki_page_object = get_wiki_page_object(wiki, page_name) wiki_page_object = get_wiki_page_object(wiki, page_name)
@ -332,7 +332,7 @@ class WikiPageContentView(APIView):
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
url = gen_inner_file_get_url(token, file_name) url = gen_inner_file_get_url(token, file_name)
file_response = urllib2.urlopen(url) file_response = urllib.request.urlopen(url)
content = file_response.read() content = file_response.read()
try: try:

View File

@ -47,7 +47,7 @@ class WikisView(APIView):
rtype = request.GET.get('type', "") rtype = request.GET.get('type', "")
if not rtype: if not rtype:
# set all to True, no filter applied # set all to True, no filter applied
filter_by = filter_by.fromkeys(filter_by.iterkeys(), True) filter_by = filter_by.fromkeys(iter(filter_by.keys()), True)
for f in rtype.split(','): for f in rtype.split(','):
f = f.strip() f = f.strip()

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-03-21 08:41 # Generated by Django 1.11.11 on 2018-03-21 08:41
from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models
import django.utils.timezone import django.utils.timezone
@ -41,6 +41,6 @@ class Migration(migrations.Migration):
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name='tokenv2', name='tokenv2',
unique_together=set([('user', 'platform', 'device_id')]), unique_together={('user', 'platform', 'device_id')},
), ),
] ]

View File

@ -4,6 +4,9 @@ import hmac
import datetime import datetime
from hashlib import sha1 from hashlib import sha1
import operator
from functools import cmp_to_key
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
@ -27,7 +30,7 @@ class Token(models.Model):
def generate_key(self): def generate_key(self):
unique = str(uuid.uuid4()) unique = str(uuid.uuid4())
return hmac.new(unique, digestmod=sha1).hexdigest() return hmac.new(unique.encode('utf-8'), digestmod=sha1).hexdigest()
def __unicode__(self): def __unicode__(self):
return self.key return self.key
@ -72,13 +75,12 @@ class TokenV2Manager(models.Manager):
the same category are listed by most recently used first the same category are listed by most recently used first
''' '''
ret = cmp(platform_priorities[d1.platform], platform_priorities[d2.platform]) if operator.eq(platform_priorities[d1.platform], platform_priorities[d2.platform]):
if ret != 0: return operator.lt(d2.last_accessed, d1.last_accessed)
return ret else:
return operator.lt(platform_priorities[d1.platform], platform_priorities[d2.platform])
return cmp(d2.last_accessed, d1.last_accessed) return [ d.as_dict() for d in sorted(devices, key=cmp_to_key(sort_devices)) ]
return [ d.as_dict() for d in sorted(devices, sort_devices) ]
def _get_token_by_user_device(self, username, platform, device_id): def _get_token_by_user_device(self, username, platform, device_id):
try: try:
@ -172,11 +174,11 @@ class TokenV2(models.Model):
def generate_key(self): def generate_key(self):
unique = str(uuid.uuid4()) unique = str(uuid.uuid4())
return hmac.new(unique, digestmod=sha1).hexdigest() return hmac.new(unique.encode('utf-8'), digestmod=sha1).hexdigest()
def __unicode__(self): def __unicode__(self):
return "TokenV2{user=%(user)s,device=%(device_name)s}" % \ return "TokenV2{user=%(user)s,device=%(device_name)s}" % \
dict(user=self.user,device_name=self.device_name) dict(user=self.user, device_name=self.device_name)
def is_desktop_client(self): def is_desktop_client(self):
return str(self.platform) in ('windows', 'linux', 'mac') return str(self.platform) in ('windows', 'linux', 'mac')

View File

@ -2,7 +2,7 @@
""" """
Provides various throttling policies. Provides various throttling policies.
""" """
from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.core.cache import cache as default_cache from django.core.cache import cache as default_cache
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured

View File

@ -104,12 +104,12 @@ def get_groups(email):
if len(msg) >= 1: if len(msg) >= 1:
mtime = get_timestamp(msg[0].timestamp) mtime = get_timestamp(msg[0].timestamp)
group = { group = {
"id":g.id, "id": g.id,
"name":g.group_name, "name": g.group_name,
"creator":g.creator_name, "creator": g.creator_name,
"ctime":g.timestamp, "ctime": g.timestamp,
"mtime":mtime, "mtime": mtime,
"msgnum":grpmsgs[g.id], "msgnum": grpmsgs[g.id],
} }
group_json.append(group) group_json.append(group)
@ -227,11 +227,11 @@ def group_msg_to_json(msg, get_all_replies):
replies = [] replies = []
for reply in msg.replies: for reply in msg.replies:
r = { r = {
'from_email' : reply.from_email, 'from_email': reply.from_email,
'nickname' : email2nickname(reply.from_email), 'nickname': email2nickname(reply.from_email),
'timestamp' : get_timestamp(reply.timestamp), 'timestamp': get_timestamp(reply.timestamp),
'msg' : reply.message, 'msg': reply.message,
'msgid' : reply.id, 'msgid': reply.id,
} }
replies.append(r) replies.append(r)

View File

@ -9,7 +9,7 @@ import datetime
import posixpath import posixpath
import re import re
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from urllib2 import quote from urllib.parse import quote
from rest_framework import parsers from rest_framework import parsers
from rest_framework import status from rest_framework import status
@ -129,13 +129,13 @@ except ImportError:
from pysearpc import SearpcError, SearpcObjEncoder from pysearpc import SearpcError, SearpcObjEncoder
import seaserv import seaserv
from seaserv import seafserv_threaded_rpc, \ from seaserv import seafserv_threaded_rpc, \
get_personal_groups_by_user, get_session_info, is_personal_repo, \ get_personal_groups_by_user, is_personal_repo, \
get_repo, check_permission, get_commits, is_passwd_set,\ get_repo, check_permission, get_commits,\
check_quota, list_share_repos, get_group_repos_by_owner, get_group_repoids, \ check_quota, list_share_repos, get_group_repos_by_owner, get_group_repoids, \
remove_share, get_group, \ remove_share, get_group, \
get_commit, get_file_id_by_path, MAX_DOWNLOAD_DIR_SIZE, edit_repo, \ get_commit, get_file_id_by_path, MAX_DOWNLOAD_DIR_SIZE, edit_repo, \
ccnet_threaded_rpc, get_personal_groups, seafile_api, \ ccnet_threaded_rpc, get_personal_groups, seafile_api, \
create_org, ccnet_api, send_message create_org, ccnet_api
from constance import config from constance import config
@ -345,11 +345,11 @@ class AccountInfo(APIView):
if name is not None: if name is not None:
if len(name) > 64: if len(name) > 64:
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u'Name is too long (maximum is 64 characters)')) _('Name is too long (maximum is 64 characters)'))
if "/" in name: if "/" in name:
return api_error(status.HTTP_400_BAD_REQUEST, return api_error(status.HTTP_400_BAD_REQUEST,
_(u"Name should not include '/'.")) _("Name should not include '/'."))
email_interval = request.data.get("email_notification_interval", None) email_interval = request.data.get("email_notification_interval", None)
if email_interval is not None: if email_interval is not None:
@ -524,7 +524,7 @@ class Search(APIView):
suffixes = [] suffixes = []
if len(custom_ftypes) > 0: if len(custom_ftypes) > 0:
for ftp in custom_ftypes: for ftp in custom_ftypes:
if SEARCH_FILEEXT.has_key(ftp): if ftp in SEARCH_FILEEXT:
for ext in SEARCH_FILEEXT[ftp]: for ext in SEARCH_FILEEXT[ftp]:
suffixes.append(ext) suffixes.append(ext)
@ -590,7 +590,7 @@ class Search(APIView):
e['permission'] = permission e['permission'] = permission
# get repo type # get repo type
if repo_type_map.has_key(repo_id): if repo_id in repo_type_map:
e['repo_type'] = repo_type_map[repo_id] e['repo_type'] = repo_type_map[repo_id]
else: else:
e['repo_type'] = '' e['repo_type'] = ''
@ -605,7 +605,7 @@ def repo_download_info(request, repo_id, gen_sync_token=True):
return api_error(status.HTTP_404_NOT_FOUND, 'Library not found.') return api_error(status.HTTP_404_NOT_FOUND, 'Library not found.')
# generate download url for client # generate download url for client
relay_id = get_session_info().id relay_id = 0
addr, port = get_ccnet_server_addr_port() addr, port = get_ccnet_server_addr_port()
email = request.user.username email = request.user.username
if gen_sync_token: if gen_sync_token:
@ -670,7 +670,7 @@ class Repos(APIView):
rtype = request.GET.get('type', "") rtype = request.GET.get('type', "")
if not rtype: if not rtype:
# set all to True, no filter applied # set all to True, no filter applied
filter_by = filter_by.fromkeys(filter_by.iterkeys(), True) filter_by = filter_by.fromkeys(iter(filter_by.keys()), True)
for f in rtype.split(','): for f in rtype.split(','):
f = f.strip() f = f.strip()
@ -695,14 +695,14 @@ class Repos(APIView):
ret_corrupted=True) ret_corrupted=True)
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
modifiers_set = set([x.last_modifier for x in owned_repos]) modifiers_set = {x.last_modifier for x in owned_repos}
for e in modifiers_set: for e in modifiers_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
if e not in nickname_dict: if e not in nickname_dict:
nickname_dict[e] = email2nickname(e) nickname_dict[e] = email2nickname(e)
owned_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) owned_repos.sort(key=lambda x: x.last_modify, reverse=True)
for r in owned_repos: for r in owned_repos:
# do not return virtual repos # do not return virtual repos
if r.is_virtual: if r.is_virtual:
@ -753,15 +753,15 @@ class Repos(APIView):
get_repos_with_admin_permission(email) get_repos_with_admin_permission(email)
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
owners_set = set([x.user for x in shared_repos]) owners_set = {x.user for x in shared_repos}
modifiers_set = set([x.last_modifier for x in shared_repos]) modifiers_set = {x.last_modifier for x in shared_repos}
for e in owners_set | modifiers_set: for e in owners_set | modifiers_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
if e not in nickname_dict: if e not in nickname_dict:
nickname_dict[e] = email2nickname(e) nickname_dict[e] = email2nickname(e)
shared_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) shared_repos.sort(key=lambda x: x.last_modify, reverse=True)
for r in shared_repos: for r in shared_repos:
if q and q.lower() not in r.name.lower(): if q and q.lower() not in r.name.lower():
continue continue
@ -775,7 +775,7 @@ class Repos(APIView):
if not is_web_request(request): if not is_web_request(request):
continue continue
r.password_need = is_passwd_set(r.repo_id, email) r.password_need = seafile_api.is_password_set(r.repo_id, email)
repo = { repo = {
"type": "srepo", "type": "srepo",
"id": r.repo_id, "id": r.repo_id,
@ -784,7 +784,6 @@ class Repos(APIView):
"owner_contact_email": contact_email_dict.get(r.user, ''), "owner_contact_email": contact_email_dict.get(r.user, ''),
"name": r.repo_name, "name": r.repo_name,
"owner_nickname": nickname_dict.get(r.user, ''), "owner_nickname": nickname_dict.get(r.user, ''),
"owner_name": nickname_dict.get(r.user, ''),
"mtime": r.last_modify, "mtime": r.last_modify,
"mtime_relative": translate_seahub_time(r.last_modify), "mtime_relative": translate_seahub_time(r.last_modify),
"modifier_email": r.last_modifier, "modifier_email": r.last_modifier,
@ -816,11 +815,11 @@ class Repos(APIView):
else: else:
group_repos = seafile_api.get_group_repos_by_user(email) group_repos = seafile_api.get_group_repos_by_user(email)
group_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) group_repos.sort(key=lambda x: x.last_modify, reverse=True)
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
share_from_set = set([x.user for x in group_repos]) share_from_set = {x.user for x in group_repos}
modifiers_set = set([x.last_modifier for x in group_repos]) modifiers_set = {x.last_modifier for x in group_repos}
for e in modifiers_set | share_from_set: for e in modifiers_set | share_from_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
@ -863,8 +862,8 @@ class Repos(APIView):
public_repos = list_inner_pub_repos(request) public_repos = list_inner_pub_repos(request)
# Reduce memcache fetch ops. # Reduce memcache fetch ops.
share_from_set = set([x.user for x in public_repos]) share_from_set = {x.user for x in public_repos}
modifiers_set = set([x.last_modifier for x in public_repos]) modifiers_set = {x.last_modifier for x in public_repos}
for e in modifiers_set | share_from_set: for e in modifiers_set | share_from_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
@ -906,7 +905,7 @@ class Repos(APIView):
org_id = request.user.org.org_id org_id = request.user.org.org_id
try: try:
send_message('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id)) seafile_api.publish_event('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id))
except Exception as e: except Exception as e:
logger.error('Error when sending user-login message: %s' % str(e)) logger.error('Error when sending user-login message: %s' % str(e))
response = HttpResponse(json.dumps(repos_json), status=200, response = HttpResponse(json.dumps(repos_json), status=200,
@ -985,7 +984,7 @@ class Repos(APIView):
return None, api_error(status.HTTP_403_FORBIDDEN, return None, api_error(status.HTTP_403_FORBIDDEN,
'NOT allow to create encrypted library.') 'NOT allow to create encrypted library.')
if org_id > 0: if org_id and org_id > 0:
repo_id = seafile_api.create_org_repo(repo_name, repo_id = seafile_api.create_org_repo(repo_name,
repo_desc, username, org_id, passwd, repo_desc, username, org_id, passwd,
enc_version=settings.ENCRYPTED_LIBRARY_VERSION) enc_version=settings.ENCRYPTED_LIBRARY_VERSION)
@ -1049,7 +1048,7 @@ class Repos(APIView):
return None, api_error(status.HTTP_400_BAD_REQUEST, return None, api_error(status.HTTP_400_BAD_REQUEST,
'You must provide magic, random_key and enc_version.') 'You must provide magic, random_key and enc_version.')
if org_id > 0: if org_id and org_id > 0:
repo_id = seafile_api.create_org_enc_repo(repo_id, repo_name, repo_desc, repo_id = seafile_api.create_org_enc_repo(repo_id, repo_name, repo_desc,
username, magic, random_key, username, magic, random_key,
salt, enc_version, org_id) salt, enc_version, org_id)
@ -1196,7 +1195,7 @@ def set_repo_password(request, repo, password):
if ENABLE_RESET_ENCRYPTED_REPO_PASSWORD: if ENABLE_RESET_ENCRYPTED_REPO_PASSWORD:
add_encrypted_repo_secret_key_to_database(repo_id, password) add_encrypted_repo_secret_key_to_database(repo_id, password)
except SearpcError, e: except SearpcError as e:
if e.msg == 'Bad arguments': if e.msg == 'Bad arguments':
return api_error(status.HTTP_400_BAD_REQUEST, e.msg) return api_error(status.HTTP_400_BAD_REQUEST, e.msg)
elif e.msg == 'Repo is not encrypted': elif e.msg == 'Repo is not encrypted':
@ -1254,14 +1253,14 @@ class Repo(APIView):
root_id = current_commit.root_id if current_commit else None root_id = current_commit.root_id if current_commit else None
repo_json = { repo_json = {
"type":"repo", "type": "repo",
"id":repo.id, "id": repo.id,
"owner":owner, "owner": owner,
"name":repo.name, "name": repo.name,
"mtime":repo.latest_modify, "mtime": repo.latest_modify,
"size":repo.size, "size": repo.size,
"encrypted":repo.encrypted, "encrypted": repo.encrypted,
"root":root_id, "root": root_id,
"permission": check_permission(repo.id, username), "permission": check_permission(repo.id, username),
"modifier_email": repo.last_modifier, "modifier_email": repo.last_modifier,
"modifier_contact_email": email2contact_email(repo.last_modifier), "modifier_contact_email": email2contact_email(repo.last_modifier),
@ -1583,7 +1582,7 @@ class RepoOwner(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if org_id and not ccnet_api.org_user_exists(org_id, new_owner): if org_id and not ccnet_api.org_user_exists(org_id, new_owner):
error_msg = _(u'User %s not found in organization.') % new_owner error_msg = _('User %s not found in organization.') % new_owner
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check # permission check
@ -1598,12 +1597,12 @@ class RepoOwner(APIView):
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
if not new_owner_obj.permissions.can_add_repo(): if not new_owner_obj.permissions.can_add_repo():
error_msg = _(u'Transfer failed: role of %s is %s, can not add library.') % \ error_msg = _('Transfer failed: role of %s is %s, can not add library.') % \
(new_owner, new_owner_obj.role) (new_owner, new_owner_obj.role)
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
if new_owner == repo_owner: if new_owner == repo_owner:
error_msg = _(u"Library can not be transferred to owner.") error_msg = _("Library can not be transferred to owner.")
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
pub_repos = [] pub_repos = []
@ -1741,7 +1740,7 @@ class FileBlockDownloadLinkView(APIView):
'You do not have permission to access this repo.') 'You do not have permission to access this repo.')
if check_quota(repo_id) < 0: if check_quota(repo_id) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
token = seafile_api.get_fileserver_access_token( token = seafile_api.get_fileserver_access_token(
repo_id, file_id, 'downloadblks', request.user.username) repo_id, file_id, 'downloadblks', request.user.username)
@ -1777,7 +1776,7 @@ class UploadLinkView(APIView):
'You do not have permission to access this folder.') 'You do not have permission to access this folder.')
if check_quota(repo_id) < 0: if check_quota(repo_id) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
token = seafile_api.get_fileserver_access_token(repo_id, token = seafile_api.get_fileserver_access_token(repo_id,
'dummy', 'upload', request.user.username, use_onetime=False) 'dummy', 'upload', request.user.username, use_onetime=False)
@ -1825,7 +1824,7 @@ class UpdateLinkView(APIView):
'You do not have permission to access this folder.') 'You do not have permission to access this folder.')
if check_quota(repo_id) < 0: if check_quota(repo_id) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
token = seafile_api.get_fileserver_access_token(repo_id, token = seafile_api.get_fileserver_access_token(repo_id,
'dummy', 'update', request.user.username, use_onetime=False) 'dummy', 'update', request.user.username, use_onetime=False)
@ -1869,7 +1868,7 @@ class UploadBlksLinkView(APIView):
'You do not have permission to access this folder.') 'You do not have permission to access this folder.')
if check_quota(repo_id) < 0: if check_quota(repo_id) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
token = seafile_api.get_fileserver_access_token(repo_id, token = seafile_api.get_fileserver_access_token(repo_id,
'dummy', 'upload-blks-api', request.user.username, use_onetime=False) 'dummy', 'upload-blks-api', request.user.username, use_onetime=False)
@ -1914,7 +1913,7 @@ class UploadBlksLinkView(APIView):
'You do not have permission to access this folder.') 'You do not have permission to access this folder.')
if check_quota(repo_id) < 0: if check_quota(repo_id) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
token = seafile_api.get_fileserver_access_token(repo_id, token = seafile_api.get_fileserver_access_token(repo_id,
'dummy', 'upload', request.user.username, use_onetime=False) 'dummy', 'upload', request.user.username, use_onetime=False)
@ -1962,7 +1961,7 @@ class UpdateBlksLinkView(APIView):
'You do not have permission to access this folder.') 'You do not have permission to access this folder.')
if check_quota(repo_id) < 0: if check_quota(repo_id) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
token = seafile_api.get_fileserver_access_token(repo_id, token = seafile_api.get_fileserver_access_token(repo_id,
'dummy', 'update-blks-api', request.user.username, use_onetime=False) 'dummy', 'update-blks-api', request.user.username, use_onetime=False)
@ -2012,7 +2011,7 @@ def get_dir_file_recursively(username, repo_id, path, all_dirs):
file_list = [item for item in all_dirs if item['type'] == 'file'] file_list = [item for item in all_dirs if item['type'] == 'file']
contact_email_dict = {} contact_email_dict = {}
nickname_dict = {} nickname_dict = {}
modifiers_set = set([x['modifier_email'] for x in file_list]) modifiers_set = {x['modifier_email'] for x in file_list}
for e in modifiers_set: for e in modifiers_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
@ -2042,7 +2041,7 @@ def get_dir_entrys_by_id(request, repo, path, dir_id, request_type=None):
dirs = seafile_api.list_dir_with_perm(repo.id, path, dir_id, dirs = seafile_api.list_dir_with_perm(repo.id, path, dir_id,
username, -1, -1) username, -1, -1)
dirs = dirs if dirs else [] dirs = dirs if dirs else []
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
return api_error(HTTP_520_OPERATION_FAILED, return api_error(HTTP_520_OPERATION_FAILED,
"Failed to list dir.") "Failed to list dir.")
@ -2084,7 +2083,7 @@ def get_dir_entrys_by_id(request, repo, path, dir_id, request_type=None):
# Use dict to reduce memcache fetch cost in large for-loop. # Use dict to reduce memcache fetch cost in large for-loop.
contact_email_dict = {} contact_email_dict = {}
nickname_dict = {} nickname_dict = {}
modifiers_set = set([x['modifier_email'] for x in file_list]) modifiers_set = {x['modifier_email'] for x in file_list}
for e in modifiers_set: for e in modifiers_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
@ -2108,8 +2107,8 @@ def get_dir_entrys_by_id(request, repo, path, dir_id, request_type=None):
if normalize_file_path(file_path) in starred_files: if normalize_file_path(file_path) in starred_files:
e['starred'] = True e['starred'] = True
dir_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) dir_list.sort(key=lambda x: x['name'].lower())
file_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) file_list.sort(key=lambda x: x['name'].lower())
if request_type == 'f': if request_type == 'f':
dentrys = file_list dentrys = file_list
@ -2142,7 +2141,7 @@ def get_shared_link(request, repo_id, path):
try: try:
fs.save() fs.save()
except IntegrityError, e: except IntegrityError as e:
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, e.msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, e.msg)
http_or_https = request.is_secure() and 'https' or 'http' http_or_https = request.is_secure() and 'https' or 'http'
@ -2207,7 +2206,7 @@ def get_repo_file(request, repo_id, file_id, file_name, op,
def reloaddir(request, repo, parent_dir): def reloaddir(request, repo, parent_dir):
try: try:
dir_id = seafile_api.get_dir_id_by_path(repo.id, parent_dir) dir_id = seafile_api.get_dir_id_by_path(repo.id, parent_dir)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
return api_error(HTTP_520_OPERATION_FAILED, return api_error(HTTP_520_OPERATION_FAILED,
"Failed to get dir id by path") "Failed to get dir id by path")
@ -2260,7 +2259,7 @@ class OpDeleteView(APIView):
allowed_file_names = [] allowed_file_names = []
locked_files = get_locked_files_by_dir(request, repo_id, parent_dir) locked_files = get_locked_files_by_dir(request, repo_id, parent_dir)
for file_name in file_names.split(':'): for file_name in file_names.split(':'):
if file_name not in locked_files.keys(): if file_name not in list(locked_files.keys()):
# file is not locked # file is not locked
allowed_file_names.append(file_name) allowed_file_names.append(file_name)
elif locked_files[file_name] == username: elif locked_files[file_name] == username:
@ -2333,7 +2332,7 @@ class OpMoveView(APIView):
allowed_obj_names = [] allowed_obj_names = []
locked_files = get_locked_files_by_dir(request, repo_id, parent_dir) locked_files = get_locked_files_by_dir(request, repo_id, parent_dir)
for file_name in obj_names.split(':'): for file_name in obj_names.split(':'):
if file_name not in locked_files.keys(): if file_name not in list(locked_files.keys()):
# file is not locked # file is not locked
allowed_obj_names.append(file_name) allowed_obj_names.append(file_name)
elif locked_files[file_name] == username: elif locked_files[file_name] == username:
@ -2373,7 +2372,7 @@ class OpMoveView(APIView):
# check if above quota for dst repo # check if above quota for dst repo
if seafile_api.check_quota(dst_repo, total_size) < 0: if seafile_api.check_quota(dst_repo, total_size) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
# make new name # make new name
dst_dirents = seafile_api.list_dir_by_path(dst_repo, dst_dir) dst_dirents = seafile_api.list_dir_by_path(dst_repo, dst_dir)
@ -2487,7 +2486,7 @@ class OpCopyView(APIView):
# check if above quota for dst repo # check if above quota for dst repo
if seafile_api.check_quota(dst_repo, total_size) < 0: if seafile_api.check_quota(dst_repo, total_size) < 0:
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
# make new name # make new name
dst_dirents = seafile_api.list_dir_by_path(dst_repo, dst_dir) dst_dirents = seafile_api.list_dir_by_path(dst_repo, dst_dir)
@ -2849,7 +2848,7 @@ class FileView(APIView):
try: try:
seafile_api.rename_file(repo_id, parent_dir, oldname, newname, seafile_api.rename_file(repo_id, parent_dir, oldname, newname,
username) username)
except SearpcError,e: except SearpcError as e:
return api_error(HTTP_520_OPERATION_FAILED, return api_error(HTTP_520_OPERATION_FAILED,
"Failed to rename file: %s" % e) "Failed to rename file: %s" % e)
@ -2892,7 +2891,7 @@ class FileView(APIView):
dst_dir, new_filename, dst_dir, new_filename,
replace=False, username=username, replace=False, username=username,
need_progress=0, synchronous=1) need_progress=0, synchronous=1)
except SearpcError, e: except SearpcError as e:
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
"SearpcError:" + e.msg) "SearpcError:" + e.msg)
@ -2984,7 +2983,7 @@ class FileView(APIView):
try: try:
seafile_api.post_empty_file(repo_id, parent_dir, seafile_api.post_empty_file(repo_id, parent_dir,
new_file_name, username) new_file_name, username)
except SearpcError, e: except SearpcError as e:
return api_error(HTTP_520_OPERATION_FAILED, return api_error(HTTP_520_OPERATION_FAILED,
'Failed to create file.') 'Failed to create file.')
@ -3038,7 +3037,7 @@ class FileView(APIView):
try: try:
seafile_api.lock_file(repo_id, path.lstrip('/'), username, expire) seafile_api.lock_file(repo_id, path.lstrip('/'), username, expire)
return Response('success', status=status.HTTP_200_OK) return Response('success', status=status.HTTP_200_OK)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal error')
@ -3052,7 +3051,7 @@ class FileView(APIView):
try: try:
seafile_api.unlock_file(repo_id, path.lstrip('/')) seafile_api.unlock_file(repo_id, path.lstrip('/'))
return Response('success', status=status.HTTP_200_OK) return Response('success', status=status.HTTP_200_OK)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal error')
else: else:
@ -3617,7 +3616,7 @@ class DirView(APIView):
resp = Response('success', status=status.HTTP_201_CREATED) resp = Response('success', status=status.HTTP_201_CREATED)
uri = reverse('DirView', args=[repo_id], request=request) uri = reverse('DirView', args=[repo_id], request=request)
resp['Location'] = uri + '?p=' + quote( resp['Location'] = uri + '?p=' + quote(
parent_dir.encode('utf-8') + '/' + new_dir_name.encode('utf-8')) parent_dir.encode('utf-8') + '/'.encode('utf-8') + new_dir_name.encode('utf-8'))
return resp return resp
elif operation.lower() == 'rename': elif operation.lower() == 'rename':
@ -3646,7 +3645,7 @@ class DirView(APIView):
seafile_api.rename_file(repo_id, parent_dir, old_dir_name, seafile_api.rename_file(repo_id, parent_dir, old_dir_name,
checked_newname, username) checked_newname, username)
return Response('success', status=status.HTTP_200_OK) return Response('success', status=status.HTTP_200_OK)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
return api_error(HTTP_520_OPERATION_FAILED, return api_error(HTTP_520_OPERATION_FAILED,
'Failed to rename folder.') 'Failed to rename folder.')
@ -3786,13 +3785,13 @@ class DirSubRepoView(APIView):
error_msg = 'Bad arguments' error_msg = 'Bad arguments'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
elif e.msg == 'Incorrect password': elif e.msg == 'Incorrect password':
error_msg = _(u'Wrong password') error_msg = _('Wrong password')
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
elif e.msg == 'Internal server error': elif e.msg == 'Internal server error':
error_msg = _(u'Internal server error') error_msg = _('Internal server error')
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
else: else:
error_msg = _(u'Decrypt library error') error_msg = _('Decrypt library error')
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
# create sub-lib for encrypted repo # create sub-lib for encrypted repo
@ -3883,7 +3882,7 @@ class BeSharedRepos(APIView):
shared_repos.append(r) shared_repos.append(r)
if not CLOUD_MODE: if not CLOUD_MODE:
shared_repos += seaserv.list_inner_pub_repos(username) shared_repos += seafile_api.get_inner_pub_repo_list()
return HttpResponse(json.dumps(shared_repos, cls=SearpcObjEncoder), return HttpResponse(json.dumps(shared_repos, cls=SearpcObjEncoder),
status=200, content_type=json_content_type) status=200, content_type=json_content_type)
@ -3960,7 +3959,7 @@ class SharedFileDetailView(APIView):
file_id = seafile_api.get_file_id_by_path(repo_id, path) file_id = seafile_api.get_file_id_by_path(repo_id, path)
commits = get_file_revisions_after_renamed(repo_id, path) commits = get_file_revisions_after_renamed(repo_id, path)
c = commits[0] c = commits[0]
except SearpcError, e: except SearpcError as e:
return api_error(HTTP_520_OPERATION_FAILED, return api_error(HTTP_520_OPERATION_FAILED,
"Failed to get file id by path.") "Failed to get file id by path.")
@ -4089,7 +4088,7 @@ class SharedDirView(APIView):
dirs = seafserv_threaded_rpc.list_dir_with_perm(repo_id, real_path, dir_id, dirs = seafserv_threaded_rpc.list_dir_with_perm(repo_id, real_path, dir_id,
username, -1, -1) username, -1, -1)
dirs = dirs if dirs else [] dirs = dirs if dirs else []
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
return api_error(HTTP_520_OPERATION_FAILED, "Failed to list dir.") return api_error(HTTP_520_OPERATION_FAILED, "Failed to list dir.")
@ -4115,8 +4114,8 @@ class SharedDirView(APIView):
else: else:
file_list.append(entry) file_list.append(entry)
dir_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) dir_list.sort(key=lambda x: x['name'].lower())
file_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) file_list.sort(key=lambda x: x['name'].lower())
dentrys = dir_list + file_list dentrys = dir_list + file_list
content_type = 'application/json; charset=utf-8' content_type = 'application/json; charset=utf-8'
@ -4298,7 +4297,7 @@ class SharedRepo(APIView):
try: try:
seafile_api.share_repo(repo_id, username, u, permission) seafile_api.share_repo(repo_id, username, u, permission)
shared_users.append(u) shared_users.append(u)
except SearpcError, e: except SearpcError as e:
logger.error(e) logger.error(e)
notsharable_errors.append(e) notsharable_errors.append(e)
@ -4313,7 +4312,7 @@ class SharedRepo(APIView):
for s_user in shared_users: for s_user in shared_users:
try: try:
remove_share(repo_id, username, s_user) remove_share(repo_id, username, s_user)
except SearpcError, e: except SearpcError as e:
# ignoring this error, go to next unsharing # ignoring this error, go to next unsharing
continue continue
@ -4348,7 +4347,7 @@ class SharedRepo(APIView):
try: try:
seafile_api.set_group_repo(repo_id, seafile_api.set_group_repo(repo_id,
group_id, username, permission) group_id, username, permission)
except SearpcError, e: except SearpcError as e:
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
"Searpc Error: " + e.msg) "Searpc Error: " + e.msg)
try: try:
@ -4555,7 +4554,7 @@ class Groups(APIView):
group_id = ccnet_api.create_group(group_name, username) group_id = ccnet_api.create_group(group_name, username)
return HttpResponse(json.dumps({'success': True, 'group_id': group_id}), return HttpResponse(json.dumps({'success': True, 'group_id': group_id}),
content_type=content_type) content_type=content_type)
except SearpcError, e: except SearpcError as e:
result['error'] = e.msg result['error'] = e.msg
return HttpResponse(json.dumps(result), status=500, return HttpResponse(json.dumps(result), status=500,
content_type=content_type) content_type=content_type)
@ -4648,7 +4647,7 @@ class GroupMembers(APIView):
try: try:
ccnet_threaded_rpc.group_add_member(group.id, request.user.username, user_name) ccnet_threaded_rpc.group_add_member(group.id, request.user.username, user_name)
except SearpcError, e: except SearpcError as e:
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Unable to add user to group') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Unable to add user to group')
return HttpResponse(json.dumps({'success': True}), status=200, content_type=json_content_type) return HttpResponse(json.dumps({'success': True}), status=200, content_type=json_content_type)
@ -4673,7 +4672,7 @@ class GroupMembers(APIView):
try: try:
ccnet_threaded_rpc.group_remove_member(group.id, request.user.username, user_name) ccnet_threaded_rpc.group_remove_member(group.id, request.user.username, user_name)
except SearpcError, e: except SearpcError as e:
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Unable to add user to group') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Unable to add user to group')
return HttpResponse(json.dumps({'success': True}), status=200, content_type=json_content_type) return HttpResponse(json.dumps({'success': True}), status=200, content_type=json_content_type)
@ -4783,14 +4782,14 @@ class GroupRepos(APIView):
else: else:
repos = seafile_api.get_repos_by_group(group.id) repos = seafile_api.get_repos_by_group(group.id)
repos.sort(lambda x, y: cmp(y.last_modified, x.last_modified)) repos.sort(key=lambda x: x.last_modified, reverse=True)
group.is_staff = is_group_staff(group, request.user) group.is_staff = is_group_staff(group, request.user)
# Use dict to reduce memcache fetch cost in large for-loop. # Use dict to reduce memcache fetch cost in large for-loop.
contact_email_dict = {} contact_email_dict = {}
nickname_dict = {} nickname_dict = {}
owner_set = set([x.user for x in repos]) owner_set = {x.user for x in repos}
modifiers_set = set([x.modifier for x in repos]) modifiers_set = {x.modifier for x in repos}
for e in owner_set | modifiers_set: for e in owner_set | modifiers_set:
if e not in contact_email_dict: if e not in contact_email_dict:
contact_email_dict[e] = email2contact_email(e) contact_email_dict[e] = email2contact_email(e)
@ -4949,7 +4948,7 @@ class OfficeConvertQueryStatus(APIView):
else: else:
ret['success'] = True ret['success'] = True
ret['status'] = d.status ret['status'] = d.status
except Exception, e: except Exception as e:
logging.exception('failed to call query_office_convert_status') logging.exception('failed to call query_office_convert_status')
ret['error'] = str(e) ret['error'] = str(e)

View File

@ -19,9 +19,9 @@ def load_backend(path):
module, attr = path[:i], path[i+1:] module, attr = path[:i], path[i+1:]
try: try:
mod = import_module(module) mod = import_module(module)
except ImportError, e: except ImportError as e:
raise ImproperlyConfigured('Error importing authentication backend %s: "%s"' % (module, e)) raise ImproperlyConfigured('Error importing authentication backend %s: "%s"' % (module, e))
except ValueError, e: except ValueError as e:
raise ImproperlyConfigured('Error importing authentication backends. Is AUTHENTICATION_BACKENDS a correctly defined list or tuple?') raise ImproperlyConfigured('Error importing authentication backends. Is AUTHENTICATION_BACKENDS a correctly defined list or tuple?')
try: try:
cls = getattr(mod, attr) cls = getattr(mod, attr)

View File

@ -194,7 +194,7 @@ class SeafileRemoteUserBackend(AuthBackend):
""" """
user_info = {} user_info = {}
for header, user_info_key in self.remote_user_attribute_map.items(): for header, user_info_key in list(self.remote_user_attribute_map.items()):
value = request.META.get(header, None) value = request.META.get(header, None)
if value: if value:
user_info[user_info_key] = value user_info[user_info_key] = value

View File

@ -112,7 +112,7 @@ class PasswordResetForm(forms.Form):
Validates that a user exists with the given e-mail address. Validates that a user exists with the given e-mail address.
""" """
if not IS_EMAIL_CONFIGURED: if not IS_EMAIL_CONFIGURED:
raise forms.ValidationError(_(u'Failed to send email, email service is not properly configured, please contact administrator.')) raise forms.ValidationError(_('Failed to send email, email service is not properly configured, please contact administrator.'))
email = self.cleaned_data["email"].lower().strip() email = self.cleaned_data["email"].lower().strip()

View File

@ -122,7 +122,7 @@ class SeafileRemoteUserMiddleware(MiddlewareMixin):
if not user: if not user:
if not getattr(settings, 'REMOTE_USER_CREATE_UNKNOWN_USER', True): if not getattr(settings, 'REMOTE_USER_CREATE_UNKNOWN_USER', True):
return render(request, 'remote_user/create_unknown_user_false.html') return render(request, 'remote_user/create_unknown_user_false.html')
return render(request, 'remote_user/error.html') return render(request, 'remote_user/error.html')
if user: if user:
if not user.is_active: if not user.is_active:

View File

@ -1,7 +1,7 @@
# Copyright (c) 2012-2016 Seafile Ltd. # Copyright (c) 2012-2016 Seafile Ltd.
import datetime import datetime
import hashlib import hashlib
import urllib import urllib.request, urllib.parse, urllib.error
import logging import logging
# import auth # import auth
@ -21,7 +21,7 @@ def get_hexdigest(algorithm, salt, raw_password):
Returns a string of the hexdigest of the given plaintext password and salt Returns a string of the hexdigest of the given plaintext password and salt
using the given algorithm ('md5', 'sha1' or 'crypt'). using the given algorithm ('md5', 'sha1' or 'crypt').
""" """
raw_password, salt = smart_str(raw_password), smart_str(salt) raw_password, salt = smart_str(raw_password).encode('utf-8'), smart_str(salt).encode('utf-8')
if algorithm == 'crypt': if algorithm == 'crypt':
try: try:
import crypt import crypt
@ -65,7 +65,7 @@ class AnonymousUser(object):
return 'AnonymousUser' return 'AnonymousUser'
def __str__(self): def __str__(self):
return unicode(self).encode('utf-8') return str(self).encode('utf-8')
def __eq__(self, other): def __eq__(self, other):
return isinstance(other, self.__class__) return isinstance(other, self.__class__)
@ -156,7 +156,7 @@ class SocialAuthUser(models.Model):
class Meta: class Meta:
"""Meta data""" """Meta data"""
app_label = "seahub.work_weixin" app_label = "base"
unique_together = ('provider', 'uid') unique_together = ('provider', 'uid')
db_table = 'social_auth_usersocialauth' db_table = 'social_auth_usersocialauth'

View File

@ -72,7 +72,7 @@ class PasswordResetTokenGenerator(object):
return "%s-%s" % (ts_b36, hash) return "%s-%s" % (ts_b36, hash)
def _num_days(self, dt): def _num_days(self, dt):
return (dt - date(2001,1,1)).days return (dt - date(2001, 1, 1)).days
def _today(self): def _today(self):
# Used for mocking in tests # Used for mocking in tests

View File

@ -217,7 +217,7 @@ def login_simple_check(request):
raise Http404 raise Http404
today = datetime.now().strftime('%Y-%m-%d') today = datetime.now().strftime('%Y-%m-%d')
expect = hashlib.md5(settings.SECRET_KEY+username+today).hexdigest() expect = hashlib.md5((settings.SECRET_KEY+username+today).encode('utf-8')).hexdigest()
if expect == random_key: if expect == random_key:
try: try:
user = User.objects.get(email=username) user = User.objects.get(email=username)
@ -313,9 +313,9 @@ def password_reset(request, is_admin_site=False, template_name='registration/pas
opts['domain_override'] = get_current_site(request).domain opts['domain_override'] = get_current_site(request).domain
try: try:
form.save(**opts) form.save(**opts)
except Exception, e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
messages.error(request, _(u'Failed to send email, please contact administrator.')) messages.error(request, _('Failed to send email, please contact administrator.'))
return render(request, template_name, { return render(request, template_name, {
'form': form, 'form': form,
}) })

View File

@ -16,7 +16,7 @@ def avatar_img(avatar, size):
if not avatar.thumbnail_exists(size): if not avatar.thumbnail_exists(size):
avatar.create_thumbnail(size) avatar.create_thumbnail(size)
return mark_safe("""<img src="%s" alt="%s" width="%s" height="%s" />""" % return mark_safe("""<img src="%s" alt="%s" width="%s" height="%s" />""" %
(avatar.avatar_url(size), unicode(avatar), size, size)) (avatar.avatar_url(size), str(avatar), size, size))
class UploadAvatarForm(forms.Form): class UploadAvatarForm(forms.Form):
@ -40,7 +40,7 @@ class UploadAvatarForm(forms.Form):
if AVATAR_MAX_AVATARS_PER_USER > 1 and \ if AVATAR_MAX_AVATARS_PER_USER > 1 and \
count >= AVATAR_MAX_AVATARS_PER_USER: count >= AVATAR_MAX_AVATARS_PER_USER:
raise forms.ValidationError( raise forms.ValidationError(
_(u"You already have %(nb_avatars)d avatars, and the maximum allowed is %(nb_max_avatars)d.") % _("You already have %(nb_avatars)d avatars, and the maximum allowed is %(nb_max_avatars)d.") %
{ 'nb_avatars' : count, 'nb_max_avatars' : AVATAR_MAX_AVATARS_PER_USER}) { 'nb_avatars' : count, 'nb_max_avatars' : AVATAR_MAX_AVATARS_PER_USER})
return return

View File

@ -32,9 +32,9 @@ class Command(BaseCommand):
for avatar in Avatar.objects.all(): for avatar in Avatar.objects.all():
try: try:
self._save(avatar.avatar.name, avatar.avatar) self._save(avatar.avatar.name, avatar.avatar)
print "SUCCESS: migrated Avatar path=%s user=%s" % (avatar.avatar.name, avatar.emailuser) print("SUCCESS: migrated Avatar path=%s user=%s" % (avatar.avatar.name, avatar.emailuser))
except AvatarNotFoundError: except AvatarNotFoundError:
print "ERROR: Avatar file not found: path=%s user=%s. Skip." % (avatar.avatar.name, avatar.emailuser) print("ERROR: Avatar file not found: path=%s user=%s. Skip." % (avatar.avatar.name, avatar.emailuser))
continue continue
# try: # try:
@ -50,10 +50,10 @@ class Command(BaseCommand):
in the name will be converted to forward '/'. in the name will be converted to forward '/'.
""" """
name = name.replace('\\', '/') name = name.replace('\\', '/')
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
try: try:
binary = content.read() binary = content.read()
except AttributeError, IOError: except AttributeError as IOError:
raise AvatarNotFoundError raise AvatarNotFoundError
size = len(binary) size = len(binary)
@ -78,7 +78,7 @@ class Command(BaseCommand):
return name return name
def exists(self, name): def exists(self, name):
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
query = 'SELECT COUNT(*) FROM %(table)s WHERE %(name_md5_column)s = %%s' query = 'SELECT COUNT(*) FROM %(table)s WHERE %(name_md5_column)s = %%s'
query %= self.__dict__ query %= self.__dict__
cursor = connection.cursor() cursor = connection.cursor()

View File

@ -11,5 +11,5 @@ class Command(BaseCommand):
def handle(self, **options): def handle(self, **options):
for avatar in Avatar.objects.all(): for avatar in Avatar.objects.all():
for size in AUTO_GENERATE_AVATAR_SIZES: for size in AUTO_GENERATE_AVATAR_SIZES:
print "Rebuilding Avatar id=%s at size %s." % (avatar.id, size) print("Rebuilding Avatar id=%s at size %s." % (avatar.id, size))
avatar.create_thumbnail(size) avatar.create_thumbnail(size)

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-03-21 08:42 # Generated by Django 1.11.11 on 2018-03-21 08:42
from __future__ import unicode_literals
import datetime import datetime
from django.db import migrations, models from django.db import migrations, models

View File

@ -14,10 +14,10 @@ from django.utils.encoding import smart_str
from django.db.models import signals from django.db.models import signals
try: try:
from cStringIO import StringIO from io import BytesIO
dir(StringIO) # Placate PyFlakes dir(BytesIO) # Placate PyFlakes
except ImportError: except ImportError:
from StringIO import StringIO from io import BytesIO
try: try:
from PIL import Image from PIL import Image
@ -39,7 +39,7 @@ def avatar_file_path(instance=None, filename=None, size=None, ext=None):
if isinstance(instance, Avatar): if isinstance(instance, Avatar):
tmppath = [AVATAR_STORAGE_DIR] tmppath = [AVATAR_STORAGE_DIR]
if AVATAR_HASH_USERDIRNAMES: if AVATAR_HASH_USERDIRNAMES:
tmp = hashlib.md5(instance.emailuser).hexdigest() tmp = hashlib.md5(instance.emailuser.encode('utf-8')).hexdigest()
tmppath.extend([tmp[0], tmp[1], tmp[2:]]) tmppath.extend([tmp[0], tmp[1], tmp[2:]])
else: else:
tmppath.append(instance.emailuser) tmppath.append(instance.emailuser)
@ -63,7 +63,7 @@ def avatar_file_path(instance=None, filename=None, size=None, ext=None):
# File doesn't exist yet # File doesn't exist yet
if AVATAR_HASH_FILENAMES: if AVATAR_HASH_FILENAMES:
(root, ext) = os.path.splitext(filename) (root, ext) = os.path.splitext(filename)
filename = hashlib.md5(smart_str(filename)).hexdigest() filename = hashlib.md5(smart_str(filename).encode('utf-8')).hexdigest()
filename = filename + ext filename = filename + ext
if size: if size:
tmppath.extend(['resized', str(size)]) tmppath.extend(['resized', str(size)])
@ -92,7 +92,7 @@ class AvatarBase(object):
try: try:
orig = self.avatar.storage.open(self.avatar.name, 'rb').read() orig = self.avatar.storage.open(self.avatar.name, 'rb').read()
image = Image.open(StringIO(orig)) image = Image.open(BytesIO(orig))
quality = quality or AVATAR_THUMB_QUALITY quality = quality or AVATAR_THUMB_QUALITY
(w, h) = image.size (w, h) = image.size
@ -106,7 +106,7 @@ class AvatarBase(object):
if image.mode != "RGBA": if image.mode != "RGBA":
image = image.convert("RGBA") image = image.convert("RGBA")
image = image.resize((size, size), AVATAR_RESIZE_METHOD) image = image.resize((size, size), AVATAR_RESIZE_METHOD)
thumb = StringIO() thumb = BytesIO()
image.save(thumb, AVATAR_THUMB_FORMAT, quality=quality) image.save(thumb, AVATAR_THUMB_FORMAT, quality=quality)
thumb_file = ContentFile(thumb.getvalue()) thumb_file = ContentFile(thumb.getvalue())
else: else:
@ -141,7 +141,7 @@ class Avatar(models.Model, AvatarBase):
date_uploaded = models.DateTimeField(default=datetime.datetime.now) date_uploaded = models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self): def __unicode__(self):
return _(u'Avatar for %s') % self.emailuser return _('Avatar for %s') % self.emailuser
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
avatars = Avatar.objects.filter(emailuser=self.emailuser) avatars = Avatar.objects.filter(emailuser=self.emailuser)
@ -169,7 +169,7 @@ class GroupAvatar(models.Model, AvatarBase):
date_uploaded = models.DateTimeField(default=datetime.datetime.now) date_uploaded = models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self): def __unicode__(self):
return _(u'Avatar for %s') % self.group_id return _('Avatar for %s') % self.group_id
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(GroupAvatar, self).save(*args, **kwargs) super(GroupAvatar, self).save(*args, **kwargs)

View File

@ -1,8 +1,8 @@
# Copyright (c) 2012-2016 Seafile Ltd. # Copyright (c) 2012-2016 Seafile Ltd.
import logging import logging
import urllib import urllib.request, urllib.parse, urllib.error
import hashlib import hashlib
from urlparse import urlparse from urllib.parse import urlparse
from django import template from django import template
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -34,8 +34,8 @@ def avatar_url(user, size=AVATAR_DEFAULT_SIZE):
if AVATAR_GRAVATAR_DEFAULT: if AVATAR_GRAVATAR_DEFAULT:
params['d'] = AVATAR_GRAVATAR_DEFAULT params['d'] = AVATAR_GRAVATAR_DEFAULT
return "http://www.gravatar.com/avatar/%s/?%s" % ( return "http://www.gravatar.com/avatar/%s/?%s" % (
hashlib.md5(user.email).hexdigest(), hashlib.md5(user.email.encode('utf-8')).hexdigest(),
urllib.urlencode(params)) urllib.parse.urlencode(params))
else: else:
url = get_default_avatar_url() url = get_default_avatar_url()

View File

@ -39,8 +39,8 @@ class AvatarTestCase(TestCase):
'password': 'testpassword', 'password': 'testpassword',
}, },
) )
self.assertEquals(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assert_(response['Location'].endswith(settings.LOGIN_REDIRECT_URL)) self.assertTrue(response['Location'].endswith(settings.LOGIN_REDIRECT_URL))
Image.init() Image.init()
@ -50,38 +50,38 @@ class AvatarTestCase(TestCase):
class AvatarUploadTests(AvatarTestCase): class AvatarUploadTests(AvatarTestCase):
def testNonImageUpload(self): def testNonImageUpload(self):
response = upload_helper(self, "nonimagefile") response = upload_helper(self, "nonimagefile")
self.failUnlessEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.failIfEqual(response.context['upload_avatar_form'].errors, {}) self.assertNotEqual(response.context['upload_avatar_form'].errors, {})
def testNormalImageUpload(self): def testNormalImageUpload(self):
response = upload_helper(self, "test.png") response = upload_helper(self, "test.png")
self.failUnlessEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.failUnlessEqual(len(response.redirect_chain), 1) self.assertEqual(len(response.redirect_chain), 1)
self.failUnlessEqual(response.context['upload_avatar_form'].errors, {}) self.assertEqual(response.context['upload_avatar_form'].errors, {})
avatar = get_primary_avatar(self.user) avatar = get_primary_avatar(self.user)
self.failIfEqual(avatar, None) self.assertNotEqual(avatar, None)
def testImageWithoutExtension(self): def testImageWithoutExtension(self):
# use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png') # use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png')
response = upload_helper(self, "imagefilewithoutext") response = upload_helper(self, "imagefilewithoutext")
self.failUnlessEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.assertEqual(len(response.redirect_chain), 0) # Redirect only if it worked
self.failIfEqual(response.context['upload_avatar_form'].errors, {}) self.assertNotEqual(response.context['upload_avatar_form'].errors, {})
def testImageWithWrongExtension(self): def testImageWithWrongExtension(self):
# use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png') # use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png')
response = upload_helper(self, "imagefilewithwrongext.ogg") response = upload_helper(self, "imagefilewithwrongext.ogg")
self.failUnlessEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.assertEqual(len(response.redirect_chain), 0) # Redirect only if it worked
self.failIfEqual(response.context['upload_avatar_form'].errors, {}) self.assertNotEqual(response.context['upload_avatar_form'].errors, {})
def testImageTooBig(self): def testImageTooBig(self):
# use with AVATAR_MAX_SIZE = 1024 * 1024 # use with AVATAR_MAX_SIZE = 1024 * 1024
response = upload_helper(self, "testbig.png") response = upload_helper(self, "testbig.png")
self.failUnlessEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.assertEqual(len(response.redirect_chain), 0) # Redirect only if it worked
self.failIfEqual(response.context['upload_avatar_form'].errors, {}) self.assertNotEqual(response.context['upload_avatar_form'].errors, {})
def testDefaultUrl(self): def testDefaultUrl(self):
response = self.client.get(reverse('avatar_render_primary', kwargs={ response = self.client.get(reverse('avatar_render_primary', kwargs={
@ -97,13 +97,13 @@ class AvatarUploadTests(AvatarTestCase):
def testNonExistingUser(self): def testNonExistingUser(self):
a = get_primary_avatar("nonexistinguser@mail.com") a = get_primary_avatar("nonexistinguser@mail.com")
self.failUnlessEqual(a, None) self.assertEqual(a, None)
def testThereCanBeOnlyOnePrimaryAvatar(self): def testThereCanBeOnlyOnePrimaryAvatar(self):
for i in range(1, 10): for i in range(1, 10):
self.testNormalImageUpload() self.testNormalImageUpload()
count = Avatar.objects.filter(emailuser=self.user, primary=True).count() count = Avatar.objects.filter(emailuser=self.user, primary=True).count()
self.failUnlessEqual(count, 1) self.assertEqual(count, 1)
# def testDeleteAvatar(self): # def testDeleteAvatar(self):
# self.testNormalImageUpload() # self.testNormalImageUpload()

View File

@ -34,11 +34,11 @@ def _get_next(request):
3. If Django can determine the previous page from the HTTP headers, the view will 3. If Django can determine the previous page from the HTTP headers, the view will
redirect to that previous page. redirect to that previous page.
""" """
next = request.POST.get('next', request.GET.get('next', next_page = request.POST.get('next', request.GET.get('next',
request.META.get('HTTP_REFERER', None))) request.META.get('HTTP_REFERER', None)))
if not next: if not next_page:
next = request.path next_page = request.path
return next return next_page
def _get_avatars(user): def _get_avatars(user):
# Default set. Needs to be sliced, but that's it. Keep the natural order. # Default set. Needs to be sliced, but that's it. Keep the natural order.
@ -148,10 +148,10 @@ def delete(request, extra_context=None, next_override=None, *args, **kwargs):
if request.method == 'POST': if request.method == 'POST':
if delete_avatar_form.is_valid(): if delete_avatar_form.is_valid():
ids = delete_avatar_form.cleaned_data['choices'] ids = delete_avatar_form.cleaned_data['choices']
if unicode(avatar.id) in ids and avatars.count() > len(ids): if str(avatar.id) in ids and avatars.count() > len(ids):
# Find the next best avatar, and set it as the new primary # Find the next best avatar, and set it as the new primary
for a in avatars: for a in avatars:
if unicode(a.id) not in ids: if str(a.id) not in ids:
a.primary = True a.primary = True
a.save() a.save()
avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar) avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar)

View File

@ -11,7 +11,7 @@ from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site from django.contrib.sites.shortcuts import get_current_site
import seaserv import seaserv
from seaserv import ccnet_threaded_rpc, unset_repo_passwd, is_passwd_set, \ from seaserv import ccnet_threaded_rpc, unset_repo_passwd, \
seafile_api, ccnet_api seafile_api, ccnet_api
from constance import config from constance import config
from registration import signals from registration import signals
@ -89,14 +89,14 @@ class UserManager(object):
def get(self, email=None, id=None): def get(self, email=None, id=None):
if not email and not id: if not email and not id:
raise User.DoesNotExist, 'User matching query does not exits.' raise User.DoesNotExist('User matching query does not exits.')
if email: if email:
emailuser = ccnet_threaded_rpc.get_emailuser(email) emailuser = ccnet_threaded_rpc.get_emailuser(email)
if id: if id:
emailuser = ccnet_threaded_rpc.get_emailuser_by_id(id) emailuser = ccnet_threaded_rpc.get_emailuser_by_id(id)
if not emailuser: if not emailuser:
raise User.DoesNotExist, 'User matching query does not exits.' raise User.DoesNotExist('User matching query does not exits.')
user = User(emailuser.email) user = User(emailuser.email)
user.id = emailuser.id user.id = emailuser.id
@ -510,7 +510,7 @@ class User(object):
passwd_setted_repos = [] passwd_setted_repos = []
for r in owned_repos + shared_repos + groups_repos + public_repos: for r in owned_repos + shared_repos + groups_repos + public_repos:
if not has_repo(passwd_setted_repos, r) and r.encrypted and \ if not has_repo(passwd_setted_repos, r) and r.encrypted and \
is_passwd_set(r.id, self.email): seafile_api.is_password_set(r.id, self.email):
passwd_setted_repos.append(r) passwd_setted_repos.append(r)
for r in passwd_setted_repos: for r in passwd_setted_repos:
@ -532,7 +532,7 @@ class User(object):
passwd_setted_repos = [] passwd_setted_repos = []
for r in owned_repos + shared_repos + groups_repos + public_repos: for r in owned_repos + shared_repos + groups_repos + public_repos:
if not has_repo(passwd_setted_repos, r) and r.encrypted and \ if not has_repo(passwd_setted_repos, r) and r.encrypted and \
is_passwd_set(r.id, self.email): seafile_api.is_password_set(r.id, self.email):
passwd_setted_repos.append(r) passwd_setted_repos.append(r)
for r in passwd_setted_repos: for r in passwd_setted_repos:
@ -543,7 +543,7 @@ class AuthBackend(object):
def get_user_with_import(self, username): def get_user_with_import(self, username):
emailuser = seaserv.get_emailuser_with_import(username) emailuser = seaserv.get_emailuser_with_import(username)
if not emailuser: if not emailuser:
raise User.DoesNotExist, 'User matching query does not exits.' raise User.DoesNotExist('User matching query does not exits.')
user = User(emailuser.email) user = User(emailuser.email)
user.id = emailuser.id user.id = emailuser.id

View File

@ -14,6 +14,6 @@ class BaseConfig(AppConfig):
try: try:
_ = list(FileComment.objects.all()[:1].values('uuid_id')) _ = list(FileComment.objects.all()[:1].values('uuid_id'))
except: except:
print ''' print('''
Warning: File comment has changed since version 6.3, while table `base_filecomment` is not migrated yet, please consider migrate it according to v6.3.0 release note, otherwise the file comment feature will not work correctly. Warning: File comment has changed since version 6.3, while table `base_filecomment` is not migrated yet, please consider migrate it according to v6.3.0 release note, otherwise the file comment feature will not work correctly.
''' ''')

View File

@ -2,4 +2,4 @@
# Allow users to: from database_storage import DatabaseStorage # Allow users to: from database_storage import DatabaseStorage
# (reduce redundancy a little bit) # (reduce redundancy a little bit)
from database_storage import * from .database_storage import *

View File

@ -10,8 +10,8 @@ from django.db import connection, transaction
import base64 import base64
import hashlib import hashlib
import StringIO import io
import urlparse import urllib.parse
from datetime import datetime from datetime import datetime
from seahub.utils.timeutils import value_to_db_datetime from seahub.utils.timeutils import value_to_db_datetime
@ -137,7 +137,7 @@ class DatabaseStorage(Storage):
""" """
assert mode == 'rb', "DatabaseStorage open mode must be 'rb'." assert mode == 'rb', "DatabaseStorage open mode must be 'rb'."
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
query = 'SELECT %(data_column)s FROM %(table)s ' + \ query = 'SELECT %(data_column)s FROM %(table)s ' + \
'WHERE %(name_md5_column)s = %%s' 'WHERE %(name_md5_column)s = %%s'
@ -148,7 +148,7 @@ class DatabaseStorage(Storage):
if row is None: if row is None:
return None return None
inMemFile = StringIO.StringIO(base64.b64decode(row[0])) inMemFile = io.BytesIO(base64.b64decode(row[0]))
inMemFile.name = name inMemFile.name = name
inMemFile.mode = mode inMemFile.mode = mode
@ -160,7 +160,7 @@ class DatabaseStorage(Storage):
in the name will be converted to forward '/'. in the name will be converted to forward '/'.
""" """
name = name.replace('\\', '/') name = name.replace('\\', '/')
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
binary = content.read() binary = content.read()
size = len(binary) size = len(binary)
@ -185,7 +185,7 @@ class DatabaseStorage(Storage):
return name return name
def exists(self, name): def exists(self, name):
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
query = 'SELECT COUNT(*) FROM %(table)s WHERE %(name_md5_column)s = %%s' query = 'SELECT COUNT(*) FROM %(table)s WHERE %(name_md5_column)s = %%s'
query %= self.__dict__ query %= self.__dict__
cursor = connection.cursor() cursor = connection.cursor()
@ -196,7 +196,7 @@ class DatabaseStorage(Storage):
def delete(self, name): def delete(self, name):
if self.exists(name): if self.exists(name):
with transaction.atomic(using='default'): with transaction.atomic(using='default'):
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
query = 'DELETE FROM %(table)s WHERE %(name_md5_column)s = %%s' query = 'DELETE FROM %(table)s WHERE %(name_md5_column)s = %%s'
query %= self.__dict__ query %= self.__dict__
connection.cursor().execute(query, [name_md5]) connection.cursor().execute(query, [name_md5])
@ -207,12 +207,12 @@ class DatabaseStorage(Storage):
def url(self, name): def url(self, name):
if self.base_url is None: if self.base_url is None:
raise ValueError("This file is not accessible via a URL.") raise ValueError("This file is not accessible via a URL.")
result = urlparse.urljoin(self.base_url, name).replace('\\', '/') result = urllib.parse.urljoin(self.base_url, name).replace('\\', '/')
return result return result
def size(self, name): def size(self, name):
"Get the size of the given filename or raise ObjectDoesNotExist." "Get the size of the given filename or raise ObjectDoesNotExist."
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
query = 'SELECT %(size_column)s FROM %(table)s ' + \ query = 'SELECT %(size_column)s FROM %(table)s ' + \
'WHERE %(name_md5_column)s = %%s' 'WHERE %(name_md5_column)s = %%s'
query %= self.__dict__ query %= self.__dict__
@ -226,7 +226,7 @@ class DatabaseStorage(Storage):
def modified_time(self, name): def modified_time(self, name):
"Get the modified time of the given filename or raise ObjectDoesNotExist." "Get the modified time of the given filename or raise ObjectDoesNotExist."
name_md5 = hashlib.md5(name).hexdigest() name_md5 = hashlib.md5(name.encode('utf-8')).hexdigest()
query = 'SELECT %(mtime_column)s FROM %(table)s ' + \ query = 'SELECT %(mtime_column)s FROM %(table)s ' + \
'WHERE %(name_md5_column)s = %%s' 'WHERE %(name_md5_column)s = %%s'
query %= self.__dict__ query %= self.__dict__

View File

@ -4,7 +4,7 @@ from django.http import Http404, HttpResponseRedirect, HttpResponseNotAllowed
from django.shortcuts import render from django.shortcuts import render
from django.utils.http import urlquote from django.utils.http import urlquote
from seaserv import get_repo, is_passwd_set from seaserv import get_repo, seafile_api
from seahub.options.models import UserOptions, CryptoOptionNotSetError from seahub.options.models import UserOptions, CryptoOptionNotSetError
@ -49,7 +49,7 @@ def repo_passwd_set_required(func):
def _decorated(request, *args, **kwargs): def _decorated(request, *args, **kwargs):
repo_id = kwargs.get('repo_id', None) repo_id = kwargs.get('repo_id', None)
if not repo_id: if not repo_id:
raise Exception, 'Repo id is not found in url.' raise Exception('Repo id is not found in url.')
repo = get_repo(repo_id) repo = get_repo(repo_id)
if not repo: if not repo:
raise Http404 raise Http404
@ -62,14 +62,14 @@ def repo_passwd_set_required(func):
}) })
if (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) \ if (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) \
and not is_passwd_set(repo_id, username): and not seafile_api.is_password_set(repo_id, username):
return render(request, 'decrypt_repo_form.html', { return render(request, 'decrypt_repo_form.html', {
'repo': repo, 'repo': repo,
'next': request.get_full_path(), 'next': request.get_full_path(),
}) })
if repo.enc_version == 2 and not server_crypto: if repo.enc_version == 2 and not server_crypto:
return render_error(request, _(u'Files in this library can not be viewed online.')) return render_error(request, _('Files in this library can not be viewed online.'))
return func(request, *args, **kwargs) return func(request, *args, **kwargs)
return _decorated return _decorated

View File

@ -15,7 +15,7 @@ class ModifyingFieldDescriptor(object):
class LowerCaseCharField(CharField): class LowerCaseCharField(CharField):
def to_python(self, value): def to_python(self, value):
value = super(LowerCaseCharField, self).to_python(value) value = super(LowerCaseCharField, self).to_python(value)
if isinstance(value, basestring): if isinstance(value, str):
return value.lower() return value.lower()
return value return value
def contribute_to_class(self, cls, name): def contribute_to_class(self, cls, name):

View File

@ -12,7 +12,7 @@ class DirectTemplateView(TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(self.__class__, self).get_context_data(**kwargs) context = super(self.__class__, self).get_context_data(**kwargs)
if self.extra_context is not None: if self.extra_context is not None:
for key, value in self.extra_context.items(): for key, value in list(self.extra_context.items()):
if callable(value): if callable(value):
context[key] = value() context[key] = value()
else: else:

View File

@ -28,7 +28,7 @@ class Command(BaseCommand):
except User.DoesNotExist: except User.DoesNotExist:
raise CommandError("user '%s' does not exist" % username) raise CommandError("user '%s' does not exist" % username)
print "Changing password for user '%s'" % u.username print("Changing password for user '%s'" % u.username)
MAX_TRIES = 3 MAX_TRIES = 3
count = 0 count = 0
@ -37,7 +37,7 @@ class Command(BaseCommand):
p1 = self._get_pass() p1 = self._get_pass()
p2 = self._get_pass("Password (again): ") p2 = self._get_pass("Password (again): ")
if p1 != p2: if p1 != p2:
print "Passwords do not match. Please try again." print("Passwords do not match. Please try again.")
count = count + 1 count = count + 1
if count == MAX_TRIES: if count == MAX_TRIES:

View File

@ -27,7 +27,7 @@ class Command(BaseCommand):
'ExtraSharePermission': ExtraSharePermission, 'ExtraSharePermission': ExtraSharePermission,
'UploadLinkShare': UploadLinkShare} 'UploadLinkShare': UploadLinkShare}
for table in self.tables.items(): for table in list(self.tables.items()):
self.clear_table(table[0], table[1]) self.clear_table(table[0], table[1])
self.stdout.write('All invalid repo data are deleted') self.stdout.write('All invalid repo data are deleted')

View File

@ -118,9 +118,9 @@ class Command(BaseCommand):
# username = None # username = None
# Get an email # Get an email
while 1: while True:
if not email: if not email:
email = raw_input('E-mail address: ') email = input('E-mail address: ')
try: try:
is_valid_email(email) is_valid_email(email)
except exceptions.ValidationError: except exceptions.ValidationError:
@ -130,7 +130,7 @@ class Command(BaseCommand):
break break
# Get a password # Get a password
while 1: while True:
if not password: if not password:
password = getpass.getpass() password = getpass.getpass()
password2 = getpass.getpass('Password (again): ') password2 = getpass.getpass('Password (again): ')
@ -148,4 +148,4 @@ class Command(BaseCommand):
sys.exit(1) sys.exit(1)
User.objects.create_superuser(email, password) User.objects.create_superuser(email, password)
print "Superuser created successfully." print("Superuser created successfully.")

View File

@ -62,7 +62,7 @@ class Command(BaseCommand):
repo_obj_dict = {} repo_obj_dict = {}
repo_owner_dict = {} repo_owner_dict = {}
events.sort(lambda x, y: cmp(y.timestamp, x.timestamp)) events.sort(key=lambda x: x.timestamp, reverse=True)
for ev in events: for ev in events:
event_type, ev.show_device = generate_file_audit_event_type(ev) event_type, ev.show_device = generate_file_audit_event_type(ev)

View File

@ -24,19 +24,19 @@ class Command(BaseCommand):
elif 'sqlite' in engine: elif 'sqlite' in engine:
sqlite = True sqlite = True
else: else:
print 'Unsupported database. Exit.' print('Unsupported database. Exit.')
return return
print 'Start to update schema...' print('Start to update schema...')
comments = list(FileComment.objects.raw('SELECT * from base_filecomment')) comments = list(FileComment.objects.raw('SELECT * from base_filecomment'))
with connection.cursor() as cursor: with connection.cursor() as cursor:
sql = 'ALTER TABLE base_filecomment RENAME TO base_filecomment_backup_%s' % (random_key()) sql = 'ALTER TABLE base_filecomment RENAME TO base_filecomment_backup_%s' % (random_key())
cursor.execute(sql) cursor.execute(sql)
print sql print(sql)
print '' print('')
if mysql: if mysql:
sql = '''CREATE TABLE `base_filecomment` ( sql = '''CREATE TABLE `base_filecomment` (
@ -54,23 +54,23 @@ class Command(BaseCommand):
''' % (random_key(), random_key(), random_key()) ''' % (random_key(), random_key(), random_key())
cursor.execute(sql) cursor.execute(sql)
print sql print(sql)
if sqlite: if sqlite:
sql = '''CREATE TABLE "base_filecomment" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "author" varchar(255) NOT NULL, "comment" text NOT NULL, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "uuid_id" char(32) NOT NULL REFERENCES "tags_fileuuidmap" ("uuid")) sql = '''CREATE TABLE "base_filecomment" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "author" varchar(255) NOT NULL, "comment" text NOT NULL, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "uuid_id" char(32) NOT NULL REFERENCES "tags_fileuuidmap" ("uuid"))
''' '''
cursor.execute(sql) cursor.execute(sql)
print sql print(sql)
sql = '''CREATE INDEX "base_filecomment_%s" ON "base_filecomment" ("author")''' % random_key() sql = '''CREATE INDEX "base_filecomment_%s" ON "base_filecomment" ("author")''' % random_key()
cursor.execute(sql) cursor.execute(sql)
print sql print(sql)
sql = '''CREATE INDEX "base_filecomment_%s" ON "base_filecomment" ("uuid_id") ''' % random_key() sql = '''CREATE INDEX "base_filecomment_%s" ON "base_filecomment" ("uuid_id") ''' % random_key()
cursor.execute(sql) cursor.execute(sql)
print sql print(sql)
print 'Start to migate comments data...' print('Start to migate comments data...')
for c in comments: for c in comments:
repo_id = c.repo_id repo_id = c.repo_id
parent_path = c.parent_path parent_path = c.parent_path
@ -83,15 +83,15 @@ class Command(BaseCommand):
uuid = FileUUIDMap.objects.get_or_create_fileuuidmap(repo_id, parent_path, filename, False) uuid = FileUUIDMap.objects.get_or_create_fileuuidmap(repo_id, parent_path, filename, False)
FileComment(uuid=uuid, author=author, comment=comment, FileComment(uuid=uuid, author=author, comment=comment,
created_at=created_at, updated_at=updated_at).save() created_at=created_at, updated_at=updated_at).save()
print 'migrated comment ID: %d' % c.pk print('migrated comment ID: %d' % c.pk)
print 'Done' print('Done')
def handle(self, *args, **options): def handle(self, *args, **options):
# check table column `uuid` # check table column `uuid`
try: try:
res = FileComment.objects.raw('SELECT uuid_id from base_filecomment limit 1') res = FileComment.objects.raw('SELECT uuid_id from base_filecomment limit 1')
if 'uuid_id' in res.columns: if 'uuid_id' in res.columns:
print 'base_filecomment is already migrated, exit.' print('base_filecomment is already migrated, exit.')
except OperationalError: except OperationalError:
self.migrate_schema() self.migrate_schema()

View File

@ -185,7 +185,7 @@ class UserPermissionMiddleware(object):
request_path = request.path request_path = request.path
def get_permission_by_request_path(request_path, permission_url): def get_permission_by_request_path(request_path, permission_url):
for permission, url_list in permission_url.iteritems(): for permission, url_list in permission_url.items():
for url in url_list: for url in url_list:
if url in request_path: if url in request_path:
return permission return permission

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-03-21 08:42 # Generated by Django 1.11.11 on 2018-03-21 08:42
from __future__ import unicode_literals
import datetime import datetime
from django.db import migrations, models from django.db import migrations, models
@ -126,6 +126,6 @@ class Migration(migrations.Migration):
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name='devicetoken', name='devicetoken',
unique_together=set([('token', 'user')]), unique_together={('token', 'user')},
), ),
] ]

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-07-10 09:33 # Generated by Django 1.11.11 on 2018-07-10 09:33
from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.15 on 2018-10-16 12:42 # Generated by Django 1.11.15 on 2018-10-16 12:42
from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -15,7 +15,7 @@ from seahub.utils import calc_file_path_hash, within_time_range, \
normalize_file_path, normalize_dir_path normalize_file_path, normalize_dir_path
from seahub.utils.timeutils import datetime_to_isoformat_timestr from seahub.utils.timeutils import datetime_to_isoformat_timestr
from seahub.tags.models import FileUUIDMap from seahub.tags.models import FileUUIDMap
from fields import LowerCaseCharField from .fields import LowerCaseCharField
# Get an instance of a logger # Get an instance of a logger
@ -192,7 +192,7 @@ class UserStarredFilesManager(models.Manager):
repo_cache = {} repo_cache = {}
for sfile in starred_files: for sfile in starred_files:
# repo still exists? # repo still exists?
if repo_cache.has_key(sfile.repo_id): if sfile.repo_id in repo_cache:
repo = repo_cache[sfile.repo_id] repo = repo_cache[sfile.repo_id]
else: else:
try: try:
@ -241,7 +241,7 @@ class UserStarredFilesManager(models.Manager):
logger.error(e) logger.error(e)
sfile.last_modified = 0 sfile.last_modified = 0
ret.sort(lambda x, y: cmp(y.last_modified, x.last_modified)) ret.sort(key=lambda x: x.last_modified, reverse=True)
return ret return ret

View File

@ -26,10 +26,10 @@ THE SOFTWARE.
try: try:
import cProfile as profile import cProfile as profile
except ImportError: except ImportError:
import profile from . import profile
import pstats import pstats
from cStringIO import StringIO from io import StringIO
from django.conf import settings from django.conf import settings
class ProfilerMiddleware(object): class ProfilerMiddleware(object):

View File

@ -2,10 +2,10 @@
from django import template from django import template
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import QueryDict from django.http import QueryDict
from django.utils.encoding import force_unicode from django.utils.encoding import force_text
from django.utils.html import escape from django.utils.html import escape
from django.utils.safestring import SafeData, mark_safe from django.utils.safestring import SafeData, mark_safe
from urlparse import urlsplit, urlunsplit from urllib.parse import urlsplit, urlunsplit
import re import re
import string import string
@ -97,7 +97,7 @@ def add_class(value, css_class):
In the case of REST Framework, the filter is used to add Bootstrap-specific In the case of REST Framework, the filter is used to add Bootstrap-specific
classes to the forms. classes to the forms.
""" """
html = unicode(value) html = str(value)
match = class_re.search(html) match = class_re.search(html)
if match: if match:
m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class, m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class,
@ -131,7 +131,7 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru
""" """
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
safe_input = isinstance(text, SafeData) safe_input = isinstance(text, SafeData)
words = word_split_re.split(force_unicode(text)) words = word_split_re.split(force_text(text))
nofollow_attr = nofollow and ' rel="nofollow"' or '' nofollow_attr = nofollow and ' rel="nofollow"' or ''
for i, word in enumerate(words): for i, word in enumerate(words):
match = None match = None
@ -167,4 +167,4 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru
words[i] = mark_safe(word) words[i] = mark_safe(word)
elif autoescape: elif autoescape:
words[i] = escape(word) words[i] = escape(word)
return mark_safe(u''.join(words)) return mark_safe(''.join(words))

View File

@ -53,23 +53,23 @@ FILEEXT_ICON_MAP = {
'txt': 'txt.png', 'txt': 'txt.png',
# pdf file # pdf file
'pdf' : 'pdf.png', 'pdf': 'pdf.png',
# document file # document file
'doc' : 'word.png', 'doc': 'word.png',
'docx' : 'word.png', 'docx': 'word.png',
'odt' : 'word.png', 'odt': 'word.png',
'fodt' : 'word.png', 'fodt': 'word.png',
'ppt' : 'ppt.png', 'ppt': 'ppt.png',
'pptx' : 'ppt.png', 'pptx': 'ppt.png',
'odp' : 'ppt.png', 'odp': 'ppt.png',
'fodp' : 'ppt.png', 'fodp': 'ppt.png',
'xls' : 'excel.png', 'xls': 'excel.png',
'xlsx' : 'excel.png', 'xlsx': 'excel.png',
'ods' : 'excel.png', 'ods': 'excel.png',
'fods' : 'excel.png', 'fods': 'excel.png',
# video # video
'mp4': 'video.png', 'mp4': 'video.png',
@ -81,25 +81,25 @@ FILEEXT_ICON_MAP = {
'rmvb': 'video.png', 'rmvb': 'video.png',
# music file # music file
'mp3' : 'music.png', 'mp3': 'music.png',
'oga' : 'music.png', 'oga': 'music.png',
'ogg' : 'music.png', 'ogg': 'music.png',
'flac' : 'music.png', 'flac': 'music.png',
'aac' : 'music.png', 'aac': 'music.png',
'ac3' : 'music.png', 'ac3': 'music.png',
'wma' : 'music.png', 'wma': 'music.png',
# image file # image file
'jpg' : 'pic.png', 'jpg': 'pic.png',
'jpeg' : 'pic.png', 'jpeg': 'pic.png',
'png' : 'pic.png', 'png': 'pic.png',
'svg' : 'pic.png', 'svg': 'pic.png',
'gif' : 'pic.png', 'gif': 'pic.png',
'bmp' : 'pic.png', 'bmp': 'pic.png',
'ico' : 'pic.png', 'ico': 'pic.png',
# default # default
'default' : 'file.png', 'default': 'file.png',
} }
@register.filter(name='file_icon_filter') @register.filter(name='file_icon_filter')
def file_icon_filter(value, size=None): def file_icon_filter(value, size=None):
@ -109,7 +109,7 @@ def file_icon_filter(value, size=None):
else: else:
file_ext = None file_ext = None
if file_ext and FILEEXT_ICON_MAP.has_key(file_ext): if file_ext and file_ext in FILEEXT_ICON_MAP:
if size == 192: if size == 192:
return '192/' + FILEEXT_ICON_MAP.get(file_ext) return '192/' + FILEEXT_ICON_MAP.get(file_ext)
else: else:
@ -122,17 +122,17 @@ def file_icon_filter(value, size=None):
# This way of translation looks silly, but works well. # This way of translation looks silly, but works well.
COMMIT_MSG_TRANSLATION_MAP = { COMMIT_MSG_TRANSLATION_MAP = {
'Added' : _('Added'), 'Added': _('Added'),
'Deleted' : _('Deleted'), 'Deleted': _('Deleted'),
'Removed' : _('Removed'), 'Removed': _('Removed'),
'Modified' : _('Modified'), 'Modified': _('Modified'),
'Renamed' : _('Renamed'), 'Renamed': _('Renamed'),
'Moved' : _('Moved'), 'Moved': _('Moved'),
'Added directory' : _('Added directory'), 'Added directory': _('Added directory'),
'Removed directory' : _('Removed directory'), 'Removed directory': _('Removed directory'),
'Renamed directory' : _('Renamed directory'), 'Renamed directory': _('Renamed directory'),
'Moved directory' : _('Moved directory'), 'Moved directory': _('Moved directory'),
'Added or modified' : _('Added or modified'), 'Added or modified': _('Added or modified'),
} }
@register.filter(name='translate_commit_desc') @register.filter(name='translate_commit_desc')
def translate_commit_desc(value): def translate_commit_desc(value):
@ -164,7 +164,7 @@ def translate_commit_desc(value):
else: else:
# Use regular expression to translate commit description. # Use regular expression to translate commit description.
# Commit description has two forms, e.g., 'Added "foo.txt" and 3 more files.' or 'Added "foo.txt".' # Commit description has two forms, e.g., 'Added "foo.txt" and 3 more files.' or 'Added "foo.txt".'
operations = '|'.join(COMMIT_MSG_TRANSLATION_MAP.keys()) operations = '|'.join(list(COMMIT_MSG_TRANSLATION_MAP.keys()))
patt = r'(%s) "(.*)"\s?(and ([0-9]+) more (files|directories))?' % operations patt = r'(%s) "(.*)"\s?(and ([0-9]+) more (files|directories))?' % operations
ret_list = [] ret_list = []
@ -186,14 +186,14 @@ def translate_commit_desc(value):
if has_more: if has_more:
if translation.get_language() == 'zh-cn': if translation.get_language() == 'zh-cn':
typ = u'文件' if more_type == 'files' else u'目录' typ = '文件' if more_type == 'files' else '目录'
ret = op_trans + u' "' + file_name + u'"以及另外' + n_files + u'' + typ + '.' ret = op_trans + ' "' + file_name + '"以及另外' + n_files + '' + typ + '.'
# elif translation.get_language() == 'ru': # elif translation.get_language() == 'ru':
# ret = ... # ret = ...
else: else:
ret = e ret = e
else: else:
ret = op_trans + u' "' + file_name + u'".' ret = op_trans + ' "' + file_name + '".'
ret_list.append(ret) ret_list.append(ret)
return '\n'.join(ret_list) return '\n'.join(ret_list)
@ -235,7 +235,7 @@ def translate_commit_desc_escape(value):
else: else:
# Use regular expression to translate commit description. # Use regular expression to translate commit description.
# Commit description has two forms, e.g., 'Added "foo.txt" and 3 more files.' or 'Added "foo.txt".' # Commit description has two forms, e.g., 'Added "foo.txt" and 3 more files.' or 'Added "foo.txt".'
operations = '|'.join(COMMIT_MSG_TRANSLATION_MAP.keys()) operations = '|'.join(list(COMMIT_MSG_TRANSLATION_MAP.keys()))
patt = r'(%s) "(.*)"\s?(and ([0-9]+) more (files|directories))?' % operations patt = r'(%s) "(.*)"\s?(and ([0-9]+) more (files|directories))?' % operations
for e in value.split('\n'): for e in value.split('\n'):
@ -258,14 +258,14 @@ def translate_commit_desc_escape(value):
if has_more: if has_more:
if translation.get_language() == 'zh-cn': if translation.get_language() == 'zh-cn':
typ = u'文件' if more_type == 'files' else u'目录' typ = '文件' if more_type == 'files' else '目录'
ret = op_trans + u' "' + file_name + u'"以及另外' + n_files + u'' + typ + '.' ret = op_trans + ' "' + file_name + '"以及另外' + n_files + '' + typ + '.'
# elif translation.get_language() == 'ru': # elif translation.get_language() == 'ru':
# ret = ... # ret = ...
else: else:
ret = e ret = e
else: else:
ret = op_trans + u' "' + file_name + u'".' ret = op_trans + ' "' + file_name + '".'
# if not match, this commit desc will not convert link, so # if not match, this commit desc will not convert link, so
# escape it # escape it
@ -278,7 +278,7 @@ def translate_commit_desc_escape(value):
@register.filter(name='translate_seahub_time') @register.filter(name='translate_seahub_time')
def translate_seahub_time(value, autoescape=None): def translate_seahub_time(value, autoescape=None):
if isinstance(value, int) or isinstance(value, long): # check whether value is int if isinstance(value, int) or isinstance(value, int): # check whether value is int
try: try:
val = datetime.fromtimestamp(value) # convert timestamp to datetime val = datetime.fromtimestamp(value) # convert timestamp to datetime
except ValueError as e: except ValueError as e:
@ -461,9 +461,9 @@ def char2pinyin(value):
@register.filter(name='translate_permission') @register.filter(name='translate_permission')
def translate_permission(value): def translate_permission(value):
if value == 'rw': if value == 'rw':
return _(u'Read-Write') return _('Read-Write')
elif value == 'r': elif value == 'r':
return _(u'Read-Only') return _('Read-Only')
else: else:
return '' return ''

View File

@ -3,7 +3,7 @@ import re
import string import string
from django.utils.safestring import SafeData, mark_safe from django.utils.safestring import SafeData, mark_safe
from django.utils.encoding import force_unicode from django.utils.encoding import force_text
from django.utils.functional import allow_lazy from django.utils.functional import allow_lazy
from django.utils.http import urlquote from django.utils.http import urlquote
@ -21,8 +21,8 @@ def escape(html):
""" """
Returns the given HTML with ampersands, quotes and angle brackets encoded. Returns the given HTML with ampersands, quotes and angle brackets encoded.
""" """
return mark_safe(force_unicode(html).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;')) return mark_safe(force_text(html).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;'))
escape = allow_lazy(escape, unicode) escape = allow_lazy(escape, str)
## modification of django's urlize, add '%' to safe: ## modification of django's urlize, add '%' to safe:
## urlquote('http://%s' % middle, safe='/&=:;#?+*%') ## urlquote('http://%s' % middle, safe='/&=:;#?+*%')
@ -47,7 +47,7 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
""" """
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
safe_input = isinstance(text, SafeData) safe_input = isinstance(text, SafeData)
words = word_split_re.split(force_unicode(text)) words = word_split_re.split(force_text(text))
nofollow_attr = nofollow and ' rel="nofollow"' or '' nofollow_attr = nofollow and ' rel="nofollow"' or ''
for i, word in enumerate(words): for i, word in enumerate(words):
match = None match = None
@ -83,5 +83,5 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
words[i] = mark_safe(word) words[i] = mark_safe(word)
elif autoescape: elif autoescape:
words[i] = escape(word) words[i] = escape(word)
return u''.join(words) return ''.join(words)
urlize = allow_lazy(urlize, unicode) urlize = allow_lazy(urlize, str)

Some files were not shown because too many files have changed in this diff Show More