| 1 |
|
|---|
| 2 |
class Root: |
|---|
| 3 |
pass |
|---|
| 4 |
|
|---|
| 5 |
class Branch: |
|---|
| 6 |
pass |
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
class Tree: |
|---|
| 10 |
"""A scaffold for cherrypy.root. |
|---|
| 11 |
|
|---|
| 12 |
This class works together with cherrypy.root, providing helper methods |
|---|
| 13 |
for mounting applications at diverse points. "Trellis" would be a more |
|---|
| 14 |
accurate name (but too hard to remember, and perhaps in CP 3.0 this |
|---|
| 15 |
class will become cherrypy.root). |
|---|
| 16 |
""" |
|---|
| 17 |
|
|---|
| 18 |
def __init__(self): |
|---|
| 19 |
self._mount_points = {} |
|---|
| 20 |
|
|---|
| 21 |
def _get_mount_points(self): |
|---|
| 22 |
m = self._mount_points |
|---|
| 23 |
if "/" not in m: |
|---|
| 24 |
import cherrypy |
|---|
| 25 |
if cherrypy.root is not None and not isinstance(cherrypy.root, Root): |
|---|
| 26 |
m["/"] = cherrypy.root |
|---|
| 27 |
return m |
|---|
| 28 |
def _set_mount_points(self, newvalue): |
|---|
| 29 |
self._mount_points = newvalue |
|---|
| 30 |
mount_points = property(_get_mount_points, _set_mount_points) |
|---|
| 31 |
|
|---|
| 32 |
def mount(self, app_root, baseurl=None, conf=None): |
|---|
| 33 |
"""Mount the given app_root at the given baseurl (relative to root).""" |
|---|
| 34 |
import cherrypy |
|---|
| 35 |
|
|---|
| 36 |
if conf and not isinstance(conf, dict): |
|---|
| 37 |
conf = cherrypy.config.dict_from_config_file(conf) |
|---|
| 38 |
|
|---|
| 39 |
if baseurl is None: |
|---|
| 40 |
baseurl = "/" |
|---|
| 41 |
if conf: |
|---|
| 42 |
conf_pt = conf.get("global", {}).get("mount_point") |
|---|
| 43 |
if conf_pt: |
|---|
| 44 |
baseurl = conf_pt |
|---|
| 45 |
|
|---|
| 46 |
point = baseurl.lstrip("/") |
|---|
| 47 |
if point: |
|---|
| 48 |
node = cherrypy.root |
|---|
| 49 |
if node is None: |
|---|
| 50 |
node = cherrypy.root = Root() |
|---|
| 51 |
atoms = point.split("/") |
|---|
| 52 |
tail = atoms.pop() |
|---|
| 53 |
for atom in atoms: |
|---|
| 54 |
if not hasattr(node, atom): |
|---|
| 55 |
setattr(node, atom, Branch()) |
|---|
| 56 |
node = getattr(node, atom) |
|---|
| 57 |
if hasattr(node, tail): |
|---|
| 58 |
raise ValueError("The url '%s' is already mounted." % baseurl) |
|---|
| 59 |
else: |
|---|
| 60 |
|
|---|
| 61 |
if cherrypy.root is not None: |
|---|
| 62 |
raise ValueError("The url '%s' is already mounted." % baseurl) |
|---|
| 63 |
node = cherrypy |
|---|
| 64 |
tail = "root" |
|---|
| 65 |
|
|---|
| 66 |
setattr(node, tail, app_root) |
|---|
| 67 |
self.mount_points[baseurl] = app_root |
|---|
| 68 |
|
|---|
| 69 |
if conf is not None: |
|---|
| 70 |
cherrypy.config.update(updateMap=conf, baseurl=baseurl) |
|---|
| 71 |
|
|---|
| 72 |
def mount_point(self, path=None): |
|---|
| 73 |
"""The 'root path' of the app which governs the given path, or None. |
|---|
| 74 |
|
|---|
| 75 |
If path is None, cherrypy.request.object_path is used. |
|---|
| 76 |
""" |
|---|
| 77 |
|
|---|
| 78 |
if path is None: |
|---|
| 79 |
try: |
|---|
| 80 |
import cherrypy |
|---|
| 81 |
path = cherrypy.request.object_path |
|---|
| 82 |
except AttributeError: |
|---|
| 83 |
return None |
|---|
| 84 |
|
|---|
| 85 |
while path: |
|---|
| 86 |
if path in self.mount_points: |
|---|
| 87 |
return path |
|---|
| 88 |
|
|---|
| 89 |
|
|---|
| 90 |
if path == "/": |
|---|
| 91 |
break |
|---|
| 92 |
path = path[:path.rfind("/")] or "/" |
|---|
| 93 |
|
|---|
| 94 |
return None |
|---|
| 95 |
|
|---|
| 96 |
def url(self, path, mount_point=None): |
|---|
| 97 |
"""Return 'path', prefixed with mount_point. |
|---|
| 98 |
|
|---|
| 99 |
If mount_point is None, cherrypy.request.object_path will be used |
|---|
| 100 |
to find a mount point. |
|---|
| 101 |
""" |
|---|
| 102 |
|
|---|
| 103 |
if mount_point is None: |
|---|
| 104 |
mount_point = self.mount_point() |
|---|
| 105 |
if mount_point is None: |
|---|
| 106 |
return path |
|---|
| 107 |
|
|---|
| 108 |
from cherrypy.lib import httptools |
|---|
| 109 |
return httptools.urljoin(mount_point, path) |
|---|
| 110 |
|
|---|