Commit 42049e19 authored by Keith Packard's avatar Keith Packard

Port to python3

Fix imports
Change how HTTPS socket is created
Fix exception syntax to use 'as'
Change 'has_key(foo)' to 'foo in'
Signed-off-by: 's avatarKeith Packard <keithp@keithp.com>
parent dbc43bf6
#!/usr/bin/python
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# This file is part of Calypso - CalDAV/CardDAV/WebDAV Server
......
......@@ -41,17 +41,10 @@ import socket
import time
import email.utils
import logging
import rfc822
import email
import ssl
from http import client, server
# Manage Python2/3 different modules
# pylint: disable=F0401
try:
from http import client, server
except ImportError:
import httplib as client
import BaseHTTPServer as server
# pylint: enable=F0401
from . import acl, config, webdav, xmlutils, paths, gssapi
......@@ -115,18 +108,14 @@ class HTTPSServer(HTTPServer):
"""HTTPS server."""
PROTOCOL = "https"
def __init__(self, address, handler):
"""Create server by wrapping HTTP socket in an SSL socket."""
HTTPServer.__init__(self, address, handler)
self.socket = ssl.wrap_socket(
socket.socket(self.address_family, self.socket_type),
server_side=True,
certfile=os.path.expanduser(config.get("server", "certificate")),
keyfile=os.path.expanduser(config.get("server", "key")),
ssl_version=ssl.PROTOCOL_SSLv23)
self.server_bind()
self.server_activate()
def server_bind(self):
HTTPServer.server_bind(self)
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(os.path.expanduser(config.get("server", "certificate")),
keyfile=os.path.expanduser(config.get("server", "key")))
self.socket = context.wrap_socket(self.socket,server_side=True)
class CollectionHTTPHandler(server.BaseHTTPRequestHandler):
"""HTTP requests handler for WebDAV collections."""
......@@ -233,7 +222,7 @@ class CollectionHTTPHandler(server.BaseHTTPRequestHandler):
log.error("Request timed out: %r", e)
self.close_connection = 1
return
except ssl.SSLError, x:
except ssl.SSLError as x:
#an io error. Discard this connection
log.error("SSL request error: %r", x.args[0])
self.close_connection = 1
......@@ -338,13 +327,13 @@ class CollectionHTTPHandler(server.BaseHTTPRequestHandler):
def if_match(self, item):
header = self.headers.get("If-Match", item.etag)
header = rfc822.unquote(header)
header = email.utils.unquote(header)
if header == item.etag:
return True
quoted = '"' + item.etag + '"'
if header == quoted:
return True
extraquoted = rfc822.quote(quoted)
extraquoted = email.utils.quote(quoted)
if header == extraquoted:
return True
return False
......
......@@ -31,6 +31,6 @@ from calypso import config
def load():
"""Load list of available ACL managers."""
acl_type = config.get("acl", "type").encode("utf-8")
acl_type = config.get("acl", "type")
module = __import__("calypso.acl", fromlist=[acl_type])
return getattr(module, acl_type)
......@@ -23,9 +23,9 @@ This module handles kerberos authenticatien via gssapi
"""
import os
from . import config
from acl import nopwd
import calypso.acl
import calypso.config
import calypso.acl.nopwd
# pylint: disable=F0401
try:
......
......@@ -20,6 +20,7 @@
# along with Calypso. If not, see <http://www.gnu.org/licenses/>.
import urllib
import urllib.request
import os.path
import posixpath # the semantics of urls follow posix rules, not platform dependent rules
import logging
......@@ -62,7 +63,7 @@ def base_prefix():
def url_to_file(url):
if url.startswith(base_prefix()):
url = "/" + url[len(base_prefix()):].lstrip("/")
tail = urllib.url2pathname(url.strip("/"))
tail = urllib.request.url2pathname(url.strip("/"))
# eliminate .. components, and potential double leading slashes
tail = posixpath.normpath('/' + tail).lstrip('/')
file = os.path.join(data_root(), tail)
......@@ -128,7 +129,7 @@ def resource_from_path(path):
collection = parent_url(collection)
if child_path:
name = urllib.unquote(child_path)
name = urllib.parse.unquote(child_path)
else:
name = None
......@@ -153,7 +154,7 @@ def collection_from_path(path):
return None
# unquote, strip off any trailing slash, then clean up /../ and // entries
collection = "/" + urllib.unquote(collection).strip("/")
collection = "/" + urllib.parse.unquote(collection).strip("/")
log.debug('Path %s results in collection: %s', path, collection)
return collection
......
......@@ -36,13 +36,15 @@ import vobject
import re
import subprocess
import vobject.base
import ConfigParser
import iniparse
import configparser
from configparser import RawConfigParser as ConfigParser
from . import config, paths
METADATA_FILENAME = ".calypso-collection"
# pylint: enable=F0401
#
# Recursive search for 'name' within 'vobject'
#
......@@ -67,10 +69,6 @@ class Item(object):
"""Initialize object from ``text`` and different ``kwargs``."""
self.log = logging.getLogger(__name__)
try:
text = text.encode('utf8')
except UnicodeDecodeError:
text = text.decode('latin1').encode('utf-8')
# Strip out control characters
......@@ -83,21 +81,21 @@ class Item(object):
raise
if not self.object.contents.has_key('x-calypso-name'):
if 'x-calpyso-name' not in self.object.contents:
if not name:
if self.object.name == 'VCARD' or self.object.name == 'VEVENT':
if not self.object.contents.has_key('uid'):
self.object.add('UID').value = hashlib.sha1(text).hexdigest()
if 'uid' not in self.object.contents:
self.object.add('UID').value = hashlib.sha1(text.encode('utf-8')).hexdigest()
name = self.object.uid.value
else:
for child in self.object.getChildren():
if child.name == 'VEVENT' or child.name == 'VCARD':
if not child.contents.has_key('uid'):
child.add('UID').value = hashlib.sha1(text).hexdigest()
if 'uid' not in child.contents:
child.add('UID').value = hashlib.sha1(text.encode('utf-8')).hexdigest()
name = child.uid.value
break
if not name:
name = hashlib.sha1(text).hexdigest()
name = hashlib.sha1(text.encode('utf-8')).hexdigest()
self.object.add("X-CALYPSO-NAME").value = name
else:
......@@ -109,7 +107,7 @@ class Item(object):
self.name = self.object.x_calypso_name.value
self.urlpath = "/".join([parent_urlpath, self.name])
self.tag = self.object.name
self.etag = hashlib.sha1(text).hexdigest()
self.etag = hashlib.sha1(text.encode('utf-8')).hexdigest()
@property
def is_vcard(self):
......@@ -175,10 +173,10 @@ class Item(object):
"""
try:
return self.object.serialize().decode('utf-8')
except vobject.base.ValidateError, e:
return self.object.serialize()
except vobject.base.ValidateError as e:
self.log.warn('Validation error %s in %s', e, self.urlpath)
return self.object.serialize(validate=False).decode('utf-8')
return self.object.serialize(validate=False)
@property
def length(self):
......@@ -191,7 +189,7 @@ class Item(object):
return value.utctimetuple()
return time.gmtime()
def __unicode__(self):
def __str__(self):
fn = self.object.getChildValue("fn")
if fn:
return fn
......@@ -249,7 +247,7 @@ class Collection(object):
def get_description(self):
try:
return str(self.metadata.get('collection', 'description'))
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, ValueError):
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
pass
try:
......@@ -268,7 +266,7 @@ class Collection(object):
try:
item = self.read_file(path)
self.my_items.append(item)
except Exception, ex:
except Exception as ex:
self.log.exception("Insert %s failed", path)
return
......@@ -276,7 +274,7 @@ class Collection(object):
try:
item = Collection(path)
self.my_items.append(item)
except Exception, ex:
except Exception as ex:
self.log.exception("Insert %s failed", path)
return
......@@ -304,7 +302,7 @@ class Collection(object):
if not force and mtime == self.mtime and self.metadata is not None:
return
parser = ConfigParser.RawConfigParser()
parser = ConfigParser()
parser.read(self.__metadatafile)
self.metadata = parser
......@@ -350,9 +348,9 @@ class Collection(object):
h = hashlib.sha1()
for item in self.my_items:
if getattr(item, 'etag', None):
h.update(item.etag)
h.update(item.etag.encode('utf-8'))
else:
h.update(item.ctag)
h.update(item.ctag.encode('utf-8'))
self._ctag = '%d-' % self.mtime + h.hexdigest()
self.files = newfiles
......@@ -368,7 +366,7 @@ class Collection(object):
self.my_items = []
self.mtime = 0
self._ctag = ''
self.etag = hashlib.sha1(self.path).hexdigest()
self.etag = hashlib.sha1(self.path.encode('utf-8')).hexdigest()
self.metadata = None
self.metadata_mtime = None
self.scan_dir(False)
......@@ -422,7 +420,7 @@ class Collection(object):
# Touch directory so that another running instance will update
try:
os.utime(self.path, None)
except Exception, ex:
except Exception as ex:
self.log.exception("Failed to set directory mtime")
def write_file(self, item):
......@@ -440,7 +438,7 @@ class Collection(object):
if not os.path.exists(os.path.dirname(self.path)):
try:
os.makedirs(os.path.dirname(self.path))
except OSError, ose:
except OSError as ose:
self.log.exception("Failed to make collection directory %s: %s", self.path, ose)
raise
......@@ -450,10 +448,10 @@ class Collection(object):
path = self.write_file(item)
self.git_add(path, context=context)
self.scan_dir(True)
except OSError, ex:
except OSError as ex:
self.log.exception("Error writing file")
raise
except Exception, ex:
except Exception as ex:
self.log.exception("Caught Exception")
self.log.debug("Failed to create %s: %s", self.path, ex)
raise
......@@ -467,7 +465,7 @@ class Collection(object):
os.unlink(item.path)
self.git_rm(item.path, context=context)
self.scan_dir(True)
except Exception, ex:
except Exception as ex:
self.log.exception("Failed to remove %s", item.path)
raise
......@@ -482,7 +480,7 @@ class Collection(object):
self.scan_file(item.path)
self.git_change(item.path, context=context)
self.scan_dir(True)
except Exception, ex:
except Exception as ex:
self.log.exception("Failed to rewrite %s", item.path)
raise
......@@ -511,7 +509,7 @@ class Collection(object):
self.log.debug('append name %s', name)
try:
new_item = Item(text, name, None, self.urlpath)
except Exception, e:
except Exception as e:
self.log.exception("Cannot create new item")
raise
if new_item.name in (item.name for item in self.my_items):
......@@ -575,7 +573,7 @@ class Collection(object):
for ve in events:
# Check for events with both dtstart and duration entries and
# delete the duration one
if ve.contents.has_key('dtstart') and ve.contents.has_key('duration'):
if 'dtstart' in ve.contents and 'duration' in ve.contents:
del ve.contents['duration']
new_ics.vevent_list = [ve]
new_item = Item(new_ics.serialize().decode('utf-8'), None, path, self.urlpath)
......@@ -584,7 +582,7 @@ class Collection(object):
new_item = Item(new_ics.serialize().decode('utf-8'), None, path, self.urlpath)
self.import_item(new_item, path)
return True
except Exception, ex:
except Exception as ex:
self.log.exception("Failed to import: %s", path)
return False
......@@ -616,7 +614,7 @@ class Collection(object):
"""Color."""
try:
return "#%s" % self.metadata.get('collection', 'color')
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, ValueError):
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
return None
@property
......@@ -648,12 +646,12 @@ class Collection(object):
def is_addressbook(self):
try:
return self.metadata.getboolean('collection', 'is-addressbook')
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, ValueError):
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
return True
@property
def is_calendar(self):
try:
return self.metadata.getboolean('collection', 'is-calendar')
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, ValueError):
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
return True
#!/usr/bin/python
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# This file is part of Calypso Server - Calendar Server
......@@ -42,11 +42,11 @@ from setuptools import setup
try:
from calypso import VERSION
except ImportError, e:
print 'Error importing Calypso, probably dependencies are not installed'
print e
except ImportError as e:
print('Error importing Calypso, probably dependencies are not installed')
print(e)
VERSION = '0.0.1'
print 'Assuming version %s' % VERSION
print('Assuming version %s' % VERSION)
# build_scripts is known to have a lot of public methods
# pylint: disable=R0904
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment