Skip to content

Commit

Permalink
Merge pull request #527 from Kozea/command_config
Browse files Browse the repository at this point in the history
Command config
  • Loading branch information
liZe committed Dec 8, 2016
2 parents 0c1dbc3 + e55d75c commit 42e7347
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 117 deletions.
13 changes: 10 additions & 3 deletions config
Expand Up @@ -45,7 +45,7 @@
# SSL Protocol used. See python's ssl module for available values
#protocol = PROTOCOL_SSLv23

# Ciphers available. See python's ssl module for available ciphers
# Available ciphers. See python's ssl module for available ciphers
#ciphers =

# Reverse DNS to resolve client address in logs
Expand Down Expand Up @@ -106,11 +106,16 @@
# Sync all changes to disk during requests. (This can impair performance.)
# Disabling it increases the risk of data loss, when the system crashes or
# power fails!
#fsync = True
#filesystem_fsync = True

# Close the lock file when no more clients are waiting.
# This option is not very useful in general, but on Windows files that are
# opened cannot be deleted.
#filesystem_close_lock_file = False

# Command that is run after changes to storage
#hook =
# Example: git add -A && (git diff --cached --quiet || git commit -m "Changes by "%(user)s)
#hook =


[logging]
Expand All @@ -120,8 +125,10 @@
# For more information about the syntax of the configuration file, see:
# http://docs.python.org/library/logging.config.html
#config = /etc/radicale/logging

# Set the default logging level to debug
#debug = False

# Store all environment variables (including those set in the shell)
#full_environment = False

Expand Down
26 changes: 14 additions & 12 deletions radicale/__init__.py
Expand Up @@ -51,28 +51,28 @@
VERSION = "2.0.0rc0"

NOT_ALLOWED = (
client.FORBIDDEN, (("Content-type", "text/plain"),),
client.FORBIDDEN, (("Content-Type", "text/plain"),),
"Access to the requested resource forbidden.")
NOT_FOUND = (
client.NOT_FOUND, (("Content-type", "text/plain"),),
client.NOT_FOUND, (("Content-Type", "text/plain"),),
"The requested resource could not be found.")
WEBDAV_PRECONDITION_FAILED = (
client.CONFLICT, (("Content-type", "text/plain"),),
client.CONFLICT, (("Content-Type", "text/plain"),),
"WebDAV precondition failed.")
PRECONDITION_FAILED = (
client.PRECONDITION_FAILED,
(("Content-type", "text/plain"),), "Precondition failed.")
(("Content-Type", "text/plain"),), "Precondition failed.")
REQUEST_TIMEOUT = (
client.REQUEST_TIMEOUT, (("Content-type", "text/plain"),),
client.REQUEST_TIMEOUT, (("Content-Type", "text/plain"),),
"Connection timed out.")
REQUEST_ENTITY_TOO_LARGE = (
client.REQUEST_ENTITY_TOO_LARGE, (("Content-type", "text/plain"),),
client.REQUEST_ENTITY_TOO_LARGE, (("Content-Type", "text/plain"),),
"Request body too large.")
REMOTE_DESTINATION = (
client.BAD_GATEWAY, (("Content-type", "text/plain"),),
client.BAD_GATEWAY, (("Content-Type", "text/plain"),),
"Remote destination not supported.")
DIRECTORY_LISTING = (
client.FORBIDDEN, (("Content-type", "text/plain"),),
client.FORBIDDEN, (("Content-Type", "text/plain"),),
"Directory listings are not supported.")

DAV_HEADERS = "1, 2, 3, calendar-access, addressbook, extended-mkcol"
Expand Down Expand Up @@ -288,6 +288,7 @@ def response(status, headers=(), answer=None):
headers["Content-Encoding"] = "gzip"

headers["Content-Length"] = str(len(answer))
headers["Content-Type"] += "; charset=%s" % self.encoding

# Add extra headers set in configuration
if self.configuration.has_section("headers"):
Expand Down Expand Up @@ -389,7 +390,7 @@ def response(status, headers=(), answer=None):
status = client.UNAUTHORIZED
realm = self.configuration.get("server", "realm")
headers = dict(headers)
headers.update ({
headers.update({
"WWW-Authenticate":
"Basic realm=\"%s\"" % realm})

Expand Down Expand Up @@ -441,13 +442,13 @@ def do_DELETE(self, environ, path, user):
answer = xmlutils.delete(path, item)
else:
answer = xmlutils.delete(path, item.collection, item.href)
return client.OK, {}, answer
return client.OK, {"Content-Type": "text/xml"}, answer

def do_GET(self, environ, path, user):
"""Manage GET request."""
# Display a "Radicale works!" message if the root URL is requested
if not path.strip("/"):
return client.OK, {"Content-type": "text/plain"}, "Radicale works!"
return client.OK, {"Content-Type": "text/plain"}, "Radicale works!"
if not self._access(user, path, "r"):
return NOT_ALLOWED
with self.Collection.acquire_lock("r", user):
Expand All @@ -458,7 +459,8 @@ def do_GET(self, environ, path, user):
return NOT_FOUND
if isinstance(item, self.Collection):
collection = item
if collection.get_meta("tag") not in ("VADDRESSBOOK", "VCALENDAR"):
if collection.get_meta("tag") not in (
"VADDRESSBOOK", "VCALENDAR"):
return DIRECTORY_LISTING
else:
collection = item.collection
Expand Down
91 changes: 45 additions & 46 deletions radicale/__main__.py
Expand Up @@ -22,8 +22,8 @@
"""

import argparse
import atexit
import optparse
import os
import select
import signal
Expand All @@ -39,44 +39,44 @@

def run():
"""Run Radicale as a standalone server."""
# Get command-line options
parser = optparse.OptionParser(version=VERSION)
parser.add_option(
"-d", "--daemon", action="store_true",
help="launch as daemon")
parser.add_option(
"-p", "--pid",
help="set PID filename for daemon mode")
parser.add_option(
"-f", "--foreground", action="store_false", dest="daemon",
help="launch in foreground (opposite of --daemon)")
parser.add_option(
"-H", "--hosts",
help="set server hostnames and ports")
parser.add_option(
"-s", "--ssl", action="store_true",
help="use SSL connection")
parser.add_option(
"-S", "--no-ssl", action="store_false", dest="ssl",
help="do not use SSL connection (opposite of --ssl)")
parser.add_option(
"-k", "--key",
help="set private key file")
parser.add_option(
"-c", "--certificate",
help="set certificate file")
parser.add_option(
"-D", "--debug", action="store_true",
help="print debug information")
parser.add_option(
"-C", "--config",
help="use a specific configuration file")

options = parser.parse_args()[0]

if options.config:
# Get command-line arguments
parser = argparse.ArgumentParser(usage="radicale [OPTIONS]")

parser.add_argument("--version", action="version", version=VERSION)
parser.add_argument(
"-C", "--config", help="use a specific configuration file")

groups = {}
for section, values in config.INITIAL_CONFIG.items():
group = parser.add_argument_group(section)
groups[group] = []
for option, data in values.items():
kwargs = data.copy()
long_name = "--{0}-{1}".format(
section, option.replace("_", "-"))
args = kwargs.pop("aliases", [])
args.append(long_name)
kwargs["dest"] = "{0}_{1}".format(section, option)
groups[group].append(kwargs["dest"])

if kwargs.pop("value") in ("True", "False"):
kwargs["action"] = "store_const"
kwargs["const"] = "True"
opposite_args = kwargs.pop("opposite", [])
opposite_args.append("--no{0}".format(long_name[1:]))
group.add_argument(*args, **kwargs)

kwargs["const"] = "False"
kwargs["help"] = "do not {0} (opposite of {1})".format(
kwargs["help"], long_name)
group.add_argument(*opposite_args, **kwargs)
else:
group.add_argument(*args, **kwargs)

args = parser.parse_args()
if args.config:
configuration = config.load()
configuration_found = configuration.read(options.config)
configuration_found = configuration.read(args.config)
else:
configuration_paths = [
"/etc/radicale/config",
Expand All @@ -86,14 +86,13 @@ def run():
configuration = config.load(configuration_paths)
configuration_found = True

# Update Radicale configuration according to options
for option in parser.option_list:
key = option.dest
if key:
section = "logging" if key == "debug" else "server"
value = getattr(options, key)
# Update Radicale configuration according to arguments
for group, actions in groups.items():
section = group.title
for action in actions:
value = getattr(args, action)
if value is not None:
configuration.set(section, key, str(value))
configuration.set(section, action.split('_', 1)[1], value)

# Start logging
filename = os.path.expanduser(configuration.get("logging", "config"))
Expand All @@ -102,7 +101,7 @@ def run():

# Log a warning if the configuration file of the command line is not found
if not configuration_found:
logger.warning("Configuration file '%s' not found" % options.config)
logger.warning("Configuration file '%s' not found" % args.config)

try:
serve(configuration, logger)
Expand Down

0 comments on commit 42e7347

Please sign in to comment.