This is an example of adding an about page that provides info about how the system is configured. All of these changes are done in the tracker home directory. You might not have a lib subdirectory. If you don't, just make the directory with the same owner, group, and permissions as the other directories like html or extensions.
Add an html template.
In html/home.about.html put:
1 <tal:block metal:use-macro="templates/page/macros/icing">
2
3 <title metal:fill-slot="head_title" i18n:translate="" >
4 About this Tracker
5 </title>
6 <tal:block metal:fill-slot="body_title" i18n:translate="">
7 About this Tracker
8 </tal:block>
9
10 <div class="content" metal:fill-slot="content">
11
12 <span tal:condition="not:python:request.user.hasRole('Admin')"
13 tal:omit-tag="python:1" i18n:translate="">
14 Please login with your username and password to find out about
15 this tracker.
16 </span>
17
18 <div tal:condition="python:request.user.hasRole('Admin')"
19 tal:omit-tag="python:1" i18n:translate="">
20
21 <div tal:replace="structure python:utils.AboutPage(db)"></div>
22
23 </div>
24 </div>
25
26 </tal:block>
in lib/tracker_version.py you can put:
this is optional as a missing tracker_version.py is ignored. But it may be useful to set as part of a deployment script of you use version control.
Put the following in extensions/about.py:
1 try:
2 import tracker_version
3 t_version = tracker_version.__version__
4 except ImportError:
5 t_version = "Not set"
6
7 import sys
8 from roundup import __version__ as roundup_version
9
10 def AboutPage(db):
11 "report useful info about this tracker"
12
13 def is_module_loaded(module):
14 modules = list(sys.modules.keys())
15 return module in modules
16
17 def get_status_of_module(module, prefix=None, version=True):
18 modules = list(sys.modules.keys())
19 is_enabled = module in modules
20 if is_enabled:
21 if module == 'MySQLdb':
22 from MySQLdb import version_info
23 version="version %s"%".".join([str(v) for v in version_info])
24 elif module == 'pychart':
25 from pychart import version
26 version="version %s"%version.version
27 elif module == 'pyme':
28 from pyme import version
29 version="version %s"%version.versionstr
30 elif module == 'sqlite3':
31 from sqlite3 import version
32 version="version %s"%version
33 elif module == "whoosh":
34 from whoosh import versionstring
35 version="version %s"%versionstring()
36 elif module == 'xapian':
37 from xapian import version_string
38 version="version %s"%version_string()
39 else:
40 if version:
41 m = __import__(module)
42 try:
43 version="version %s"%m.__version__
44 except AttributeError:
45 version="version unavailable - exception thrown"
46 else:
47 version="version unavailable"
48
49 if prefix:
50 return "%s %s %s enabled: %s"%(prefix, module, version, is_enabled)
51 else:
52 return "Module: %s %s enabled: %s"%(module, version, is_enabled)
53 else:
54 if prefix:
55 return "%s %s enabled: %s"%(prefix, module, is_enabled)
56 else:
57 return "Module: %s enabled: %s"%(module, is_enabled)
58
59 info = []
60
61 info.append("Tracker name: %s<br>"%db.config['TRACKER_NAME'])
62 info.append("Tracker base version: %s"%t_version)
63
64 info.append("<h2>Operating environment</h2>")
65 info.append('<a href="http://roundup.sourceforge.net/">Roundup</a> version: %s<br>'%roundup_version)
66 info.append("Python Version: %s<br>"%sys.version)
67
68 info.append("<h2>Configuration</h2>")
69
70 backend = db.config['RDBMS_BACKEND']
71 info.append("Roundup backend: %s<br>"%backend)
72 if backend != 'anydbm':
73 info.append("Roundup db cache: %s<br>"%db.config['RDBMS_CACHE_SIZE'])
74 info.append("Roundup isolation_level: %s<br>"%db.config['RDBMS_ISOLATION_LEVEL'])
75
76 info.append("Roundup template: %s<br>"%db.config['TEMPLATE_ENGINE'])
77
78 info.append("<h2>Database modules</h2>")
79 info.append(get_status_of_module('anydbm', version=False) + "<br>")
80 info.append(get_status_of_module('dbm', version=False) + "<br>")
81 info.append(get_status_of_module('sqlite3') + "<br>")
82 info.append(get_status_of_module('MySQLdb') + "<br>")
83 info.append(get_status_of_module('psycopg2') + "<br>")
84
85 info.append("<h2>Other modules</h2>")
86
87 indexer = db.config['INDEXER']
88 if not indexer:
89 if is_module_loaded('xapian'):
90 indexer="unset using xapian"
91 elif is_module_loaded('whoosh'):
92 indexer="unset using woosh"
93 else:
94 indexer="unset using native"
95 else:
96 indexer="set to " + indexer
97
98 info.append("Indexer used for full-text: %s<br>"%indexer)
99
100 info.append("Available indexers:<br><ul>")
101 if is_module_loaded('xapian'):
102 info.append("<li>%s</li>"%get_status_of_module('xapian', prefix="Indexer loaded:"))
103 if is_module_loaded('whoosh'):
104 info.append("<li>%s</li>"%get_status_of_module('whoosh', prefix="Indexer loaded:"))
105 info.append("<li>Indexer loaded: native: True</li>")
106 info.append("</ul>")
107 info.append(get_status_of_module('pytz') + "<br>")
108 info.append(get_status_of_module('pyme') + "<br>")
109 info.append(get_status_of_module('OpenSSL') + "<br>")
110 info.append(get_status_of_module('pychart') + "<br>")
111 info.append(get_status_of_module('pygal') + "<br>")
112
113 info.append(get_status_of_module('jinja2') + "<br>")
114
115 uid = db._db.getuid()
116 if uid == "1" or \
117 db._db.security.hasPermission("SeeAboutPrivDetails", uid) or \
118 db._db.user.has_role(uid,"Admin"):
119 info.append("<h2>Python Environment</h2>")
120 #may leak sensitive info about system, directory paths etc.
121 #so require more that just SeeAbout privs.
122 info.append("")
123 info.append("sys.path: %r"%sys.path)
124
125 info.append("<h2>Environment Variables</h2>")
126 info.append("<pre>") # include pre to prevent wrapping of values
127 for key in list(db._client.env.keys()):
128 info.append("%s=%s"%(key,db._client.env[key]) + "<br>")
129 info.append("</pre>")
130
131 info.append("<h2>Runtime state</h2>")
132 info.append("<pre>js enabled on client: %s</pre>" % \
133 str('jsdisabled' not in db._client.cookie))
134 info.append('')
135 for key in db._client.cookie:
136 info.append("<pre>Cookie: %s = %s</pre>" % (key,
137 db._client.cookie[key].value))
138 return "\n".join(info)
139
140 def init(instance):
141 instance.registerUtil('AboutPage', AboutPage)
To view the page go to the url: http://host/tracker/?@template=about I.E. append "?@template=about" to the base url of your tracker.
The page looks something like:
Hopefully I got all the important bits as I extracted this from my tracker.