Python 3 support and minor fixes.

This commit is contained in:
Guillaume Ayoub 2010-01-15 16:04:03 +01:00
parent 4a0d3936e8
commit 4ee09cf817
11 changed files with 66 additions and 70 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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())

View File

@ -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."""

View File

@ -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."""

View File

@ -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."""

View File

@ -24,6 +24,9 @@ Radicale configuration module.
Give a configparser-like interface to read and write configuration.
"""
try:
from configparser import RawConfigParser as ConfigParser
except ImportError:
from ConfigParser import RawConfigParser as ConfigParser
_config = ConfigParser()
@ -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

View File

@ -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``."""

View File

@ -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"))

View File

@ -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"):

View File

@ -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