diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml
index 1185e5eb..41ccb093 100644
--- a/.github/workflows/publish-docker.yml
+++ b/.github/workflows/publish-docker.yml
@@ -70,7 +70,7 @@ jobs:
password: ${{ secrets.GHCR_TOKEN }}
- name: Docker Build and Push
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
if: success()
with:
context: .
diff --git a/data/interfaces/default/scheduler_table.html b/data/interfaces/default/scheduler_table.html
index 8d264aa9..c4087f17 100644
--- a/data/interfaces/default/scheduler_table.html
+++ b/data/interfaces/default/scheduler_table.html
@@ -13,8 +13,6 @@ DOCUMENTATION :: END
import datetime
import plexpy
from plexpy import common, helpers
-
- scheduled_jobs = [j.id for j in plexpy.SCHED.get_jobs()]
%>
@@ -29,16 +27,15 @@ DOCUMENTATION :: END
% for job, job_type in common.SCHEDULER_LIST.items():
- % if job in scheduled_jobs:
<%
sched_job = plexpy.SCHED.get_job(job)
- now = datetime.datetime.now(sched_job.next_run_time.tzinfo)
%>
+ % if sched_job:
${sched_job.id} |
Active |
${helpers.format_timedelta_Hms(sched_job.trigger.interval)} |
- ${helpers.format_timedelta_Hms(sched_job.next_run_time - now)} |
+ ${helpers.format_timedelta_Hms(sched_job.next_run_time - datetime.datetime.now(sched_job.next_run_time.tzinfo))} |
${sched_job.next_run_time.astimezone(plexpy.SYS_TIMEZONE).strftime('%Y-%m-%d %H:%M:%S')} |
% elif job_type == 'websocket' and plexpy.WS_CONNECTED:
diff --git a/lib/backports/__init__.py b/lib/backports/__init__.py
index 8db66d3d..0d1f7edf 100644
--- a/lib/backports/__init__.py
+++ b/lib/backports/__init__.py
@@ -1 +1 @@
-__path__ = __import__("pkgutil").extend_path(__path__, __name__)
+__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore
diff --git a/lib/backports/tarfile/__init__.py b/lib/backports/tarfile/__init__.py
index 6dd498dc..8c16881c 100644
--- a/lib/backports/tarfile/__init__.py
+++ b/lib/backports/tarfile/__init__.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
#-------------------------------------------------------------------
# tarfile.py
#-------------------------------------------------------------------
@@ -46,7 +45,6 @@ import time
import struct
import copy
import re
-import warnings
from .compat.py38 import removesuffix
@@ -639,6 +637,10 @@ class _FileInFile(object):
def flush(self):
pass
+ @property
+ def mode(self):
+ return 'rb'
+
def readable(self):
return True
@@ -875,7 +877,7 @@ class TarInfo(object):
pax_headers = ('A dictionary containing key-value pairs of an '
'associated pax extended header.'),
sparse = 'Sparse member information.',
- tarfile = None,
+ _tarfile = None,
_sparse_structs = None,
_link_target = None,
)
@@ -904,6 +906,24 @@ class TarInfo(object):
self.sparse = None # sparse member information
self.pax_headers = {} # pax header information
+ @property
+ def tarfile(self):
+ import warnings
+ warnings.warn(
+ 'The undocumented "tarfile" attribute of TarInfo objects '
+ + 'is deprecated and will be removed in Python 3.16',
+ DeprecationWarning, stacklevel=2)
+ return self._tarfile
+
+ @tarfile.setter
+ def tarfile(self, tarfile):
+ import warnings
+ warnings.warn(
+ 'The undocumented "tarfile" attribute of TarInfo objects '
+ + 'is deprecated and will be removed in Python 3.16',
+ DeprecationWarning, stacklevel=2)
+ self._tarfile = tarfile
+
@property
def path(self):
'In pax headers, "name" is called "path".'
@@ -1198,7 +1218,7 @@ class TarInfo(object):
for keyword, value in pax_headers.items():
keyword = keyword.encode("utf-8")
if binary:
- # Try to restore the original byte representation of `value'.
+ # Try to restore the original byte representation of 'value'.
# Needless to say, that the encoding must match the string.
value = value.encode(encoding, "surrogateescape")
else:
@@ -1643,14 +1663,14 @@ class TarFile(object):
def __init__(self, name=None, mode="r", fileobj=None, format=None,
tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
errors="surrogateescape", pax_headers=None, debug=None,
- errorlevel=None, copybufsize=None):
- """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
+ errorlevel=None, copybufsize=None, stream=False):
+ """Open an (uncompressed) tar archive 'name'. 'mode' is either 'r' to
read from an existing archive, 'a' to append data to an existing
- file or 'w' to create a new file overwriting an existing one. `mode'
+ file or 'w' to create a new file overwriting an existing one. 'mode'
defaults to 'r'.
- If `fileobj' is given, it is used for reading or writing data. If it
- can be determined, `mode' is overridden by `fileobj's mode.
- `fileobj' is not closed, when TarFile is closed.
+ If 'fileobj' is given, it is used for reading or writing data. If it
+ can be determined, 'mode' is overridden by 'fileobj's mode.
+ 'fileobj' is not closed, when TarFile is closed.
"""
modes = {"r": "rb", "a": "r+b", "w": "wb", "x": "xb"}
if mode not in modes:
@@ -1675,6 +1695,8 @@ class TarFile(object):
self.name = os.path.abspath(name) if name else None
self.fileobj = fileobj
+ self.stream = stream
+
# Init attributes.
if format is not None:
self.format = format
@@ -1977,7 +1999,7 @@ class TarFile(object):
self.fileobj.close()
def getmember(self, name):
- """Return a TarInfo object for member ``name``. If ``name`` can not be
+ """Return a TarInfo object for member 'name'. If 'name' can not be
found in the archive, KeyError is raised. If a member occurs more
than once in the archive, its last occurrence is assumed to be the
most up-to-date version.
@@ -2005,9 +2027,9 @@ class TarFile(object):
def gettarinfo(self, name=None, arcname=None, fileobj=None):
"""Create a TarInfo object from the result of os.stat or equivalent
- on an existing file. The file is either named by ``name``, or
- specified as a file object ``fileobj`` with a file descriptor. If
- given, ``arcname`` specifies an alternative name for the file in the
+ on an existing file. The file is either named by 'name', or
+ specified as a file object 'fileobj' with a file descriptor. If
+ given, 'arcname' specifies an alternative name for the file in the
archive, otherwise, the name is taken from the 'name' attribute of
'fileobj', or the 'name' argument. The name should be a text
string.
@@ -2031,7 +2053,7 @@ class TarFile(object):
# Now, fill the TarInfo object with
# information specific for the file.
tarinfo = self.tarinfo()
- tarinfo.tarfile = self # Not needed
+ tarinfo._tarfile = self # To be removed in 3.16.
# Use os.stat or os.lstat, depending on if symlinks shall be resolved.
if fileobj is None:
@@ -2103,11 +2125,15 @@ class TarFile(object):
return tarinfo
def list(self, verbose=True, *, members=None):
- """Print a table of contents to sys.stdout. If ``verbose`` is False, only
- the names of the members are printed. If it is True, an `ls -l'-like
- output is produced. ``members`` is optional and must be a subset of the
+ """Print a table of contents to sys.stdout. If 'verbose' is False, only
+ the names of the members are printed. If it is True, an 'ls -l'-like
+ output is produced. 'members' is optional and must be a subset of the
list returned by getmembers().
"""
+ # Convert tarinfo type to stat type.
+ type2mode = {REGTYPE: stat.S_IFREG, SYMTYPE: stat.S_IFLNK,
+ FIFOTYPE: stat.S_IFIFO, CHRTYPE: stat.S_IFCHR,
+ DIRTYPE: stat.S_IFDIR, BLKTYPE: stat.S_IFBLK}
self._check()
if members is None:
@@ -2117,7 +2143,8 @@ class TarFile(object):
if tarinfo.mode is None:
_safe_print("??????????")
else:
- _safe_print(stat.filemode(tarinfo.mode))
+ modetype = type2mode.get(tarinfo.type, 0)
+ _safe_print(stat.filemode(modetype | tarinfo.mode))
_safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid,
tarinfo.gname or tarinfo.gid))
if tarinfo.ischr() or tarinfo.isblk():
@@ -2141,11 +2168,11 @@ class TarFile(object):
print()
def add(self, name, arcname=None, recursive=True, *, filter=None):
- """Add the file ``name`` to the archive. ``name`` may be any type of file
- (directory, fifo, symbolic link, etc.). If given, ``arcname``
+ """Add the file 'name' to the archive. 'name' may be any type of file
+ (directory, fifo, symbolic link, etc.). If given, 'arcname'
specifies an alternative name for the file in the archive.
Directories are added recursively by default. This can be avoided by
- setting ``recursive`` to False. ``filter`` is a function
+ setting 'recursive' to False. 'filter' is a function
that expects a TarInfo object argument and returns the changed
TarInfo object, if it returns None the TarInfo object will be
excluded from the archive.
@@ -2192,13 +2219,16 @@ class TarFile(object):
self.addfile(tarinfo)
def addfile(self, tarinfo, fileobj=None):
- """Add the TarInfo object ``tarinfo`` to the archive. If ``fileobj`` is
- given, it should be a binary file, and tarinfo.size bytes are read
- from it and added to the archive. You can create TarInfo objects
- directly, or by using gettarinfo().
+ """Add the TarInfo object 'tarinfo' to the archive. If 'tarinfo' represents
+ a non zero-size regular file, the 'fileobj' argument should be a binary file,
+ and tarinfo.size bytes are read from it and added to the archive.
+ You can create TarInfo objects directly, or by using gettarinfo().
"""
self._check("awx")
+ if fileobj is None and tarinfo.isreg() and tarinfo.size != 0:
+ raise ValueError("fileobj not provided for non zero-size regular file")
+
tarinfo = copy.copy(tarinfo)
buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
@@ -2220,11 +2250,12 @@ class TarFile(object):
if filter is None:
filter = self.extraction_filter
if filter is None:
+ import warnings
warnings.warn(
'Python 3.14 will, by default, filter extracted tar '
+ 'archives and reject files or modify their metadata. '
+ 'Use the filter argument to control this behavior.',
- DeprecationWarning)
+ DeprecationWarning, stacklevel=3)
return fully_trusted_filter
if isinstance(filter, str):
raise TypeError(
@@ -2243,12 +2274,12 @@ class TarFile(object):
filter=None):
"""Extract all members from the archive to the current working
directory and set owner, modification time and permissions on
- directories afterwards. `path' specifies a different directory
- to extract to. `members' is optional and must be a subset of the
- list returned by getmembers(). If `numeric_owner` is True, only
+ directories afterwards. 'path' specifies a different directory
+ to extract to. 'members' is optional and must be a subset of the
+ list returned by getmembers(). If 'numeric_owner' is True, only
the numbers for user/group names are used and not the names.
- The `filter` function will be called on each member just
+ The 'filter' function will be called on each member just
before extraction.
It can return a changed TarInfo or None to skip the member.
String names of common filters are accepted.
@@ -2288,13 +2319,13 @@ class TarFile(object):
filter=None):
"""Extract a member from the archive to the current working directory,
using its full name. Its file information is extracted as accurately
- as possible. `member' may be a filename or a TarInfo object. You can
- specify a different directory using `path'. File attributes (owner,
- mtime, mode) are set unless `set_attrs' is False. If `numeric_owner`
+ as possible. 'member' may be a filename or a TarInfo object. You can
+ specify a different directory using 'path'. File attributes (owner,
+ mtime, mode) are set unless 'set_attrs' is False. If 'numeric_owner'
is True, only the numbers for user/group names are used and not
the names.
- The `filter` function will be called before extraction.
+ The 'filter' function will be called before extraction.
It can return a changed TarInfo or None to skip the member.
String names of common filters are accepted.
"""
@@ -2359,10 +2390,10 @@ class TarFile(object):
self._dbg(1, "tarfile: %s %s" % (type(e).__name__, e))
def extractfile(self, member):
- """Extract a member from the archive as a file object. ``member`` may be
- a filename or a TarInfo object. If ``member`` is a regular file or
+ """Extract a member from the archive as a file object. 'member' may be
+ a filename or a TarInfo object. If 'member' is a regular file or
a link, an io.BufferedReader object is returned. For all other
- existing members, None is returned. If ``member`` does not appear
+ existing members, None is returned. If 'member' does not appear
in the archive, KeyError is raised.
"""
self._check("r")
@@ -2406,7 +2437,7 @@ class TarFile(object):
if upperdirs and not os.path.exists(upperdirs):
# Create directories that are not part of the archive with
# default permissions.
- os.makedirs(upperdirs)
+ os.makedirs(upperdirs, exist_ok=True)
if tarinfo.islnk() or tarinfo.issym():
self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
@@ -2559,7 +2590,8 @@ class TarFile(object):
os.lchown(targetpath, u, g)
else:
os.chown(targetpath, u, g)
- except OSError as e:
+ except (OSError, OverflowError) as e:
+ # OverflowError can be raised if an ID doesn't fit in 'id_t'
raise ExtractError("could not change owner") from e
def chmod(self, tarinfo, targetpath):
@@ -2642,7 +2674,9 @@ class TarFile(object):
break
if tarinfo is not None:
- self.members.append(tarinfo)
+ # if streaming the file we do not want to cache the tarinfo
+ if not self.stream:
+ self.members.append(tarinfo)
else:
self._loaded = True
@@ -2693,11 +2727,12 @@ class TarFile(object):
def _load(self):
"""Read through the entire archive file and look for readable
- members.
+ members. This should not run if the file is set to stream.
"""
- while self.next() is not None:
- pass
- self._loaded = True
+ if not self.stream:
+ while self.next() is not None:
+ pass
+ self._loaded = True
def _check(self, mode=None):
"""Check if TarFile is still open, and if the operation's mode
diff --git a/lib/certifi/__init__.py b/lib/certifi/__init__.py
index 1c91f3ec..62b27b63 100644
--- a/lib/certifi/__init__.py
+++ b/lib/certifi/__init__.py
@@ -1,4 +1,4 @@
from .core import contents, where
__all__ = ["contents", "where"]
-__version__ = "2024.02.02"
+__version__ = "2024.06.02"
diff --git a/lib/certifi/cacert.pem b/lib/certifi/cacert.pem
index fac3c319..6e1f1a67 100644
--- a/lib/certifi/cacert.pem
+++ b/lib/certifi/cacert.pem
@@ -4812,3 +4812,27 @@ X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q
ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm
dTdmQRCsu/WU48IxK63nI1bMNSWSs1A=
-----END CERTIFICATE-----
+
+# Issuer: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA
+# Subject: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA
+# Label: "FIRMAPROFESIONAL CA ROOT-A WEB"
+# Serial: 65916896770016886708751106294915943533
+# MD5 Fingerprint: 82:b2:ad:45:00:82:b0:66:63:f8:5f:c3:67:4e:ce:a3
+# SHA1 Fingerprint: a8:31:11:74:a6:14:15:0d:ca:77:dd:0e:e4:0c:5d:58:fc:a0:72:a5
+# SHA256 Fingerprint: be:f2:56:da:f2:6e:9c:69:bd:ec:16:02:35:97:98:f3:ca:f7:18:21:a0:3e:01:82:57:c5:3c:65:61:7f:3d:4a
+-----BEGIN CERTIFICATE-----
+MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw
+CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE
+YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB
+IFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQsw
+CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE
+YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB
+IFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zf
+e9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6C
+cyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0O
+BBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
+PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw
+hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG
+XSaQpYXFuXqUPoeovQA=
+-----END CERTIFICATE-----
diff --git a/lib/cherrypy/__init__.py b/lib/cherrypy/__init__.py
index 8e27c812..49e955f8 100644
--- a/lib/cherrypy/__init__.py
+++ b/lib/cherrypy/__init__.py
@@ -57,9 +57,11 @@ These API's are described in the `CherryPy specification
"""
try:
- import pkg_resources
+ import importlib.metadata as importlib_metadata
except ImportError:
- pass
+ # fall back for python <= 3.7
+ # This try/except can be removed with py <= 3.7 support
+ import importlib_metadata
from threading import local as _local
@@ -109,7 +111,7 @@ tree = _cptree.Tree()
try:
- __version__ = pkg_resources.require('cherrypy')[0].version
+ __version__ = importlib_metadata.version('cherrypy')
except Exception:
__version__ = 'unknown'
@@ -181,24 +183,28 @@ def quickstart(root=None, script_name='', config=None):
class _Serving(_local):
"""An interface for registering request and response objects.
- Rather than have a separate "thread local" object for the request and
- the response, this class works as a single threadlocal container for
- both objects (and any others which developers wish to define). In this
- way, we can easily dump those objects when we stop/start a new HTTP
- conversation, yet still refer to them as module-level globals in a
- thread-safe way.
+ Rather than have a separate "thread local" object for the request
+ and the response, this class works as a single threadlocal container
+ for both objects (and any others which developers wish to define).
+ In this way, we can easily dump those objects when we stop/start a
+ new HTTP conversation, yet still refer to them as module-level
+ globals in a thread-safe way.
"""
request = _cprequest.Request(_httputil.Host('127.0.0.1', 80),
_httputil.Host('127.0.0.1', 1111))
+ """The request object for the current thread.
+
+ In the main thread, and any threads which are not receiving HTTP
+ requests, this is None.
"""
- The request object for the current thread. In the main thread,
- and any threads which are not receiving HTTP requests, this is None."""
response = _cprequest.Response()
+ """The response object for the current thread.
+
+ In the main thread, and any threads which are not receiving HTTP
+ requests, this is None.
"""
- The response object for the current thread. In the main thread,
- and any threads which are not receiving HTTP requests, this is None."""
def load(self, request, response):
self.request = request
@@ -316,8 +322,8 @@ class _GlobalLogManager(_cplogging.LogManager):
def __call__(self, *args, **kwargs):
"""Log the given message to the app.log or global log.
- Log the given message to the app.log or global
- log as appropriate.
+ Log the given message to the app.log or global log as
+ appropriate.
"""
# Do NOT use try/except here. See
# https://github.com/cherrypy/cherrypy/issues/945
@@ -330,8 +336,8 @@ class _GlobalLogManager(_cplogging.LogManager):
def access(self):
"""Log an access message to the app.log or global log.
- Log the given message to the app.log or global
- log as appropriate.
+ Log the given message to the app.log or global log as
+ appropriate.
"""
try:
return request.app.log.access()
diff --git a/lib/cherrypy/_cpchecker.py b/lib/cherrypy/_cpchecker.py
index f26f319c..096b19c3 100644
--- a/lib/cherrypy/_cpchecker.py
+++ b/lib/cherrypy/_cpchecker.py
@@ -313,7 +313,10 @@ class Checker(object):
# -------------------- Specific config warnings -------------------- #
def check_localhost(self):
- """Warn if any socket_host is 'localhost'. See #711."""
+ """Warn if any socket_host is 'localhost'.
+
+ See #711.
+ """
for k, v in cherrypy.config.items():
if k == 'server.socket_host' and v == 'localhost':
warnings.warn("The use of 'localhost' as a socket host can "
diff --git a/lib/cherrypy/_cpconfig.py b/lib/cherrypy/_cpconfig.py
index 8e3fd612..c22937d3 100644
--- a/lib/cherrypy/_cpconfig.py
+++ b/lib/cherrypy/_cpconfig.py
@@ -1,5 +1,4 @@
-"""
-Configuration system for CherryPy.
+"""Configuration system for CherryPy.
Configuration in CherryPy is implemented via dictionaries. Keys are strings
which name the mapped value, which may be of any type.
@@ -132,8 +131,8 @@ def _if_filename_register_autoreload(ob):
def merge(base, other):
"""Merge one app config (from a dict, file, or filename) into another.
- If the given config is a filename, it will be appended to
- the list of files to monitor for "autoreload" changes.
+ If the given config is a filename, it will be appended to the list
+ of files to monitor for "autoreload" changes.
"""
_if_filename_register_autoreload(other)
diff --git a/lib/cherrypy/_cpdispatch.py b/lib/cherrypy/_cpdispatch.py
index 5c506e99..5a3a8ad6 100644
--- a/lib/cherrypy/_cpdispatch.py
+++ b/lib/cherrypy/_cpdispatch.py
@@ -1,9 +1,10 @@
"""CherryPy dispatchers.
A 'dispatcher' is the object which looks up the 'page handler' callable
-and collects config for the current request based on the path_info, other
-request attributes, and the application architecture. The core calls the
-dispatcher as early as possible, passing it a 'path_info' argument.
+and collects config for the current request based on the path_info,
+other request attributes, and the application architecture. The core
+calls the dispatcher as early as possible, passing it a 'path_info'
+argument.
The default dispatcher discovers the page handler by matching path_info
to a hierarchical arrangement of objects, starting at request.app.root.
@@ -21,7 +22,6 @@ import cherrypy
class PageHandler(object):
-
"""Callable which sets response.body."""
def __init__(self, callable, *args, **kwargs):
@@ -64,8 +64,7 @@ class PageHandler(object):
def test_callable_spec(callable, callable_args, callable_kwargs):
- """
- Inspect callable and test to see if the given args are suitable for it.
+ """Inspect callable and test to see if the given args are suitable for it.
When an error occurs during the handler's invoking stage there are 2
erroneous cases:
@@ -252,16 +251,16 @@ else:
class Dispatcher(object):
-
"""CherryPy Dispatcher which walks a tree of objects to find a handler.
- The tree is rooted at cherrypy.request.app.root, and each hierarchical
- component in the path_info argument is matched to a corresponding nested
- attribute of the root object. Matching handlers must have an 'exposed'
- attribute which evaluates to True. The special method name "index"
- matches a URI which ends in a slash ("/"). The special method name
- "default" may match a portion of the path_info (but only when no longer
- substring of the path_info matches some other object).
+ The tree is rooted at cherrypy.request.app.root, and each
+ hierarchical component in the path_info argument is matched to a
+ corresponding nested attribute of the root object. Matching handlers
+ must have an 'exposed' attribute which evaluates to True. The
+ special method name "index" matches a URI which ends in a slash
+ ("/"). The special method name "default" may match a portion of the
+ path_info (but only when no longer substring of the path_info
+ matches some other object).
This is the default, built-in dispatcher for CherryPy.
"""
@@ -306,9 +305,9 @@ class Dispatcher(object):
The second object returned will be a list of names which are
'virtual path' components: parts of the URL which are dynamic,
- and were not used when looking up the handler.
- These virtual path components are passed to the handler as
- positional arguments.
+ and were not used when looking up the handler. These virtual
+ path components are passed to the handler as positional
+ arguments.
"""
request = cherrypy.serving.request
app = request.app
@@ -448,13 +447,11 @@ class Dispatcher(object):
class MethodDispatcher(Dispatcher):
-
"""Additional dispatch based on cherrypy.request.method.upper().
- Methods named GET, POST, etc will be called on an exposed class.
- The method names must be all caps; the appropriate Allow header
- will be output showing all capitalized method names as allowable
- HTTP verbs.
+ Methods named GET, POST, etc will be called on an exposed class. The
+ method names must be all caps; the appropriate Allow header will be
+ output showing all capitalized method names as allowable HTTP verbs.
Note that the containing class must be exposed, not the methods.
"""
@@ -492,16 +489,14 @@ class MethodDispatcher(Dispatcher):
class RoutesDispatcher(object):
-
"""A Routes based dispatcher for CherryPy."""
def __init__(self, full_result=False, **mapper_options):
- """
- Routes dispatcher
+ """Routes dispatcher.
- Set full_result to True if you wish the controller
- and the action to be passed on to the page handler
- parameters. By default they won't be.
+ Set full_result to True if you wish the controller and the
+ action to be passed on to the page handler parameters. By
+ default they won't be.
"""
import routes
self.full_result = full_result
@@ -617,8 +612,7 @@ def XMLRPCDispatcher(next_dispatcher=Dispatcher()):
def VirtualHost(next_dispatcher=Dispatcher(), use_x_forwarded_host=True,
**domains):
- """
- Select a different handler based on the Host header.
+ """Select a different handler based on the Host header.
This can be useful when running multiple sites within one CP server.
It allows several domains to point to different parts of a single
diff --git a/lib/cherrypy/_cperror.py b/lib/cherrypy/_cperror.py
index f6ff2913..203fabf5 100644
--- a/lib/cherrypy/_cperror.py
+++ b/lib/cherrypy/_cperror.py
@@ -136,19 +136,17 @@ from cherrypy.lib import httputil as _httputil
class CherryPyException(Exception):
-
"""A base class for CherryPy exceptions."""
pass
class InternalRedirect(CherryPyException):
-
"""Exception raised to switch to the handler for a different URL.
- This exception will redirect processing to another path within the site
- (without informing the client). Provide the new path as an argument when
- raising the exception. Provide any params in the querystring for the new
- URL.
+ This exception will redirect processing to another path within the
+ site (without informing the client). Provide the new path as an
+ argument when raising the exception. Provide any params in the
+ querystring for the new URL.
"""
def __init__(self, path, query_string=''):
@@ -173,7 +171,6 @@ class InternalRedirect(CherryPyException):
class HTTPRedirect(CherryPyException):
-
"""Exception raised when the request should be redirected.
This exception will force a HTTP redirect to the URL or URL's you give it.
@@ -202,7 +199,7 @@ class HTTPRedirect(CherryPyException):
"""The list of URL's to emit."""
encoding = 'utf-8'
- """The encoding when passed urls are not native strings"""
+ """The encoding when passed urls are not native strings."""
def __init__(self, urls, status=None, encoding=None):
self.urls = abs_urls = [
@@ -230,8 +227,7 @@ class HTTPRedirect(CherryPyException):
@classproperty
def default_status(cls):
- """
- The default redirect status for the request.
+ """The default redirect status for the request.
RFC 2616 indicates a 301 response code fits our goal; however,
browser support for 301 is quite messy. Use 302/303 instead. See
@@ -249,8 +245,9 @@ class HTTPRedirect(CherryPyException):
"""Modify cherrypy.response status, headers, and body to represent
self.
- CherryPy uses this internally, but you can also use it to create an
- HTTPRedirect object and set its output without *raising* the exception.
+ CherryPy uses this internally, but you can also use it to create
+ an HTTPRedirect object and set its output without *raising* the
+ exception.
"""
response = cherrypy.serving.response
response.status = status = self.status
@@ -339,7 +336,6 @@ def clean_headers(status):
class HTTPError(CherryPyException):
-
"""Exception used to return an HTTP error code (4xx-5xx) to the client.
This exception can be used to automatically send a response using a
@@ -358,7 +354,9 @@ class HTTPError(CherryPyException):
"""
status = None
- """The HTTP status code. May be of type int or str (with a Reason-Phrase).
+ """The HTTP status code.
+
+ May be of type int or str (with a Reason-Phrase).
"""
code = None
@@ -386,8 +384,9 @@ class HTTPError(CherryPyException):
"""Modify cherrypy.response status, headers, and body to represent
self.
- CherryPy uses this internally, but you can also use it to create an
- HTTPError object and set its output without *raising* the exception.
+ CherryPy uses this internally, but you can also use it to create
+ an HTTPError object and set its output without *raising* the
+ exception.
"""
response = cherrypy.serving.response
@@ -426,11 +425,10 @@ class HTTPError(CherryPyException):
class NotFound(HTTPError):
-
"""Exception raised when a URL could not be mapped to any handler (404).
- This is equivalent to raising
- :class:`HTTPError("404 Not Found") `.
+ This is equivalent to raising :class:`HTTPError("404 Not Found")
+ `.
"""
def __init__(self, path=None):
@@ -477,8 +475,8 @@ _HTTPErrorTemplate = ''' cherrypy.server -> HTTPServer.
+ cheroot has been designed to not reference CherryPy in any way, so
+ that it can be used in other frameworks and applications. Therefore,
+ we wrap it here, so we can apply some attributes from config ->
+ cherrypy.server -> HTTPServer.
"""
def __init__(self, server_adapter=cherrypy.server):
diff --git a/lib/cherrypy/_cpreqbody.py b/lib/cherrypy/_cpreqbody.py
index 4d3cefe7..7e0d98be 100644
--- a/lib/cherrypy/_cpreqbody.py
+++ b/lib/cherrypy/_cpreqbody.py
@@ -248,7 +248,10 @@ def process_multipart_form_data(entity):
def _old_process_multipart(entity):
- """The behavior of 3.2 and lower. Deprecated and will be changed in 3.3."""
+ """The behavior of 3.2 and lower.
+
+ Deprecated and will be changed in 3.3.
+ """
process_multipart(entity)
params = entity.params
@@ -277,7 +280,6 @@ def _old_process_multipart(entity):
# -------------------------------- Entities --------------------------------- #
class Entity(object):
-
"""An HTTP request body, or MIME multipart body.
This class collects information about the HTTP request entity. When a
@@ -346,13 +348,15 @@ class Entity(object):
content_type = None
"""The value of the Content-Type request header.
- If the Entity is part of a multipart payload, this will be the Content-Type
- given in the MIME headers for this part.
+ If the Entity is part of a multipart payload, this will be the
+ Content-Type given in the MIME headers for this part.
"""
default_content_type = 'application/x-www-form-urlencoded'
"""This defines a default ``Content-Type`` to use if no Content-Type header
- is given. The empty string is used for RequestBody, which results in the
+ is given.
+
+ The empty string is used for RequestBody, which results in the
request body not being read or parsed at all. This is by design; a missing
``Content-Type`` header in the HTTP request entity is an error at best,
and a security hole at worst. For multipart parts, however, the MIME spec
@@ -402,8 +406,8 @@ class Entity(object):
part_class = None
"""The class used for multipart parts.
- You can replace this with custom subclasses to alter the processing of
- multipart parts.
+ You can replace this with custom subclasses to alter the processing
+ of multipart parts.
"""
def __init__(self, fp, headers, params=None, parts=None):
@@ -509,7 +513,8 @@ class Entity(object):
"""Return a file-like object into which the request body will be read.
By default, this will return a TemporaryFile. Override as needed.
- See also :attr:`cherrypy._cpreqbody.Part.maxrambytes`."""
+ See also :attr:`cherrypy._cpreqbody.Part.maxrambytes`.
+ """
return tempfile.TemporaryFile()
def fullvalue(self):
@@ -525,7 +530,7 @@ class Entity(object):
return value
def decode_entity(self, value):
- """Return a given byte encoded value as a string"""
+ """Return a given byte encoded value as a string."""
for charset in self.attempt_charsets:
try:
value = value.decode(charset)
@@ -569,7 +574,6 @@ class Entity(object):
class Part(Entity):
-
"""A MIME part entity, part of a multipart entity."""
# "The default character set, which must be assumed in the absence of a
@@ -653,8 +657,8 @@ class Part(Entity):
def read_lines_to_boundary(self, fp_out=None):
"""Read bytes from self.fp and return or write them to a file.
- If the 'fp_out' argument is None (the default), all bytes read are
- returned in a single byte string.
+ If the 'fp_out' argument is None (the default), all bytes read
+ are returned in a single byte string.
If the 'fp_out' argument is not None, it must be a file-like
object that supports the 'write' method; all bytes read will be
@@ -755,15 +759,15 @@ class SizedReader:
def read(self, size=None, fp_out=None):
"""Read bytes from the request body and return or write them to a file.
- A number of bytes less than or equal to the 'size' argument are read
- off the socket. The actual number of bytes read are tracked in
- self.bytes_read. The number may be smaller than 'size' when 1) the
- client sends fewer bytes, 2) the 'Content-Length' request header
- specifies fewer bytes than requested, or 3) the number of bytes read
- exceeds self.maxbytes (in which case, 413 is raised).
+ A number of bytes less than or equal to the 'size' argument are
+ read off the socket. The actual number of bytes read are tracked
+ in self.bytes_read. The number may be smaller than 'size' when
+ 1) the client sends fewer bytes, 2) the 'Content-Length' request
+ header specifies fewer bytes than requested, or 3) the number of
+ bytes read exceeds self.maxbytes (in which case, 413 is raised).
- If the 'fp_out' argument is None (the default), all bytes read are
- returned in a single byte string.
+ If the 'fp_out' argument is None (the default), all bytes read
+ are returned in a single byte string.
If the 'fp_out' argument is not None, it must be a file-like
object that supports the 'write' method; all bytes read will be
@@ -918,7 +922,6 @@ class SizedReader:
class RequestBody(Entity):
-
"""The entity of the HTTP request."""
bufsize = 8 * 1024
diff --git a/lib/cherrypy/_cprequest.py b/lib/cherrypy/_cprequest.py
index a661112c..a4ad298b 100644
--- a/lib/cherrypy/_cprequest.py
+++ b/lib/cherrypy/_cprequest.py
@@ -16,7 +16,6 @@ from cherrypy.lib import httputil, reprconf, encoding
class Hook(object):
-
"""A callback and its metadata: failsafe, priority, and kwargs."""
callback = None
@@ -30,10 +29,12 @@ class Hook(object):
from the same call point raise exceptions."""
priority = 50
+ """Defines the order of execution for a list of Hooks.
+
+ Priority numbers should be limited to the closed interval [0, 100],
+ but values outside this range are acceptable, as are fractional
+ values.
"""
- Defines the order of execution for a list of Hooks. Priority numbers
- should be limited to the closed interval [0, 100], but values outside
- this range are acceptable, as are fractional values."""
kwargs = {}
"""
@@ -74,7 +75,6 @@ class Hook(object):
class HookMap(dict):
-
"""A map of call points to lists of callbacks (Hook objects)."""
def __new__(cls, points=None):
@@ -190,23 +190,23 @@ hookpoints = ['on_start_resource', 'before_request_body',
class Request(object):
-
"""An HTTP request.
- This object represents the metadata of an HTTP request message;
- that is, it contains attributes which describe the environment
- in which the request URL, headers, and body were sent (if you
- want tools to interpret the headers and body, those are elsewhere,
- mostly in Tools). This 'metadata' consists of socket data,
- transport characteristics, and the Request-Line. This object
- also contains data regarding the configuration in effect for
- the given URL, and the execution plan for generating a response.
+ This object represents the metadata of an HTTP request message; that
+ is, it contains attributes which describe the environment in which
+ the request URL, headers, and body were sent (if you want tools to
+ interpret the headers and body, those are elsewhere, mostly in
+ Tools). This 'metadata' consists of socket data, transport
+ characteristics, and the Request-Line. This object also contains
+ data regarding the configuration in effect for the given URL, and
+ the execution plan for generating a response.
"""
prev = None
+ """The previous Request object (if any).
+
+ This should be None unless we are processing an InternalRedirect.
"""
- The previous Request object (if any). This should be None
- unless we are processing an InternalRedirect."""
# Conversation/connection attributes
local = httputil.Host('127.0.0.1', 80)
@@ -216,9 +216,10 @@ class Request(object):
'An httputil.Host(ip, port, hostname) object for the client socket.'
scheme = 'http'
+ """The protocol used between client and server.
+
+ In most cases, this will be either 'http' or 'https'.
"""
- The protocol used between client and server. In most cases,
- this will be either 'http' or 'https'."""
server_protocol = 'HTTP/1.1'
"""
@@ -227,25 +228,30 @@ class Request(object):
base = ''
"""The (scheme://host) portion of the requested URL.
+
In some cases (e.g. when proxying via mod_rewrite), this may contain
path segments which cherrypy.url uses when constructing url's, but
- which otherwise are ignored by CherryPy. Regardless, this value
- MUST NOT end in a slash."""
+ which otherwise are ignored by CherryPy. Regardless, this value MUST
+ NOT end in a slash.
+ """
# Request-Line attributes
request_line = ''
+ """The complete Request-Line received from the client.
+
+ This is a single string consisting of the request method, URI, and
+ protocol version (joined by spaces). Any final CRLF is removed.
"""
- The complete Request-Line received from the client. This is a
- single string consisting of the request method, URI, and protocol
- version (joined by spaces). Any final CRLF is removed."""
method = 'GET'
+ """Indicates the HTTP method to be performed on the resource identified by
+ the Request-URI.
+
+ Common methods include GET, HEAD, POST, PUT, and DELETE. CherryPy
+ allows any extension method; however, various HTTP servers and
+ gateways may restrict the set of allowable methods. CherryPy
+ applications SHOULD restrict the set (on a per-URI basis).
"""
- Indicates the HTTP method to be performed on the resource identified
- by the Request-URI. Common methods include GET, HEAD, POST, PUT, and
- DELETE. CherryPy allows any extension method; however, various HTTP
- servers and gateways may restrict the set of allowable methods.
- CherryPy applications SHOULD restrict the set (on a per-URI basis)."""
query_string = ''
"""
@@ -277,22 +283,26 @@ class Request(object):
A dict which combines query string (GET) and request entity (POST)
variables. This is populated in two stages: GET params are added
before the 'on_start_resource' hook, and POST params are added
- between the 'before_request_body' and 'before_handler' hooks."""
+ between the 'before_request_body' and 'before_handler' hooks.
+ """
# Message attributes
header_list = []
+ """A list of the HTTP request headers as (name, value) tuples.
+
+ In general, you should use request.headers (a dict) instead.
"""
- A list of the HTTP request headers as (name, value) tuples.
- In general, you should use request.headers (a dict) instead."""
headers = httputil.HeaderMap()
- """
- A dict-like object containing the request headers. Keys are header
+ """A dict-like object containing the request headers.
+
+ Keys are header
names (in Title-Case format); however, you may get and set them in
a case-insensitive manner. That is, headers['Content-Type'] and
headers['content-type'] refer to the same value. Values are header
values (decoded according to :rfc:`2047` if necessary). See also:
- httputil.HeaderMap, httputil.HeaderElement."""
+ httputil.HeaderMap, httputil.HeaderElement.
+ """
cookie = SimpleCookie()
"""See help(Cookie)."""
@@ -336,7 +346,8 @@ class Request(object):
or multipart, this will be None. Otherwise, this will be an instance
of :class:`RequestBody` (which you
can .read()); this value is set between the 'before_request_body' and
- 'before_handler' hooks (assuming that process_request_body is True)."""
+ 'before_handler' hooks (assuming that process_request_body is True).
+ """
# Dispatch attributes
dispatch = cherrypy.dispatch.Dispatcher()
@@ -347,23 +358,24 @@ class Request(object):
calls the dispatcher as early as possible, passing it a 'path_info'
argument.
- The default dispatcher discovers the page handler by matching path_info
- to a hierarchical arrangement of objects, starting at request.app.root.
- See help(cherrypy.dispatch) for more information."""
+ The default dispatcher discovers the page handler by matching
+ path_info to a hierarchical arrangement of objects, starting at
+ request.app.root. See help(cherrypy.dispatch) for more information.
+ """
script_name = ''
- """
- The 'mount point' of the application which is handling this request.
+ """The 'mount point' of the application which is handling this request.
This attribute MUST NOT end in a slash. If the script_name refers to
the root of the URI, it MUST be an empty string (not "/").
"""
path_info = '/'
+ """The 'relative path' portion of the Request-URI.
+
+ This is relative to the script_name ('mount point') of the
+ application which is handling this request.
"""
- The 'relative path' portion of the Request-URI. This is relative
- to the script_name ('mount point') of the application which is
- handling this request."""
login = None
"""
@@ -391,14 +403,16 @@ class Request(object):
of the form: {Toolbox.namespace: {Tool.name: config dict}}."""
config = None
+ """A flat dict of all configuration entries which apply to the current
+ request.
+
+ These entries are collected from global config, application config
+ (based on request.path_info), and from handler config (exactly how
+ is governed by the request.dispatch object in effect for this
+ request; by default, handler config can be attached anywhere in the
+ tree between request.app.root and the final handler, and inherits
+ downward).
"""
- A flat dict of all configuration entries which apply to the
- current request. These entries are collected from global config,
- application config (based on request.path_info), and from handler
- config (exactly how is governed by the request.dispatch object in
- effect for this request; by default, handler config can be attached
- anywhere in the tree between request.app.root and the final handler,
- and inherits downward)."""
is_index = None
"""
@@ -409,13 +423,14 @@ class Request(object):
the trailing slash. See cherrypy.tools.trailing_slash."""
hooks = HookMap(hookpoints)
- """
- A HookMap (dict-like object) of the form: {hookpoint: [hook, ...]}.
+ """A HookMap (dict-like object) of the form: {hookpoint: [hook, ...]}.
+
Each key is a str naming the hook point, and each value is a list
of hooks which will be called at that hook point during this request.
The list of hooks is generally populated as early as possible (mostly
from Tools specified in config), but may be extended at any time.
- See also: _cprequest.Hook, _cprequest.HookMap, and cherrypy.tools."""
+ See also: _cprequest.Hook, _cprequest.HookMap, and cherrypy.tools.
+ """
error_response = cherrypy.HTTPError(500).set_response
"""
@@ -428,12 +443,11 @@ class Request(object):
error response to the user-agent."""
error_page = {}
- """
- A dict of {error code: response filename or callable} pairs.
+ """A dict of {error code: response filename or callable} pairs.
The error code must be an int representing a given HTTP error code,
- or the string 'default', which will be used if no matching entry
- is found for a given numeric code.
+ or the string 'default', which will be used if no matching entry is
+ found for a given numeric code.
If a filename is provided, the file should contain a Python string-
formatting template, and can expect by default to receive format
@@ -447,8 +461,8 @@ class Request(object):
iterable of strings which will be set to response.body. It may also
override headers or perform any other processing.
- If no entry is given for an error code, and no 'default' entry exists,
- a default template will be used.
+ If no entry is given for an error code, and no 'default' entry
+ exists, a default template will be used.
"""
show_tracebacks = True
@@ -473,9 +487,10 @@ class Request(object):
"""True once the close method has been called, False otherwise."""
stage = None
+ """A string containing the stage reached in the request-handling process.
+
+ This is useful when debugging a live server with hung requests.
"""
- A string containing the stage reached in the request-handling process.
- This is useful when debugging a live server with hung requests."""
unique_id = None
"""A lazy object generating and memorizing UUID4 on ``str()`` render."""
@@ -492,9 +507,10 @@ class Request(object):
server_protocol='HTTP/1.1'):
"""Populate a new Request object.
- local_host should be an httputil.Host object with the server info.
- remote_host should be an httputil.Host object with the client info.
- scheme should be a string, either "http" or "https".
+ local_host should be an httputil.Host object with the server
+ info. remote_host should be an httputil.Host object with the
+ client info. scheme should be a string, either "http" or
+ "https".
"""
self.local = local_host
self.remote = remote_host
@@ -514,7 +530,10 @@ class Request(object):
self.unique_id = LazyUUID4()
def close(self):
- """Run cleanup code. (Core)"""
+ """Run cleanup code.
+
+ (Core)
+ """
if not self.closed:
self.closed = True
self.stage = 'on_end_request'
@@ -551,7 +570,6 @@ class Request(object):
Consumer code (HTTP servers) should then access these response
attributes to build the outbound stream.
-
"""
response = cherrypy.serving.response
self.stage = 'run'
@@ -631,7 +649,10 @@ class Request(object):
return response
def respond(self, path_info):
- """Generate a response for the resource at self.path_info. (Core)"""
+ """Generate a response for the resource at self.path_info.
+
+ (Core)
+ """
try:
try:
try:
@@ -702,7 +723,10 @@ class Request(object):
response.finalize()
def process_query_string(self):
- """Parse the query string into Python structures. (Core)"""
+ """Parse the query string into Python structures.
+
+ (Core)
+ """
try:
p = httputil.parse_query_string(
self.query_string, encoding=self.query_string_encoding)
@@ -715,7 +739,10 @@ class Request(object):
self.params.update(p)
def process_headers(self):
- """Parse HTTP header data into Python structures. (Core)"""
+ """Parse HTTP header data into Python structures.
+
+ (Core)
+ """
# Process the headers into self.headers
headers = self.headers
for name, value in self.header_list:
@@ -751,7 +778,10 @@ class Request(object):
self.base = '%s://%s' % (self.scheme, host)
def get_resource(self, path):
- """Call a dispatcher (which sets self.handler and .config). (Core)"""
+ """Call a dispatcher (which sets self.handler and .config).
+
+ (Core)
+ """
# First, see if there is a custom dispatch at this URI. Custom
# dispatchers can only be specified in app.config, not in _cp_config
# (since custom dispatchers may not even have an app.root).
@@ -762,7 +792,10 @@ class Request(object):
dispatch(path)
def handle_error(self):
- """Handle the last unanticipated exception. (Core)"""
+ """Handle the last unanticipated exception.
+
+ (Core)
+ """
try:
self.hooks.run('before_error_response')
if self.error_response:
@@ -776,7 +809,6 @@ class Request(object):
class ResponseBody(object):
-
"""The body of the HTTP response (the response entity)."""
unicode_err = ('Page handlers MUST return bytes. Use tools.encode '
@@ -802,18 +834,18 @@ class ResponseBody(object):
class Response(object):
-
"""An HTTP Response, including status, headers, and body."""
status = ''
"""The HTTP Status-Code and Reason-Phrase."""
header_list = []
- """
- A list of the HTTP response headers as (name, value) tuples.
+ """A list of the HTTP response headers as (name, value) tuples.
+
In general, you should use response.headers (a dict) instead. This
attribute is generated from response.headers and is not valid until
- after the finalize phase."""
+ after the finalize phase.
+ """
headers = httputil.HeaderMap()
"""
@@ -833,7 +865,10 @@ class Response(object):
"""The body (entity) of the HTTP response."""
time = None
- """The value of time.time() when created. Use in HTTP dates."""
+ """The value of time.time() when created.
+
+ Use in HTTP dates.
+ """
stream = False
"""If False, buffer the response body."""
@@ -861,15 +896,15 @@ class Response(object):
return new_body
def _flush_body(self):
- """
- Discard self.body but consume any generator such that
- any finalization can occur, such as is required by
- caching.tee_output().
- """
+ """Discard self.body but consume any generator such that any
+ finalization can occur, such as is required by caching.tee_output()."""
consume(iter(self.body))
def finalize(self):
- """Transform headers (and cookies) into self.header_list. (Core)"""
+ """Transform headers (and cookies) into self.header_list.
+
+ (Core)
+ """
try:
code, reason, _ = httputil.valid_status(self.status)
except ValueError:
diff --git a/lib/cherrypy/_cpserver.py b/lib/cherrypy/_cpserver.py
index 5f8d98fa..62331673 100644
--- a/lib/cherrypy/_cpserver.py
+++ b/lib/cherrypy/_cpserver.py
@@ -50,7 +50,8 @@ class Server(ServerAdapter):
"""If given, the name of the UNIX socket to use instead of TCP/IP.
When this option is not None, the `socket_host` and `socket_port` options
- are ignored."""
+ are ignored.
+ """
socket_queue_size = 5
"""The 'backlog' argument to socket.listen(); specifies the maximum number
@@ -79,17 +80,24 @@ class Server(ServerAdapter):
"""The number of worker threads to start up in the pool."""
thread_pool_max = -1
- """The maximum size of the worker-thread pool. Use -1 to indicate no limit.
+ """The maximum size of the worker-thread pool.
+
+ Use -1 to indicate no limit.
"""
max_request_header_size = 500 * 1024
"""The maximum number of bytes allowable in the request headers.
- If exceeded, the HTTP server should return "413 Request Entity Too Large".
+
+ If exceeded, the HTTP server should return "413 Request Entity Too
+ Large".
"""
max_request_body_size = 100 * 1024 * 1024
- """The maximum number of bytes allowable in the request body. If exceeded,
- the HTTP server should return "413 Request Entity Too Large"."""
+ """The maximum number of bytes allowable in the request body.
+
+ If exceeded, the HTTP server should return "413 Request Entity Too
+ Large".
+ """
instance = None
"""If not None, this should be an HTTP server instance (such as
@@ -119,7 +127,8 @@ class Server(ServerAdapter):
the builtin WSGI server. Builtin options are: 'builtin' (to
use the SSL library built into recent versions of Python).
You may also register your own classes in the
- cheroot.server.ssl_adapters dict."""
+ cheroot.server.ssl_adapters dict.
+ """
statistics = False
"""Turns statistics-gathering on or off for aware HTTP servers."""
@@ -129,11 +138,13 @@ class Server(ServerAdapter):
wsgi_version = (1, 0)
"""The WSGI version tuple to use with the builtin WSGI server.
- The provided options are (1, 0) [which includes support for PEP 3333,
- which declares it covers WSGI version 1.0.1 but still mandates the
- wsgi.version (1, 0)] and ('u', 0), an experimental unicode version.
- You may create and register your own experimental versions of the WSGI
- protocol by adding custom classes to the cheroot.server.wsgi_gateways dict.
+
+ The provided options are (1, 0) [which includes support for PEP
+ 3333, which declares it covers WSGI version 1.0.1 but still mandates
+ the wsgi.version (1, 0)] and ('u', 0), an experimental unicode
+ version. You may create and register your own experimental versions
+ of the WSGI protocol by adding custom classes to the
+ cheroot.server.wsgi_gateways dict.
"""
peercreds = False
@@ -184,7 +195,8 @@ class Server(ServerAdapter):
def bind_addr(self):
"""Return bind address.
- A (host, port) tuple for TCP sockets or a str for Unix domain sockts.
+ A (host, port) tuple for TCP sockets or a str for Unix domain
+ sockets.
"""
if self.socket_file:
return self.socket_file
diff --git a/lib/cherrypy/_cptools.py b/lib/cherrypy/_cptools.py
index 716f99a4..e47c046e 100644
--- a/lib/cherrypy/_cptools.py
+++ b/lib/cherrypy/_cptools.py
@@ -1,7 +1,7 @@
"""CherryPy tools. A "tool" is any helper, adapted to CP.
-Tools are usually designed to be used in a variety of ways (although some
-may only offer one if they choose):
+Tools are usually designed to be used in a variety of ways (although
+some may only offer one if they choose):
Library calls
All tools are callables that can be used wherever needed.
@@ -48,10 +48,10 @@ _attr_error = (
class Tool(object):
-
"""A registered function for use with CherryPy request-processing hooks.
- help(tool.callable) should give you more information about this Tool.
+ help(tool.callable) should give you more information about this
+ Tool.
"""
namespace = 'tools'
@@ -135,8 +135,8 @@ class Tool(object):
def _setup(self):
"""Hook this tool into cherrypy.request.
- The standard CherryPy request object will automatically call this
- method when the tool is "turned on" in config.
+ The standard CherryPy request object will automatically call
+ this method when the tool is "turned on" in config.
"""
conf = self._merged_args()
p = conf.pop('priority', None)
@@ -147,15 +147,15 @@ class Tool(object):
class HandlerTool(Tool):
-
"""Tool which is called 'before main', that may skip normal handlers.
- If the tool successfully handles the request (by setting response.body),
- if should return True. This will cause CherryPy to skip any 'normal' page
- handler. If the tool did not handle the request, it should return False
- to tell CherryPy to continue on and call the normal page handler. If the
- tool is declared AS a page handler (see the 'handler' method), returning
- False will raise NotFound.
+ If the tool successfully handles the request (by setting
+ response.body), if should return True. This will cause CherryPy to
+ skip any 'normal' page handler. If the tool did not handle the
+ request, it should return False to tell CherryPy to continue on and
+ call the normal page handler. If the tool is declared AS a page
+ handler (see the 'handler' method), returning False will raise
+ NotFound.
"""
def __init__(self, callable, name=None):
@@ -185,8 +185,8 @@ class HandlerTool(Tool):
def _setup(self):
"""Hook this tool into cherrypy.request.
- The standard CherryPy request object will automatically call this
- method when the tool is "turned on" in config.
+ The standard CherryPy request object will automatically call
+ this method when the tool is "turned on" in config.
"""
conf = self._merged_args()
p = conf.pop('priority', None)
@@ -197,7 +197,6 @@ class HandlerTool(Tool):
class HandlerWrapperTool(Tool):
-
"""Tool which wraps request.handler in a provided wrapper function.
The 'newhandler' arg must be a handler wrapper function that takes a
@@ -232,7 +231,6 @@ class HandlerWrapperTool(Tool):
class ErrorTool(Tool):
-
"""Tool which is used to replace the default request.error_response."""
def __init__(self, callable, name=None):
@@ -244,8 +242,8 @@ class ErrorTool(Tool):
def _setup(self):
"""Hook this tool into cherrypy.request.
- The standard CherryPy request object will automatically call this
- method when the tool is "turned on" in config.
+ The standard CherryPy request object will automatically call
+ this method when the tool is "turned on" in config.
"""
cherrypy.serving.request.error_response = self._wrapper
@@ -254,7 +252,6 @@ class ErrorTool(Tool):
class SessionTool(Tool):
-
"""Session Tool for CherryPy.
sessions.locking
@@ -282,8 +279,8 @@ class SessionTool(Tool):
def _setup(self):
"""Hook this tool into cherrypy.request.
- The standard CherryPy request object will automatically call this
- method when the tool is "turned on" in config.
+ The standard CherryPy request object will automatically call
+ this method when the tool is "turned on" in config.
"""
hooks = cherrypy.serving.request.hooks
@@ -325,7 +322,6 @@ class SessionTool(Tool):
class XMLRPCController(object):
-
"""A Controller (page handler collection) for XML-RPC.
To use it, have your controllers subclass this base class (it will
@@ -392,7 +388,6 @@ class SessionAuthTool(HandlerTool):
class CachingTool(Tool):
-
"""Caching Tool for CherryPy."""
def _wrapper(self, **kwargs):
@@ -416,11 +411,11 @@ class CachingTool(Tool):
class Toolbox(object):
-
"""A collection of Tools.
This object also functions as a config namespace handler for itself.
- Custom toolboxes should be added to each Application's toolboxes dict.
+ Custom toolboxes should be added to each Application's toolboxes
+ dict.
"""
def __init__(self, namespace):
diff --git a/lib/cherrypy/_cptree.py b/lib/cherrypy/_cptree.py
index 917c5b1a..3dea1c29 100644
--- a/lib/cherrypy/_cptree.py
+++ b/lib/cherrypy/_cptree.py
@@ -10,19 +10,22 @@ from cherrypy.lib import httputil, reprconf
class Application(object):
"""A CherryPy Application.
- Servers and gateways should not instantiate Request objects directly.
- Instead, they should ask an Application object for a request object.
+ Servers and gateways should not instantiate Request objects
+ directly. Instead, they should ask an Application object for a
+ request object.
- An instance of this class may also be used as a WSGI callable
- (WSGI application object) for itself.
+ An instance of this class may also be used as a WSGI callable (WSGI
+ application object) for itself.
"""
root = None
- """The top-most container of page handlers for this app. Handlers should
- be arranged in a hierarchy of attributes, matching the expected URI
- hierarchy; the default dispatcher then searches this hierarchy for a
- matching handler. When using a dispatcher other than the default,
- this value may be None."""
+ """The top-most container of page handlers for this app.
+
+ Handlers should be arranged in a hierarchy of attributes, matching
+ the expected URI hierarchy; the default dispatcher then searches
+ this hierarchy for a matching handler. When using a dispatcher other
+ than the default, this value may be None.
+ """
config = {}
"""A dict of {path: pathconf} pairs, where 'pathconf' is itself a dict
@@ -32,10 +35,16 @@ class Application(object):
toolboxes = {'tools': cherrypy.tools}
log = None
- """A LogManager instance. See _cplogging."""
+ """A LogManager instance.
+
+ See _cplogging.
+ """
wsgiapp = None
- """A CPWSGIApp instance. See _cpwsgi."""
+ """A CPWSGIApp instance.
+
+ See _cpwsgi.
+ """
request_class = _cprequest.Request
response_class = _cprequest.Response
@@ -82,12 +91,15 @@ class Application(object):
def script_name(self): # noqa: D401; irrelevant for properties
"""The URI "mount point" for this app.
- A mount point is that portion of the URI which is constant for all URIs
- that are serviced by this application; it does not include scheme,
- host, or proxy ("virtual host") portions of the URI.
+ A mount point is that portion of the URI which is constant for
+ all URIs that are serviced by this application; it does not
+ include scheme, host, or proxy ("virtual host") portions of the
+ URI.
- For example, if script_name is "/my/cool/app", then the URL
- "http://www.example.com/my/cool/app/page1" might be handled by a
+ For example, if script_name is "/my/cool/app", then the URL "
+
+ http://www.example.com/my/cool/app/page1"
+ might be handled by a
"page1" method on the root object.
The value of script_name MUST NOT end in a slash. If the script_name
@@ -171,9 +183,9 @@ class Application(object):
class Tree(object):
"""A registry of CherryPy applications, mounted at diverse points.
- An instance of this class may also be used as a WSGI callable
- (WSGI application object), in which case it dispatches to all
- mounted apps.
+ An instance of this class may also be used as a WSGI callable (WSGI
+ application object), in which case it dispatches to all mounted
+ apps.
"""
apps = {}
diff --git a/lib/cherrypy/_cpwsgi.py b/lib/cherrypy/_cpwsgi.py
index b4f55fd6..b2a6da52 100644
--- a/lib/cherrypy/_cpwsgi.py
+++ b/lib/cherrypy/_cpwsgi.py
@@ -1,10 +1,10 @@
"""WSGI interface (see PEP 333 and 3333).
Note that WSGI environ keys and values are 'native strings'; that is,
-whatever the type of "" is. For Python 2, that's a byte string; for Python 3,
-it's a unicode string. But PEP 3333 says: "even if Python's str type is
-actually Unicode "under the hood", the content of native strings must
-still be translatable to bytes via the Latin-1 encoding!"
+whatever the type of "" is. For Python 2, that's a byte string; for
+Python 3, it's a unicode string. But PEP 3333 says: "even if Python's
+str type is actually Unicode "under the hood", the content of native
+strings must still be translatable to bytes via the Latin-1 encoding!"
"""
import sys as _sys
@@ -34,7 +34,6 @@ def downgrade_wsgi_ux_to_1x(environ):
class VirtualHost(object):
-
"""Select a different WSGI application based on the Host header.
This can be useful when running multiple sites within one CP server.
@@ -56,7 +55,10 @@ class VirtualHost(object):
cherrypy.tree.graft(vhost)
"""
default = None
- """Required. The default WSGI application."""
+ """Required.
+
+ The default WSGI application.
+ """
use_x_forwarded_host = True
"""If True (the default), any "X-Forwarded-Host"
@@ -65,11 +67,12 @@ class VirtualHost(object):
domains = {}
"""A dict of {host header value: application} pairs.
- The incoming "Host" request header is looked up in this dict,
- and, if a match is found, the corresponding WSGI application
- will be called instead of the default. Note that you often need
- separate entries for "example.com" and "www.example.com".
- In addition, "Host" headers may contain the port number.
+
+ The incoming "Host" request header is looked up in this dict, and,
+ if a match is found, the corresponding WSGI application will be
+ called instead of the default. Note that you often need separate
+ entries for "example.com" and "www.example.com". In addition, "Host"
+ headers may contain the port number.
"""
def __init__(self, default, domains=None, use_x_forwarded_host=True):
@@ -89,7 +92,6 @@ class VirtualHost(object):
class InternalRedirector(object):
-
"""WSGI middleware that handles raised cherrypy.InternalRedirect."""
def __init__(self, nextapp, recursive=False):
@@ -137,7 +139,6 @@ class InternalRedirector(object):
class ExceptionTrapper(object):
-
"""WSGI middleware that traps exceptions."""
def __init__(self, nextapp, throws=(KeyboardInterrupt, SystemExit)):
@@ -226,7 +227,6 @@ class _TrappedResponse(object):
class AppResponse(object):
-
"""WSGI response iterable for CherryPy applications."""
def __init__(self, environ, start_response, cpapp):
@@ -277,7 +277,10 @@ class AppResponse(object):
return next(self.iter_response)
def close(self):
- """Close and de-reference the current request and response. (Core)"""
+ """Close and de-reference the current request and response.
+
+ (Core)
+ """
streaming = _cherrypy.serving.response.stream
self.cpapp.release_serving()
@@ -380,18 +383,20 @@ class AppResponse(object):
class CPWSGIApp(object):
-
"""A WSGI application object for a CherryPy Application."""
pipeline = [
('ExceptionTrapper', ExceptionTrapper),
('InternalRedirector', InternalRedirector),
]
- """A list of (name, wsgiapp) pairs. Each 'wsgiapp' MUST be a
- constructor that takes an initial, positional 'nextapp' argument,
- plus optional keyword arguments, and returns a WSGI application
- (that takes environ and start_response arguments). The 'name' can
- be any you choose, and will correspond to keys in self.config."""
+ """A list of (name, wsgiapp) pairs.
+
+ Each 'wsgiapp' MUST be a constructor that takes an initial,
+ positional 'nextapp' argument, plus optional keyword arguments, and
+ returns a WSGI application (that takes environ and start_response
+ arguments). The 'name' can be any you choose, and will correspond to
+ keys in self.config.
+ """
head = None
"""Rather than nest all apps in the pipeline on each call, it's only
@@ -399,9 +404,12 @@ class CPWSGIApp(object):
this to None again if you change self.pipeline after calling self."""
config = {}
- """A dict whose keys match names listed in the pipeline. Each
- value is a further dict which will be passed to the corresponding
- named WSGI callable (from the pipeline) as keyword arguments."""
+ """A dict whose keys match names listed in the pipeline.
+
+ Each value is a further dict which will be passed to the
+ corresponding named WSGI callable (from the pipeline) as keyword
+ arguments.
+ """
response_class = AppResponse
"""The class to instantiate and return as the next app in the WSGI chain.
@@ -417,8 +425,8 @@ class CPWSGIApp(object):
def tail(self, environ, start_response):
"""WSGI application callable for the actual CherryPy application.
- You probably shouldn't call this; call self.__call__ instead,
- so that any WSGI middleware in self.pipeline can run first.
+ You probably shouldn't call this; call self.__call__ instead, so
+ that any WSGI middleware in self.pipeline can run first.
"""
return self.response_class(environ, start_response, self.cpapp)
diff --git a/lib/cherrypy/_cpwsgi_server.py b/lib/cherrypy/_cpwsgi_server.py
index 11dd846a..b8e96deb 100644
--- a/lib/cherrypy/_cpwsgi_server.py
+++ b/lib/cherrypy/_cpwsgi_server.py
@@ -1,7 +1,7 @@
-"""
-WSGI server interface (see PEP 333).
+"""WSGI server interface (see PEP 333).
-This adds some CP-specific bits to the framework-agnostic cheroot package.
+This adds some CP-specific bits to the framework-agnostic cheroot
+package.
"""
import sys
@@ -35,10 +35,11 @@ class CPWSGIHTTPRequest(cheroot.server.HTTPRequest):
class CPWSGIServer(cheroot.wsgi.Server):
"""Wrapper for cheroot.wsgi.Server.
- cheroot has been designed to not reference CherryPy in any way,
- so that it can be used in other frameworks and applications. Therefore,
- we wrap it here, so we can set our own mount points from cherrypy.tree
- and apply some attributes from config -> cherrypy.server -> wsgi.Server.
+ cheroot has been designed to not reference CherryPy in any way, so
+ that it can be used in other frameworks and applications. Therefore,
+ we wrap it here, so we can set our own mount points from
+ cherrypy.tree and apply some attributes from config ->
+ cherrypy.server -> wsgi.Server.
"""
fmt = 'CherryPy/{cherrypy.__version__} {cheroot.wsgi.Server.version}'
diff --git a/lib/cherrypy/_helper.py b/lib/cherrypy/_helper.py
index d57cd1f9..497438eb 100644
--- a/lib/cherrypy/_helper.py
+++ b/lib/cherrypy/_helper.py
@@ -137,7 +137,6 @@ def popargs(*args, **kwargs):
class Root:
def index(self):
#...
-
"""
# Since keyword arg comes after *args, we have to process it ourselves
# for lower versions of python.
@@ -201,16 +200,17 @@ def url(path='', qs='', script_name=None, base=None, relative=None):
If it does not start with a slash, this returns
(base + script_name [+ request.path_info] + path + qs).
- If script_name is None, cherrypy.request will be used
- to find a script_name, if available.
+ If script_name is None, cherrypy.request will be used to find a
+ script_name, if available.
If base is None, cherrypy.request.base will be used (if available).
Note that you can use cherrypy.tools.proxy to change this.
- Finally, note that this function can be used to obtain an absolute URL
- for the current request path (minus the querystring) by passing no args.
- If you call url(qs=cherrypy.request.query_string), you should get the
- original browser URL (assuming no internal redirections).
+ Finally, note that this function can be used to obtain an absolute
+ URL for the current request path (minus the querystring) by passing
+ no args. If you call url(qs=cherrypy.request.query_string), you
+ should get the original browser URL (assuming no internal
+ redirections).
If relative is None or not provided, request.app.relative_urls will
be used (if available, else False). If False, the output will be an
@@ -320,8 +320,8 @@ def normalize_path(path):
class _ClassPropertyDescriptor(object):
"""Descript for read-only class-based property.
- Turns a classmethod-decorated func into a read-only property of that class
- type (means the value cannot be set).
+ Turns a classmethod-decorated func into a read-only property of that
+ class type (means the value cannot be set).
"""
def __init__(self, fget, fset=None):
diff --git a/lib/cherrypy/_json.py b/lib/cherrypy/_json.py
index 0c2a0f0e..4ef85580 100644
--- a/lib/cherrypy/_json.py
+++ b/lib/cherrypy/_json.py
@@ -1,5 +1,4 @@
-"""
-JSON support.
+"""JSON support.
Expose preferred json module as json and provide encode/decode
convenience functions.
diff --git a/lib/cherrypy/lib/__init__.py b/lib/cherrypy/lib/__init__.py
index 0edaaf20..9788ffdf 100644
--- a/lib/cherrypy/lib/__init__.py
+++ b/lib/cherrypy/lib/__init__.py
@@ -6,8 +6,8 @@ def is_iterator(obj):
(i.e. like a generator).
- This will return False for objects which are iterable,
- but not iterators themselves.
+ This will return False for objects which are iterable, but not
+ iterators themselves.
"""
from types import GeneratorType
if isinstance(obj, GeneratorType):
diff --git a/lib/cherrypy/lib/auth_basic.py b/lib/cherrypy/lib/auth_basic.py
index ad379a26..b938a560 100644
--- a/lib/cherrypy/lib/auth_basic.py
+++ b/lib/cherrypy/lib/auth_basic.py
@@ -18,7 +18,6 @@ as the credentials store::
'tools.auth_basic.accept_charset': 'UTF-8',
}
app_config = { '/' : basic_auth }
-
"""
import binascii
diff --git a/lib/cherrypy/lib/auth_digest.py b/lib/cherrypy/lib/auth_digest.py
index 981e9a5d..46749268 100644
--- a/lib/cherrypy/lib/auth_digest.py
+++ b/lib/cherrypy/lib/auth_digest.py
@@ -55,7 +55,7 @@ def TRACE(msg):
def get_ha1_dict_plain(user_password_dict):
- """Returns a get_ha1 function which obtains a plaintext password from a
+ """Return a get_ha1 function which obtains a plaintext password from a
dictionary of the form: {username : password}.
If you want a simple dictionary-based authentication scheme, with plaintext
@@ -72,7 +72,7 @@ def get_ha1_dict_plain(user_password_dict):
def get_ha1_dict(user_ha1_dict):
- """Returns a get_ha1 function which obtains a HA1 password hash from a
+ """Return a get_ha1 function which obtains a HA1 password hash from a
dictionary of the form: {username : HA1}.
If you want a dictionary-based authentication scheme, but with
@@ -87,7 +87,7 @@ def get_ha1_dict(user_ha1_dict):
def get_ha1_file_htdigest(filename):
- """Returns a get_ha1 function which obtains a HA1 password hash from a
+ """Return a get_ha1 function which obtains a HA1 password hash from a
flat file with lines of the same format as that produced by the Apache
htdigest utility. For example, for realm 'wonderland', username 'alice',
and password '4x5istwelve', the htdigest line would be::
@@ -135,7 +135,7 @@ def synthesize_nonce(s, key, timestamp=None):
def H(s):
- """The hash function H"""
+ """The hash function H."""
return md5_hex(s)
@@ -259,10 +259,11 @@ class HttpDigestAuthorization(object):
return False
def is_nonce_stale(self, max_age_seconds=600):
- """Returns True if a validated nonce is stale. The nonce contains a
- timestamp in plaintext and also a secure hash of the timestamp.
- You should first validate the nonce to ensure the plaintext
- timestamp is not spoofed.
+ """Return True if a validated nonce is stale.
+
+ The nonce contains a timestamp in plaintext and also a secure
+ hash of the timestamp. You should first validate the nonce to
+ ensure the plaintext timestamp is not spoofed.
"""
try:
timestamp, hashpart = self.nonce.split(':', 1)
@@ -275,7 +276,10 @@ class HttpDigestAuthorization(object):
return True
def HA2(self, entity_body=''):
- """Returns the H(A2) string. See :rfc:`2617` section 3.2.2.3."""
+ """Return the H(A2) string.
+
+ See :rfc:`2617` section 3.2.2.3.
+ """
# RFC 2617 3.2.2.3
# If the "qop" directive's value is "auth" or is unspecified,
# then A2 is:
@@ -306,7 +310,6 @@ class HttpDigestAuthorization(object):
4.3. This refers to the entity the user agent sent in the
request which has the Authorization header. Typically GET
requests don't have an entity, and POST requests do.
-
"""
ha2 = self.HA2(entity_body)
# Request-Digest -- RFC 2617 3.2.2.1
@@ -395,7 +398,6 @@ def digest_auth(realm, get_ha1, key, debug=False, accept_charset='utf-8'):
key
A secret string known only to the server, used in the synthesis
of nonces.
-
"""
request = cherrypy.serving.request
@@ -447,9 +449,7 @@ def digest_auth(realm, get_ha1, key, debug=False, accept_charset='utf-8'):
def _respond_401(realm, key, accept_charset, debug, **kwargs):
- """
- Respond with 401 status and a WWW-Authenticate header
- """
+ """Respond with 401 status and a WWW-Authenticate header."""
header = www_authenticate(
realm, key,
accept_charset=accept_charset,
diff --git a/lib/cherrypy/lib/caching.py b/lib/cherrypy/lib/caching.py
index 08d2d8e4..89cb0442 100644
--- a/lib/cherrypy/lib/caching.py
+++ b/lib/cherrypy/lib/caching.py
@@ -42,7 +42,6 @@ from cherrypy.lib import cptools, httputil
class Cache(object):
-
"""Base class for Cache implementations."""
def get(self):
@@ -64,17 +63,16 @@ class Cache(object):
# ------------------------------ Memory Cache ------------------------------- #
class AntiStampedeCache(dict):
-
"""A storage system for cached items which reduces stampede collisions."""
def wait(self, key, timeout=5, debug=False):
"""Return the cached value for the given key, or None.
- If timeout is not None, and the value is already
- being calculated by another thread, wait until the given timeout has
- elapsed. If the value is available before the timeout expires, it is
- returned. If not, None is returned, and a sentinel placed in the cache
- to signal other threads to wait.
+ If timeout is not None, and the value is already being
+ calculated by another thread, wait until the given timeout has
+ elapsed. If the value is available before the timeout expires,
+ it is returned. If not, None is returned, and a sentinel placed
+ in the cache to signal other threads to wait.
If timeout is None, no waiting is performed nor sentinels used.
"""
@@ -127,7 +125,6 @@ class AntiStampedeCache(dict):
class MemoryCache(Cache):
-
"""An in-memory cache for varying response content.
Each key in self.store is a URI, and each value is an AntiStampedeCache.
@@ -381,7 +378,10 @@ def get(invalid_methods=('POST', 'PUT', 'DELETE'), debug=False, **kwargs):
def tee_output():
- """Tee response output to cache storage. Internal."""
+ """Tee response output to cache storage.
+
+ Internal.
+ """
# Used by CachingTool by attaching to request.hooks
request = cherrypy.serving.request
@@ -441,7 +441,6 @@ def expires(secs=0, force=False, debug=False):
* Expires
If any are already present, none of the above response headers are set.
-
"""
response = cherrypy.serving.response
diff --git a/lib/cherrypy/lib/covercp.py b/lib/cherrypy/lib/covercp.py
index 6c3871fc..f22cce74 100644
--- a/lib/cherrypy/lib/covercp.py
+++ b/lib/cherrypy/lib/covercp.py
@@ -22,7 +22,7 @@ it will call ``serve()`` for you.
import re
import sys
-import cgi
+import html
import os
import os.path
import urllib.parse
@@ -352,9 +352,9 @@ class CoverStats(object):
buffer.append((lineno, line))
if empty_the_buffer:
for lno, pastline in buffer:
- yield template % (lno, cgi.escape(pastline))
+ yield template % (lno, html.escape(pastline))
buffer = []
- yield template % (lineno, cgi.escape(line))
+ yield template % (lineno, html.escape(line))
@cherrypy.expose
def report(self, name):
diff --git a/lib/cherrypy/lib/cpstats.py b/lib/cherrypy/lib/cpstats.py
index 111af063..5dff319b 100644
--- a/lib/cherrypy/lib/cpstats.py
+++ b/lib/cherrypy/lib/cpstats.py
@@ -184,7 +184,6 @@ To report statistics::
To format statistics reports::
See 'Reporting', above.
-
"""
import logging
@@ -254,7 +253,6 @@ def proc_time(s):
class ByteCountWrapper(object):
-
"""Wraps a file-like object, counting the number of bytes read."""
def __init__(self, rfile):
@@ -307,7 +305,6 @@ def _get_threading_ident():
class StatsTool(cherrypy.Tool):
-
"""Record various information about the current request."""
def __init__(self):
@@ -316,8 +313,8 @@ class StatsTool(cherrypy.Tool):
def _setup(self):
"""Hook this tool into cherrypy.request.
- The standard CherryPy request object will automatically call this
- method when the tool is "turned on" in config.
+ The standard CherryPy request object will automatically call
+ this method when the tool is "turned on" in config.
"""
if appstats.get('Enabled', False):
cherrypy.Tool._setup(self)
diff --git a/lib/cherrypy/lib/cptools.py b/lib/cherrypy/lib/cptools.py
index 13b4c567..61d4d36b 100644
--- a/lib/cherrypy/lib/cptools.py
+++ b/lib/cherrypy/lib/cptools.py
@@ -94,8 +94,8 @@ def validate_etags(autotags=False, debug=False):
def validate_since():
"""Validate the current Last-Modified against If-Modified-Since headers.
- If no code has set the Last-Modified response header, then no validation
- will be performed.
+ If no code has set the Last-Modified response header, then no
+ validation will be performed.
"""
response = cherrypy.serving.response
lastmod = response.headers.get('Last-Modified')
@@ -123,9 +123,9 @@ def validate_since():
def allow(methods=None, debug=False):
"""Raise 405 if request.method not in methods (default ['GET', 'HEAD']).
- The given methods are case-insensitive, and may be in any order.
- If only one method is allowed, you may supply a single string;
- if more than one, supply a list of strings.
+ The given methods are case-insensitive, and may be in any order. If
+ only one method is allowed, you may supply a single string; if more
+ than one, supply a list of strings.
Regardless of whether the current method is allowed or not, this
also emits an 'Allow' response header, containing the given methods.
@@ -154,22 +154,23 @@ def proxy(base=None, local='X-Forwarded-Host', remote='X-Forwarded-For',
scheme='X-Forwarded-Proto', debug=False):
"""Change the base URL (scheme://host[:port][/path]).
- For running a CP server behind Apache, lighttpd, or other HTTP server.
+ For running a CP server behind Apache, lighttpd, or other HTTP
+ server.
- For Apache and lighttpd, you should leave the 'local' argument at the
- default value of 'X-Forwarded-Host'. For Squid, you probably want to set
- tools.proxy.local = 'Origin'.
+ For Apache and lighttpd, you should leave the 'local' argument at
+ the default value of 'X-Forwarded-Host'. For Squid, you probably
+ want to set tools.proxy.local = 'Origin'.
- If you want the new request.base to include path info (not just the host),
- you must explicitly set base to the full base path, and ALSO set 'local'
- to '', so that the X-Forwarded-Host request header (which never includes
- path info) does not override it. Regardless, the value for 'base' MUST
- NOT end in a slash.
+ If you want the new request.base to include path info (not just the
+ host), you must explicitly set base to the full base path, and ALSO
+ set 'local' to '', so that the X-Forwarded-Host request header
+ (which never includes path info) does not override it. Regardless,
+ the value for 'base' MUST NOT end in a slash.
cherrypy.request.remote.ip (the IP address of the client) will be
- rewritten if the header specified by the 'remote' arg is valid.
- By default, 'remote' is set to 'X-Forwarded-For'. If you do not
- want to rewrite remote.ip, set the 'remote' arg to an empty string.
+ rewritten if the header specified by the 'remote' arg is valid. By
+ default, 'remote' is set to 'X-Forwarded-For'. If you do not want to
+ rewrite remote.ip, set the 'remote' arg to an empty string.
"""
request = cherrypy.serving.request
@@ -217,8 +218,8 @@ def proxy(base=None, local='X-Forwarded-Host', remote='X-Forwarded-For',
def ignore_headers(headers=('Range',), debug=False):
"""Delete request headers whose field names are included in 'headers'.
- This is a useful tool for working behind certain HTTP servers;
- for example, Apache duplicates the work that CP does for 'Range'
+ This is a useful tool for working behind certain HTTP servers; for
+ example, Apache duplicates the work that CP does for 'Range'
headers, and will doubly-truncate the response.
"""
request = cherrypy.serving.request
@@ -281,7 +282,6 @@ def referer(pattern, accept=True, accept_missing=False, error=403,
class SessionAuth(object):
-
"""Assert that the user is logged in."""
session_key = 'username'
@@ -319,7 +319,10 @@ Message: %(error_msg)s