Przeglądaj źródła

Improve documentation

Unrud 6 lat temu
rodzic
commit
88a0af8ba1

+ 4 - 2
radicale/__init__.py

@@ -18,9 +18,10 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-Radicale WSGI application.
+Entry point for external WSGI servers (like uWSGI or Gunicorn).
 
-Can be used with an external WSGI server or the built-in server.
+Configuration files can be specified in the environment variable
+``RADICALE_CONFIG``.
 
 """
 
@@ -57,6 +58,7 @@ def _init_application(config_path, wsgi_errors):
 
 
 def application(environ, start_response):
+    """Entry point for external WSGI servers."""
     config_path = environ.get("RADICALE_CONFIG",
                               os.environ.get("RADICALE_CONFIG"))
     if _application is None:

+ 1 - 0
radicale/__main__.py

@@ -19,6 +19,7 @@
 Radicale executable module.
 
 This module can be executed from a command line with ``$python -m radicale``.
+Uses the built-in WSGI server.
 
 """
 

+ 8 - 3
radicale/app/__init__.py

@@ -20,7 +20,8 @@
 """
 Radicale WSGI application.
 
-Can be used with an external WSGI server or the built-in server.
+Can be used with an external WSGI server (see ``radicale.application()``) or
+the built-in server (see ``radicale.server`` module).
 
 """
 
@@ -63,10 +64,14 @@ class Application(
         ApplicationPropfindMixin, ApplicationProppatchMixin,
         ApplicationPutMixin, ApplicationReportMixin):
 
-    """WSGI application managing collections."""
+    """WSGI application."""
 
     def __init__(self, configuration):
-        """Initialize application."""
+        """Initialize application.
+
+        ``configuration`` see ``radicale.config`` module.
+
+        """
         super().__init__()
         self.configuration = configuration
         self.auth = auth.load(configuration)

+ 5 - 31
radicale/auth/__init__.py

@@ -18,39 +18,13 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-Authentication management.
+Authentication module.
 
-Default is htpasswd authentication.
+Authentication is based on usernames and passwords. If something more
+advanced is needed an external WSGI server or reverse proxy can be used
+(see ``remote_user`` or ``http_x_remote_user`` backend).
 
-Apache's htpasswd command (httpd.apache.org/docs/programs/htpasswd.html)
-manages a file for storing user credentials. It can encrypt passwords using
-different methods, e.g. BCRYPT, MD5-APR1 (a version of MD5 modified for
-Apache), SHA1, or by using the system's CRYPT routine. The CRYPT and SHA1
-encryption methods implemented by htpasswd are considered as insecure. MD5-APR1
-provides medium security as of 2015. Only BCRYPT can be considered secure by
-current standards.
-
-MD5-APR1-encrypted credentials can be written by all versions of htpasswd (it
-is the default, in fact), whereas BCRYPT requires htpasswd 2.4.x or newer.
-
-The `is_authenticated(user, password)` function provided by this module
-verifies the user-given credentials by parsing the htpasswd credential file
-pointed to by the ``htpasswd_filename`` configuration value while assuming
-the password encryption method specified via the ``htpasswd_encryption``
-configuration value.
-
-The following htpasswd password encrpytion methods are supported by Radicale
-out-of-the-box:
-
-    - plain-text (created by htpasswd -p...) -- INSECURE
-    - CRYPT      (created by htpasswd -d...) -- INSECURE
-    - SHA1       (created by htpasswd -s...) -- INSECURE
-
-When passlib (https://pypi.python.org/pypi/passlib) is importable, the
-following significantly more secure schemes are parsable by Radicale:
-
-    - MD5-APR1   (htpasswd -m...) -- htpasswd's default method
-    - BCRYPT     (htpasswd -B...) -- Requires htpasswd 2.4.x
+Take a look at the class ``BaseAuth`` if you want to implement your own.
 
 """
 

+ 35 - 0
radicale/auth/htpasswd.py

@@ -17,6 +17,41 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Authentication backend that checks credentials with a htpasswd file.
+
+Apache's htpasswd command (httpd.apache.org/docs/programs/htpasswd.html)
+manages a file for storing user credentials. It can encrypt passwords using
+different methods, e.g. BCRYPT, MD5-APR1 (a version of MD5 modified for
+Apache), SHA1, or by using the system's CRYPT routine. The CRYPT and SHA1
+encryption methods implemented by htpasswd are considered as insecure. MD5-APR1
+provides medium security as of 2015. Only BCRYPT can be considered secure by
+current standards.
+
+MD5-APR1-encrypted credentials can be written by all versions of htpasswd (it
+is the default, in fact), whereas BCRYPT requires htpasswd 2.4.x or newer.
+
+The `is_authenticated(user, password)` function provided by this module
+verifies the user-given credentials by parsing the htpasswd credential file
+pointed to by the ``htpasswd_filename`` configuration value while assuming
+the password encryption method specified via the ``htpasswd_encryption``
+configuration value.
+
+The following htpasswd password encrpytion methods are supported by Radicale
+out-of-the-box:
+
+    - plain-text (created by htpasswd -p...) -- INSECURE
+    - CRYPT      (created by htpasswd -d...) -- INSECURE
+    - SHA1       (created by htpasswd -s...) -- INSECURE
+
+When passlib (https://pypi.python.org/pypi/passlib) is importable, the
+following significantly more secure schemes are parsable by Radicale:
+
+    - MD5-APR1   (htpasswd -m...) -- htpasswd's default method
+    - BCRYPT     (htpasswd -B...) -- Requires htpasswd 2.4.x
+
+"""
+
 import base64
 import functools
 import hashlib

+ 9 - 0
radicale/auth/http_x_remote_user.py

@@ -17,6 +17,15 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Authentication backend that takes the username from the
+``HTTP_X_REMOTE_USER`` header.
+
+It's intended for use with a reverse proxy. Be aware as this will be insecure
+if the reverse proxy is not configured properly.
+
+"""
+
 import radicale.auth.none as none
 
 

+ 5 - 0
radicale/auth/none.py

@@ -17,6 +17,11 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+A dummy backend that accepts any username and password.
+
+"""
+
 from radicale import auth
 
 

+ 8 - 0
radicale/auth/remote_user.py

@@ -17,6 +17,14 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Authentication backend that takes the username from the ``REMOTE_USER``
+WSGI environment variable.
+
+It's intended for use with an external WSGI server.
+
+"""
+
 import radicale.auth.none as none
 
 

+ 27 - 10
radicale/config.py

@@ -18,9 +18,10 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-Radicale configuration module.
+Configuration module
 
-Give a configparser-like interface to read and write configuration.
+Use ``load()`` to obtain an instance of ``Configuration`` for use with
+``radicale.app.Application``.
 
 """
 
@@ -254,9 +255,16 @@ def parse_compound_paths(*compound_paths):
 
 
 def load(paths=()):
-    """Load configuration from files.
+    """
+    Create instance of ``Configuration`` for use with
+    ``radicale.app.Application``.
+
+    ``paths`` a list of configuration files with the format
+    ``[(PATH, IGNORE_IF_MISSING), ...]``.
+    If a configuration file is missing and IGNORE_IF_MISSING is set, the
+    config is set to ``Configuration.SOURCE_MISSING``.
 
-    ``paths`` a list of the format ``[(PATH, IGNORE_IF_MISSING), ...]``.
+    The configuration can later be changed with ``Configuration.update()``.
 
     """
     configuration = Configuration(DEFAULT_CONFIG_SCHEMA)
@@ -287,6 +295,9 @@ class Configuration:
         ``schema`` a dict that describes the configuration format.
         See ``DEFAULT_CONFIG_SCHEMA``.
 
+        Use ``load()`` to create an instance for use with
+        ``radicale.app.Application``.
+
         """
         self._schema = schema
         self._values = {}
@@ -304,13 +315,12 @@ class Configuration:
         """Update the configuration.
 
         ``config`` a dict of the format {SECTION: {OPTION: VALUE, ...}, ...}.
-        Set to ``Configuration.SOURCE_MISSING`` to indicate a missing
-        configuration source for inspection.
+        The configuration is checked for errors according to the config schema.
 
-        ``source`` a description of the configuration source
+        ``source`` a description of the configuration source (used in error
+        messages).
 
-        ``internal`` allows updating "_internal" sections and skips the source
-        during inspection.
+        ``internal`` allows updating "_internal" sections.
 
         """
         new_values = {}
@@ -407,7 +417,14 @@ class Configuration:
         return copy
 
     def log_config_sources(self):
-        """Inspect all external config sources and write problems to logger."""
+        """
+        A helper function that writes a description of all config sources
+        to logger.
+
+        Configs set to ``Configuration.SOURCE_MISSING`` are described as
+        missing.
+
+        """
         for config, source, _ in self._configs:
             if config is self.SOURCE_MISSING:
                 logger.info("Skipped missing %s", source)

+ 5 - 0
radicale/httputils.py

@@ -17,6 +17,11 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Helper functions for HTTP.
+
+"""
+
 from http import client
 
 NOT_ALLOWED = (

+ 7 - 0
radicale/item/__init__.py

@@ -18,6 +18,11 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Module for address books and calendar entries (see ``Item``).
+
+"""
+
 import math
 import sys
 from hashlib import md5
@@ -257,6 +262,8 @@ def find_tag_and_time_range(vobject_item):
 
 
 class Item:
+    """Class for address book and calendar entries."""
+
     def __init__(self, collection_path=None, collection=None,
                  vobject_item=None, href=None, last_modified=None, text=None,
                  etag=None, uid=None, name=None, component_name=None,

+ 8 - 3
radicale/log.py

@@ -16,10 +16,15 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-Radicale logging module.
+Functions to set up Python's logging facility for Radicale's WSGI application.
 
-Manage logging from a configuration file. For more information, see:
-http://docs.python.org/library/logging.config.html
+Log messages are sent to the first available target of:
+
+  - Error stream specified by the WSGI server in wsgi.errors
+  - systemd-journald
+  - stderr
+
+The logger is thread-safe and fork-safe.
 
 """
 

+ 5 - 0
radicale/pathutils.py

@@ -16,6 +16,11 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Helper functions for working with the file system.
+
+"""
+
 import contextlib
 import os
 import posixpath

+ 8 - 16
radicale/rights/__init__.py

@@ -16,25 +16,17 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-Rights backends.
+The rights module used to determine if a user can read and/or write
+collections and entries.
 
-This module loads the rights backend, according to the rights
-configuration.
+Permissions:
 
-Default rights are based on a regex-based file whose name is specified in the
-config (section "right", key "file").
+  - R: read a collection
+  - r: read an address book or calendar entry
+  - W: write a collection
+  - w: read an address book or calendar entry
 
-Authentication login is matched against the "user" key, and collection's path
-is matched against the "collection" key. You can use Python's ConfigParser
-interpolation values %(login)s and %(path)s. You can also get groups from the
-user regex in the collection with {0}, {1}, etc.
-
-For example, for the "user" key, ".+" means "authenticated user" and ".*"
-means "anybody" (including anonymous users).
-
-Section names are only used for naming the rule.
-
-Leading or ending slashes are trimmed from collection's path.
+Take a look at the class ``BaseRights`` if you want to implement your own.
 
 """
 

+ 5 - 0
radicale/rights/authenticated.py

@@ -15,6 +15,11 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Rights backend that allows authenticated users to read and write all
+calendars and address books.
+
+"""
 
 from radicale import pathutils, rights
 

+ 18 - 0
radicale/rights/from_file.py

@@ -15,6 +15,24 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Rights backend based on a regex-based file whose name is specified in the
+config (section "right", key "file").
+
+Authentication login is matched against the "user" key, and collection's path
+is matched against the "collection" key. You can use Python's ConfigParser
+interpolation values %(login)s and %(path)s. You can also get groups from the
+user regex in the collection with {0}, {1}, etc.
+
+For example, for the "user" key, ".+" means "authenticated user" and ".*"
+means "anybody" (including anonymous users).
+
+Section names are only used for naming the rule.
+
+Leading or ending slashes are trimmed from collection's path.
+
+"""
+
 import configparser
 import re
 

+ 6 - 0
radicale/rights/owner_only.py

@@ -15,6 +15,12 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Rights backend that allows authenticated users to read and write their own
+calendars and address books.
+
+"""
+
 import radicale.rights.authenticated as authenticated
 from radicale import pathutils, rights
 

+ 6 - 0
radicale/rights/owner_write.py

@@ -15,6 +15,12 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Rights backend that allows authenticated users to read all calendars and
+address books but only grants write access to their own.
+
+"""
+
 import radicale.rights.authenticated as authenticated
 from radicale import pathutils, rights
 

+ 3 - 1
radicale/server.py

@@ -18,7 +18,9 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-Radicale WSGI server.
+Built-in WSGI server.
+
+Uses forking on POSIX to overcome Python's GIL.
 
 """
 

+ 2 - 5
radicale/storage/__init__.py

@@ -17,12 +17,9 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-Storage backends.
+The storage module that stores calendars and address books.
 
-This module loads the storage backend, according to the storage configuration.
-
-Default storage uses one folder per collection and one file per collection
-entry.
+Take a look at the class ``BaseCollection`` if you want to implement your own.
 
 """
 

+ 7 - 0
radicale/storage/multifilesystem/__init__.py

@@ -16,6 +16,13 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Storage backend that stores data in the file system.
+
+Uses one folder per collection and one file per collection entry.
+
+"""
+
 import contextlib
 import os
 import time

+ 7 - 0
radicale/web/__init__.py

@@ -14,6 +14,13 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+The web module for the website at ``/.web``.
+
+Take a look at the class ``BaseWeb`` if you want to implement your own.
+
+"""
+
 from importlib import import_module
 
 from radicale.log import logger

+ 12 - 0
radicale/web/internal.py

@@ -14,6 +14,18 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+The default web backend.
+
+Features:
+
+  - Create and delete address books and calendars.
+  - Edit basic metadata of existing address books and calendars.
+  - Upload address books and calendars from files.
+
+"""
+
+
 import os
 import posixpath
 import time

+ 5 - 0
radicale/web/none.py

@@ -14,6 +14,11 @@
 # You should have received a copy of the GNU General Public License
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+A dummy web backend that shows a simple message.
+
+"""
+
 from http import client
 
 from radicale import httputils, pathutils, web

+ 1 - 5
radicale/xmlutils.py

@@ -18,11 +18,7 @@
 # along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-XML and iCal requests manager.
-
-Note that all these functions need to receive unicode objects for full
-iCal requests (PUT) and string objects with charset correctly defined
-in them for XML requests (all but PUT).
+Helper functions for XML.
 
 """