1
0
Эх сурвалжийг харах

Python 3 support and minor fixes.

Guillaume Ayoub 16 жил өмнө
parent
commit
4ee09cf817

+ 1 - 4
radicale.py

@@ -30,13 +30,10 @@ Radicale Server entry point.
 Launch the Radicale Serve according to the configuration.
 """
 
-import sys
-import BaseHTTPServer
-
 import radicale
 
 if radicale.config.get("server", "type") == "http":
-    server = BaseHTTPServer.HTTPServer(
+    server = radicale.server.HTTPServer(
         ("", radicale.config.getint("server", "port")),
         radicale.CalendarHandler)
     server.serve_forever()

+ 13 - 17
radicale/__init__.py

@@ -21,25 +21,21 @@
 # TODO: Manage errors (see xmlutils)
 
 import posixpath
-import httplib
-import BaseHTTPServer
+try:
+    from http import client, server
+except ImportError:
+    import httplib as client
+    import BaseHTTPServer as server
 
-import config
-import support
-import acl
-import xmlutils
-import calendar
+from radicale import config, support, xmlutils
 
-_users = acl.users()
-_calendars = support.calendars()
-
-class CalendarHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+class CalendarHandler(server.BaseHTTPRequestHandler):
     """HTTP requests handler for calendars."""
     def _parse_path(self):
         path = self.path.strip("/").split("/")
         if len(path) >= 2:
             cal = "%s/%s" % (path[0], path[1])
-            self.calendar = calendar.Calendar(_users[0], cal)
+            self.calendar = calendar.Calendar("radicale", cal)
 
     def do_DELETE(self):
         """Manage DELETE ``request``."""
@@ -47,14 +43,14 @@ class CalendarHandler(BaseHTTPServer.BaseHTTPRequestHandler):
         obj = self.headers.get("if-match", None)
         answer = xmlutils.delete(obj, self.calendar, self.path)
 
-        self.send_response(httplib.NO_CONTENT)
+        self.send_response(client.NO_CONTENT)
         self.send_header("Content-Length", len(answer))
         self.end_headers()
         self.wfile.write(answer)
 
     def do_OPTIONS(self):
         """Manage OPTIONS ``request``."""
-        self.send_response(httplib.OK)
+        self.send_response(client.OK)
         self.send_header("Allow", "DELETE, OPTIONS, PROPFIND, PUT, REPORT")
         self.send_header("DAV", "1, calendar-access")
         self.end_headers()
@@ -65,7 +61,7 @@ class CalendarHandler(BaseHTTPServer.BaseHTTPRequestHandler):
         xml_request = self.rfile.read(int(self.headers["Content-Length"]))
         answer = xmlutils.propfind(xml_request, self.calendar, self.path)
 
-        self.send_response(httplib.MULTI_STATUS)
+        self.send_response(client.MULTI_STATUS)
         self.send_header("DAV", "1, calendar-access")
         self.send_header("Content-Length", len(answer))
         self.end_headers()
@@ -84,7 +80,7 @@ class CalendarHandler(BaseHTTPServer.BaseHTTPRequestHandler):
         obj = self.headers.get("if-match", None)
         xmlutils.put(ical_request, self.calendar, self.path, obj)
 
-        self.send_response(httplib.CREATED)
+        self.send_response(client.CREATED)
 
     def do_REPORT(self):
         """Manage REPORT ``request``."""
@@ -92,7 +88,7 @@ class CalendarHandler(BaseHTTPServer.BaseHTTPRequestHandler):
         xml_request = self.rfile.read(int(self.headers["Content-Length"]))
         answer = xmlutils.report(xml_request, self.calendar, self.path)
 
-        self.send_response(httplib.MULTI_STATUS)
+        self.send_response(client.MULTI_STATUS)
         self.send_header("Content-Length", len(answer))
         self.end_headers()
         self.wfile.write(answer)

+ 1 - 1
radicale/acl/__init__.py

@@ -25,7 +25,7 @@ This module loads a list of users with access rights, according to the acl
 configuration.
 """
 
-from .. import config
+from radicale import config
 
 _acl = __import__(config.get("acl", "type"), locals(), globals())
 

+ 1 - 1
radicale/acl/fake.py

@@ -24,7 +24,7 @@ Fake ACL.
 Just load the default user set in configuration, with no rights management.
 """
 
-from .. import config
+from radicale import config
 
 def users():
     """Get the list of all users."""

+ 1 - 1
radicale/acl/htpasswd.py

@@ -26,7 +26,7 @@ Load the list of users according to the htpasswd configuration.
 
 # TODO: Manage rights
 
-from .. import config
+from radicale import config
 
 def users():
     """Get the list of all users."""

+ 8 - 7
radicale/calendar.py

@@ -24,7 +24,7 @@ Radicale calendar classes.
 Define the main classes of a calendar as seen from the server.
 """
 
-import support
+from radicale import support
 
 hash_tag = lambda vcalendar: str(hash(vcalendar))
 
@@ -33,8 +33,9 @@ class Calendar(object):
     def __init__(self, user, cal):
         """Initialize the calendar with ``cal`` and ``user`` parameters."""
         # TODO: Use properties from the calendar configuration
+        self.support = support.load()
         self.encoding = "utf-8"
-        self.owner = "lize"
+        self.owner = "radicale"
         self.user = user
         self.cal = cal
         self.version = "2.0"
@@ -43,22 +44,22 @@ class Calendar(object):
     def append(self, vcalendar):
         """Append vcalendar to the calendar."""
         self.ctag = hash_tag(self.vcalendar())
-        support.append(self.cal, vcalendar)
+        self.support.append(self.cal, vcalendar)
 
     def remove(self, uid):
         """Remove object named ``uid`` from the calendar."""
         self.ctag = hash_tag(self.vcalendar())
-        support.remove(self.cal, uid)
+        self.support.remove(self.cal, uid)
 
     def replace(self, uid, vcalendar):
         """Replace objet named ``uid`` by ``vcalendar`` in the calendar."""
         self.ctag = hash_tag(self.vcalendar())
-        support.remove(self.cal, uid)
-        support.append(self.cal, vcalendar)
+        self.support.remove(self.cal, uid)
+        self.support.append(self.cal, vcalendar)
 
     def vcalendar(self):
         """Return unicode calendar from the calendar."""
-        return unicode(support.read(self.cal), self.encoding)
+        return self.support.read(self.cal)
 
     def etag(self):
         """Return etag from calendar."""

+ 6 - 3
radicale/config.py

@@ -24,7 +24,10 @@ Radicale configuration module.
 Give a configparser-like interface to read and write configuration.
 """
 
-from ConfigParser import RawConfigParser as ConfigParser
+try:
+    from configparser import RawConfigParser as ConfigParser
+except ImportError:
+    from ConfigParser import RawConfigParser as ConfigParser
 
 _config = ConfigParser()
 get = _config.get
@@ -68,9 +71,9 @@ _initial = {
         },
     }
 
-for section, values in _initial.iteritems():
+for section, values in _initial.items():
     _config.add_section(section)
-    for key, value in values.iteritems():
+    for key, value in values.items():
         _config.set(section, key, value)
 
 # TODO: Use abstract filename for other platforms

+ 9 - 9
radicale/ical.py

@@ -24,7 +24,7 @@ iCal parsing functions.
 
 # TODO: Manage filters (see xmlutils)
 
-import calendar
+from radicale import calendar
 
 def write_calendar(headers=[
         calendar.Header("PRODID:-//Radicale//NONSGML Radicale Server//EN"),
@@ -32,14 +32,14 @@ def write_calendar(headers=[
                   timezones=[], todos=[], events=[]):
     """Create calendar from ``headers``, ``timezones``, ``todos``, ``events``."""
     # TODO: Manage encoding and EOL
-    cal = u"\n".join((
-        u"BEGIN:VCALENDAR",
-        u"\n".join([header.text for header in headers]),
-        u"\n".join([timezone.text for timezone in timezones]),
-        u"\n".join([todo.text for todo in todos]),
-        u"\n".join([event.text for event in events]),
-        u"END:VCALENDAR"))
-    return u"\n".join([line for line in cal.splitlines() if line])
+    cal = "\n".join((
+        "BEGIN:VCALENDAR",
+        "\n".join([header.text for header in headers]),
+        "\n".join([timezone.text for timezone in timezones]),
+        "\n".join([todo.text for todo in todos]),
+        "\n".join([event.text for event in events]),
+        "END:VCALENDAR"))
+    return "\n".join([line for line in cal.splitlines() if line])
 
 def headers(vcalendar):
     """Find Headers items in ``vcalendar``."""

+ 5 - 8
radicale/support/__init__.py

@@ -22,12 +22,9 @@
 Calendar storage support configuration.
 """
 
-from .. import config
+from radicale import config
 
-_support = __import__(config.get("support", "type"), locals(), globals())
-
-append = _support.append
-calendars =_support.calendars
-mkcalendar =_support.mkcalendar
-read = _support.read
-remove = _support.remove
+def load():
+    module = __import__("radicale.support", globals(), locals(),
+                        [config.get("support", "type")])
+    return getattr(module, config.get("support", "type"))

+ 20 - 17
radicale/support/plain.py

@@ -24,12 +24,15 @@ Plain text storage.
 
 import os
 import posixpath
+import codecs
 
-from .. import ical
-from .. import config
+from radicale import config, ical
 
 _folder = os.path.expanduser(config.get("support", "folder"))
 
+def _open(path, mode="r"):
+    return codecs.open(path, mode, config.get("encoding", "stock"))
+
 def calendars():
     """List available calendars paths."""
     calendars = []
@@ -45,17 +48,17 @@ def mkcalendar(name):
     user, cal = name.split(posixpath.sep)
     if not os.path.exists(os.path.join(_folder, user)):
         os.makedirs(os.path.join(_folder, user))
-    fd = open(os.path.join(_folder, user, cal), "w")
-    fd.write(ical.write_calendar().encode(config.get("encoding", "stock")))
+    fd = _open(os.path.join(_folder, user, cal), "w")
+    fd.write(ical.write_calendar())
 
 def read(cal):
     """Read calendar ``cal``."""
     path = os.path.join(_folder, cal.replace(posixpath.sep, os.path.sep))
-    return open(path).read()
+    return _open(path).read()
 
 def append(cal, vcalendar):
     """Append ``vcalendar`` to ``cal``."""
-    old_calendar = unicode(read(cal), config.get("encoding", "stock"))
+    old_calendar = read(cal)
     old_tzs = [tz.tzid for tz in ical.timezones(old_calendar)]
     path = os.path.join(_folder, cal.replace(posixpath.sep, os.path.sep))
 
@@ -69,29 +72,29 @@ def append(cal, vcalendar):
 
     for tz in ical.timezones(vcalendar):
         if tz.tzid not in old_tzs:
-            # TODO: Manage position, encoding and EOL
-            fd = open(path)
+            # TODO: Manage position and EOL
+            fd = _open(path)
             lines = [line for line in fd.readlines() if line]
             fd.close()
 
             for i,line in enumerate(tz.text.splitlines()):
-                lines.insert(2+i, line.encode(config.get("encoding", "stock"))+"\n")
+                lines.insert(2 + i, line + "\n")
 
-            fd = open(path, "w")
+            fd = _open(path, "w")
             fd.writelines(lines)
             fd.close()
 
     for obj in objects:
         if obj.etag() not in old_objects:
-            # TODO: Manage position, encoding and EOL
-            fd = open(path)
+            # TODO: Manage position and EOL
+            fd = _open(path)
             lines = [line for line in fd.readlines() if line]
             fd.close()
 
             for line in obj.text.splitlines():
-                lines.insert(-1, line.encode(config.get("encoding", "stock"))+"\n")
+                lines.insert(-1, line + "\n")
 
-            fd = open(path, "w")
+            fd = _open(path, "w")
             fd.writelines(lines)
             fd.close()
 
@@ -99,15 +102,15 @@ def remove(cal, etag):
     """Remove object named ``etag`` from ``cal``."""
     path = os.path.join(_folder, cal.replace(posixpath.sep, os.path.sep))
 
-    cal = unicode(read(cal), config.get("encoding", "stock"))
+    cal = read(cal)
 
     headers = ical.headers(cal)
     timezones = ical.timezones(cal)
     todos = [todo for todo in ical.todos(cal) if todo.etag() != etag]
     events = [event for event in ical.events(cal) if event.etag() != etag]
 
-    fd = open(path, "w")
-    fd.write(ical.write_calendar(headers, timezones, todos, events).encode(config.get("encoding", "stock")))
+    fd = _open(path, "w")
+    fd.write(ical.write_calendar(headers, timezones, todos, events))
     fd.close()
 
 if config.get("support", "calendar"):

+ 1 - 2
radicale/xmlutils.py

@@ -31,8 +31,7 @@ in them for XML requests (all but PUT).
 
 import xml.etree.ElementTree as ET
 
-import config
-import ical
+from radicale import config, ical
 
 # TODO: This is a well-known and accepted hack for ET to avoid ET from renaming
 #       namespaces, which is accepted in XML norm but often not in XML