1 | """ |
---|
2 | Trac macros for Twisted. |
---|
3 | """ |
---|
4 | |
---|
5 | from StringIO import StringIO |
---|
6 | from urlparse import urlparse |
---|
7 | |
---|
8 | from trac.core import TracError |
---|
9 | from trac.util.html import Markup |
---|
10 | from trac.wiki.formatter import OneLinerFormatter |
---|
11 | from trac.wiki.macros import WikiMacroBase |
---|
12 | |
---|
13 | from twisted.python.versions import Version |
---|
14 | from twisted.python.filepath import FilePath |
---|
15 | |
---|
16 | |
---|
17 | RELEASES = FilePath('/srv/www-data/twisted/Releases/') |
---|
18 | |
---|
19 | |
---|
20 | |
---|
21 | class ProjectVersionMacro(WikiMacroBase): |
---|
22 | """ |
---|
23 | Macro that knows the current [http://twistedmatrix.com Twisted] version number. |
---|
24 | |
---|
25 | The version information is loaded from a folder containing text files with |
---|
26 | md5sums for each released package/installer. Also see the |
---|
27 | [http://twistedmatrix.com/trac/wiki/Downloads#SignedMD5Sums Twisted downloads] |
---|
28 | page. |
---|
29 | |
---|
30 | '''Standalone''' |
---|
31 | {{{ |
---|
32 | [[ProjectVersion]] |
---|
33 | }}} |
---|
34 | |
---|
35 | produces: |
---|
36 | |
---|
37 | [[ProjectVersion]] |
---|
38 | |
---|
39 | '''URL''' |
---|
40 | |
---|
41 | {{{ |
---|
42 | [[ProjectVersion(http://twistedmatrix.com/Releases/Twisted/%(major)s.%(minor)s/Twisted-%(base)s.win32-py2.7.msi Twisted %(base)s for Python 2.7)]] |
---|
43 | }}} |
---|
44 | |
---|
45 | produces: |
---|
46 | |
---|
47 | [[ProjectVersion(http://twistedmatrix.com/Releases/Twisted/%(major)s.%(minor)s/Twisted-%(base)s.win32-py2.7.msi Twisted %(base)s for Python 2.7)]] |
---|
48 | |
---|
49 | Including the MD5 hash (eg. `b568b504524fda2440c62aa1616b3fe5`): |
---|
50 | |
---|
51 | {{{ |
---|
52 | - [[ProjectVersion(http://pypi.python.org/packages/source/T/Twisted/Twisted-%(base)s.tar.bz2#md5=%(md5)s Twisted %(base)s tar)]] |
---|
53 | - [[ProjectVersion(http://pypi.python.org/packages/2.7/T/Twisted/Twisted-%(base)s.win32-py2.7.msi#md5=%(md5)s Twisted %(base)s for Python 2.7)]] |
---|
54 | }}} |
---|
55 | |
---|
56 | produces: |
---|
57 | |
---|
58 | - [[ProjectVersion(http://pypi.python.org/packages/source/T/Twisted/Twisted-%(base)s.tar.bz2#md5=%(md5)s Twisted %(base)s tar)]] |
---|
59 | - [[ProjectVersion(http://pypi.python.org/packages/2.7/T/Twisted/Twisted-%(base)s.win32-py2.7.msi#md5=%(md5)s Twisted %(base)s for Python 2.7)]] |
---|
60 | |
---|
61 | '''Source browser''' |
---|
62 | |
---|
63 | {{{ |
---|
64 | [[ProjectVersion(source:/tags/releases/twisted-%(base)s/ Tag for Twisted %(base)s)]] |
---|
65 | }}} |
---|
66 | |
---|
67 | produces: |
---|
68 | |
---|
69 | [[ProjectVersion(source:/tags/releases/twisted-%(base)s/ Tag for Twisted %(base)s)]] |
---|
70 | """ |
---|
71 | |
---|
72 | |
---|
73 | revision = "$Rev$" |
---|
74 | url = "$URL$" |
---|
75 | |
---|
76 | def getVersion(self): |
---|
77 | versions = [] |
---|
78 | pattern = 'twisted-%s-md5sums.txt' |
---|
79 | for md5sums in RELEASES.globChildren(pattern % '*'): |
---|
80 | try: |
---|
81 | components = map(int, md5sums.basename().split('-')[1].split('.')) |
---|
82 | except ValueError: |
---|
83 | pass |
---|
84 | else: |
---|
85 | versions.append(components) |
---|
86 | |
---|
87 | version = Version('Twisted', *max(versions)) |
---|
88 | md5sums_file = RELEASES.child(pattern % version.base()) |
---|
89 | return version, md5sums_file |
---|
90 | |
---|
91 | |
---|
92 | def expand_macro(self, formatter, name, args): |
---|
93 | """ |
---|
94 | Return output that will be displayed in the Wiki content. |
---|
95 | |
---|
96 | @param name: the actual name of the macro |
---|
97 | @param args: the text enclosed in parenthesis at the call of the macro. |
---|
98 | Note that if there are ''no'' parenthesis (like in, e.g. |
---|
99 | [[ProjectVersion]]), then `args` is `None`. |
---|
100 | """ |
---|
101 | if not RELEASES.exists(): |
---|
102 | self.log.error("The specified RELEASES directory does not exist at %s" % RELEASES.path) |
---|
103 | raise TracError("Error loading Twisted version information") |
---|
104 | |
---|
105 | v, md5sums = self.getVersion() |
---|
106 | md5sum = '' |
---|
107 | |
---|
108 | if args is None: |
---|
109 | text = v.base() |
---|
110 | else: |
---|
111 | uc = unicode(args).replace('%28', '(').replace('%29', ')') |
---|
112 | if uc.find('%(md5)s') > -1: |
---|
113 | sep = '-----BEGIN PGP SIGNATURE-----\n' |
---|
114 | lines = md5sums.open().readlines() |
---|
115 | path = urlparse(uc).path % dict(base=v.base()) |
---|
116 | filename = path.split('/')[-1] |
---|
117 | for entry in lines[3:lines.index(sep)]: |
---|
118 | entry = entry.rstrip('\n').split(' ') |
---|
119 | if entry[1] == filename: |
---|
120 | md5sum = entry[0] |
---|
121 | break |
---|
122 | |
---|
123 | url = urlparse(uc).netloc |
---|
124 | text = uc % dict(major=v.major, minor=v.minor, micro=v.micro, base=v.base(), |
---|
125 | md5=md5sum) |
---|
126 | |
---|
127 | # handle links |
---|
128 | if args.startswith('source:') or url != '': |
---|
129 | text = "[%s]" % text |
---|
130 | |
---|
131 | out = StringIO() |
---|
132 | OneLinerFormatter(self.env, formatter.context).format(text, out) |
---|
133 | |
---|
134 | return Markup(out.getvalue()) |
---|