summaryrefslogtreecommitdiff
path: root/admin/test_release.py
blob: d62e18b0e1d48177500c77eee967936ca1f990a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
"""helper script that tries to build & test passlib for various python versions.

note that this script is very Linux-specific,
and in fact contains various hardcoded assumptions
that are only true for the systems used by passlib's developers.

it also calls "rm -rf" a lot, so be wary :)
"""
#=========================================================================
# imports
#=========================================================================
import re
import sys
import os.path
import subprocess

#=========================================================================
# helpers
#=========================================================================
def absjoin(*args):
    return os.path.abspath(os.path.join(*args))

def discard_paths(*paths, **kwds):
    cmd = [ "rm", "-rf" ]
    if kwds.get("sudo"):
        cmd.insert(0, "sudo")
    paths = filter(os.path.exists, paths)
    if paths:
        subprocess.check_call(cmd + list(paths))

#=========================================================================
# main
#=========================================================================
class PlatformTestApp(object):
    "command line program that runs passlib's unittest suite for all python versions"

    #=========================================================================
    # class attrs
    #=========================================================================
    # names of vms to test
    vm_names = [
        # normal python versions
        "2.5",
        "2.6",
        "2.7",
        "3.1",
        "3.2",

        # other vms
        "y2.7-1.5",  # pypy 1.5
        "y2.7-1.6",  # pypy 1.6
        "j2.5", # jython 2.5
        "gae",
        ]

    #=========================================================================
    # instance attrs
    #=========================================================================
    root_dir = None # root dir of source
    version = None #current version string
    sdist_dir = None # unpacked sdist dir

    #=========================================================================
    # init
    #=========================================================================
    def __init__(self, args):
        self.args = args

    #=========================================================================
    # run
    #=========================================================================
    def run(self):
        # change dir root dir
        self.root_dir = absjoin(__file__, os.pardir, os.pardir)
        os.chdir(self.root_dir)

        # get version
        self.version = subprocess.check_output(
            ["python", "setup.py","--version"]).strip()

        # purge build & dist
        discard_paths(
            absjoin(self.root_dir, "dist"),
            absjoin(self.root_dir, "build"),
            )

        # create new source dist, extract it, and work from that
        subprocess.check_call(["python", "setup.py", "sdist"])
        os.chdir(absjoin(self.root_dir, "dist"))
        subprocess.check_call(["tar", "zxvf", "passlib-" + self.version + ".tar.gz"])
        self.sdist_dir = absjoin(self.root_dir, "dist", "passlib-" + self.version)

        # run test for each of the vms
        for name in self.vm_names:
            self.run_vm_test(name)

        return 0

    def run_vm_test(self, name):
        # cd to sdist dir, purge everything
        os.chdir(self.sdist_dir)
        discard_paths(
            absjoin(self.sdist_dir, "dist"),
            absjoin(self.sdist_dir, "build"),
            )
        self.uninstall_passlib(name)

        # if gae, run unittests directly in source
        if name == "gae":
            self.run_gae_test()
        else:
            self.run_vm_test_egg(name)
            if not self.parse_vm(name)[0]:
                self.uninstall_passlib(name)
                self.run_vm_test_pip(name)

        self.uninstall_passlib(name)

    def run_gae_test(self):
        # cd to preconfigured gae app
        gae_dir = absjoin(self.root_dir, os.pardir, "gae")
        os.chdir(gae_dir)

        # cleanup and init symlink for passlib
        target_dir = absjoin(gae_dir, "passlib")
        discard_paths(target_dir)
        os.symlink(absjoin(self.sdist_dir, "passlib"), target_dir)

        # run nose w/ gae integration
        subprocess.check_call([
            self.get_vm_exe("gae", "nosetests"),
            "--with-gae",
            "--exe", # later versions set exe bit on test_xxx.py files
            "--tests", "passlib/tests",
        ])

    def run_vm_test_pip(self, name):
        os.chdir(absjoin(self.root_dir, "dist"))

        # install via pip
        pkg = "passlib-" + self.version + ".tar.gz"
        if self.is_vm_sitewide(name):
            subprocess.check_call([
                "sudo",
                self.get_vm_exe(name, "pip"),
                "install",
                pkg,
            ])
        else:
            subprocess.check_call([
                self.get_vm_exe(name, "pip"),
                "install", "--user",
                pkg,
            ])

        # cd to install location and run tests
        # NOTE: just testing that pip worked, so skipping expensive tests
        os.chdir(absjoin(self.get_vm_dir(name)))
        subprocess.check_call([
            self.get_vm_exe(name, "nosetests"),
            "--exe", # later versions set exe bit on test_xxx.py files
            "--tests", "passlib/tests/test_context.py",
        ])

    def run_vm_test_egg(self, name):

        # build & install egg
        subprocess.check_call([
            self.get_vm_exe(name, "python"),
            "setup.py",
            "bdist_egg",
        ])
        egg_name = "passlib-%s-py%s.egg" %  (self.version, self.get_vm_suffix(name))
        exe = self.get_vm_exe(name, "easy_install")
        if self.is_vm_sitewide(name):
            subprocess.check_call(["sudo", exe, "dist/" + egg_name])
        else:
            subprocess.check_call([exe, "--user", "dist/" + egg_name])

        # cd to install location and run tests
        os.chdir(absjoin(self.get_vm_dir(name), egg_name))
        subprocess.check_call([
            self.get_vm_exe(name, "nosetests"),
            "--exe", # later versions set exe bit on test_xxx.py files
            "--tests", "passlib/tests",
        ])

    def uninstall_passlib(self, name):
        vm_dir = self.get_vm_dir(name)
        discard_paths(*[
            absjoin(vm_dir, fname)
            for fname in os.listdir(vm_dir)
            if fname.startswith("passlib")
            ], sudo=self.is_vm_sitewide(name))

    #=========================================================================
    # vm info
    #=========================================================================
    def parse_vm(self, name):
        "parse 'vm name' string into (vm id, py version, vm release)"
        if name == "gae":
            name = "2.5"
        m = re.match(r"^(?P<vm>[a-z]*)(?P<ver>[\d.]+)(-(?P<rel>[\d.]+))?$", name)
        if not m:
            raise ValueError("can't parse vm name: %r" % (name,))
        return m.group("vm", "ver", "rel")

    def is_vm_sitewide(self, name):
        "does vm require installing site-wide?"
        vm, ver, rel = self.parse_vm(name)
        return vm == "y" or ver == "2.5"

    def get_vm_suffix(self, name):
        "return suffix used by egg built using specified vm"
        return self.parse_vm(name)[1]

    def get_vm_dir(self, name):
        "get name of dir where eggs will be installed for specified vm"
        vm, ver, rel = self.parse_vm(name)
        if vm == "y":
            return "/opt/pypy-" + rel + "/site-packages"
        elif vm in ["j", ""] and ver == "2.5":
            prefix = "/usr/lib"
        else:
            prefix = os.path.expanduser("~/.local/lib")
        return prefix + "/python" + self.get_vm_suffix(name) + "/site-packages"

    def get_vm_exe(self, name, exe):
        "return path to appropriate exe for specified vm"
        vm, ver, rel = self.parse_vm(name)
        if vm:
            if vm == "y":
                if exe == "python":
                    exe = "pypy"
                return "/opt/pypy-" + rel + "/bin/" + exe
            elif vm == "j" and exe == "python":
                return "jython"
            else:
                return exe + "-" + name
        else:
            if exe == "python":
                return "python" + ver
            else:
                return exe + "-" + ver

    #=========================================================================
    # eoc
    #=========================================================================

if __name__ == "__main__":
    app = PlatformTestApp(sys.argv[1:])
    sys.exit(app.run())

#=========================================================================
# eof
#=========================================================================