tests/get-with-headers.py
author Manuel Jacob <me@manueljacob.de>
Sun, 22 May 2022 03:50:34 +0200
changeset 49269 395f28064826
parent 48875 6000f5b25c9b
child 49905 cd125eef4388
permissions -rwxr-xr-x
worker: avoid potential partial write of pickled data Previously, the code wrote the pickled data using os.write(). However, os.write() can write less bytes than passed to it. To trigger the problem, the pickled data had to be larger than 2147479552 bytes on my system. Instead, open a file object and pass it to pickle.dump(). This also has the advantage that it doesn’t buffer the whole pickled data in memory. Note that the opened file must be buffered because pickle doesn’t support unbuffered streams because unbuffered streams’ write() method might write less bytes than passed to it (like os.write()) but pickle.dump() relies on that all bytes are written (see https://github.com/python/cpython/issues/93050). The side effect of using a file object and a with statement is that wfd is explicitly closed now while it seems like before it was implicitly closed by process exit.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47500
23f5ed6dbcb1 run-tests: stop writing a `python3` symlink pointing to python2
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45830
diff changeset
     1
#!/usr/bin/env python
2532
84655f721f39 Add a test for getting raw files via the web UI.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     2
8447
d5ebcf8f6855 tests: fix doc string in get-with-headers.py
Martin Geisler <mg@lazybytes.net>
parents: 7544
diff changeset
     3
"""This does HTTP GET requests given a host:port and path and returns
2532
84655f721f39 Add a test for getting raw files via the web UI.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     4
a subset of the headers plus the body of the result."""
84655f721f39 Add a test for getting raw files via the web UI.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     5
27296
8e86679d8acd tests: use absolute_import in /get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25208
diff changeset
     6
35780
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
     7
import argparse
27296
8e86679d8acd tests: use absolute_import in /get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25208
diff changeset
     8
import json
8e86679d8acd tests: use absolute_import in /get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25208
diff changeset
     9
import os
8e86679d8acd tests: use absolute_import in /get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25208
diff changeset
    10
import sys
7054
e837f2294643 get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5561
diff changeset
    11
29455
0c741fd6158a py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28726
diff changeset
    12
from mercurial import (
40154
fe11fc7e541f py3: encode JSON str to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36576
diff changeset
    13
    pycompat,
29455
0c741fd6158a py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28726
diff changeset
    14
    util,
0c741fd6158a py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28726
diff changeset
    15
)
0c741fd6158a py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28726
diff changeset
    16
0c741fd6158a py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28726
diff changeset
    17
httplib = util.httplib
0c741fd6158a py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28726
diff changeset
    18
7054
e837f2294643 get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5561
diff changeset
    19
try:
27296
8e86679d8acd tests: use absolute_import in /get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25208
diff changeset
    20
    import msvcrt
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    21
7054
e837f2294643 get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5561
diff changeset
    22
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
e837f2294643 get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5561
diff changeset
    23
    msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
e837f2294643 get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5561
diff changeset
    24
except ImportError:
e837f2294643 get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5561
diff changeset
    25
    pass
e837f2294643 get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5561
diff changeset
    26
36576
cfd0c1df5e33 get-with-headers: use bytes stdout thoroughly
Yuya Nishihara <yuya@tcha.org>
parents: 36276
diff changeset
    27
stdout = getattr(sys.stdout, 'buffer', sys.stdout)
cfd0c1df5e33 get-with-headers: use bytes stdout thoroughly
Yuya Nishihara <yuya@tcha.org>
parents: 36276
diff changeset
    28
35780
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    29
parser = argparse.ArgumentParser()
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    30
parser.add_argument('--twice', action='store_true')
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    31
parser.add_argument('--headeronly', action='store_true')
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    32
parser.add_argument('--json', action='store_true')
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    33
parser.add_argument('--hgproto')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    34
parser.add_argument(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    35
    '--requestheader',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    36
    nargs='*',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    37
    default=[],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    38
    help='Send an additional HTTP request header. Argument '
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    39
    'value is <header>=<value>',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    40
)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    41
parser.add_argument('--bodyfile', help='Write HTTP response body to a file')
35780
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    42
parser.add_argument('host')
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    43
parser.add_argument('path')
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    44
parser.add_argument('show', nargs='*')
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    45
35780
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    46
args = parser.parse_args()
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    47
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    48
twice = args.twice
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    49
headeronly = args.headeronly
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    50
formatjson = args.json
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
    51
hgproto = args.hgproto
35781
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    52
requestheaders = args.requestheader
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29455
diff changeset
    53
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    54
tag = None
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    55
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    56
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    57
def request(host, path, show):
17017
953faba28e91 tests: prepare get-with-headers.py for MSYS
Mads Kiilerich <mads@kiilerich.com>
parents: 12250
diff changeset
    58
    assert not path.startswith('/'), path
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    59
    global tag
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    60
    headers = {}
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    61
    if tag:
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    62
        headers['If-None-Match'] = tag
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29455
diff changeset
    63
    if hgproto:
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29455
diff changeset
    64
        headers['X-HgProto-1'] = hgproto
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 2532
diff changeset
    65
35781
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    66
    for header in requestheaders:
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    67
        key, value = header.split('=', 1)
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    68
        headers[key] = value
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    69
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    70
    conn = httplib.HTTPConnection(host)
17017
953faba28e91 tests: prepare get-with-headers.py for MSYS
Mads Kiilerich <mads@kiilerich.com>
parents: 12250
diff changeset
    71
    conn.request("GET", '/' + path, None, headers)
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    72
    response = conn.getresponse()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    73
    stdout.write(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    74
        b'%d %s\n' % (response.status, response.reason.encode('ascii'))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    75
    )
18380
a4d7fd7ad1f7 serve: don't send any content headers with 304 responses
Mads Kiilerich <madski@unity3d.com>
parents: 17017
diff changeset
    76
    if show[:1] == ['-']:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    77
        show = sorted(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    78
            h for h, v in response.getheaders() if h.lower() not in show
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    79
        )
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    80
    for h in [h.lower() for h in show]:
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
    81
        if response.getheader(h, None) is not None:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    82
            stdout.write(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    83
                b"%s: %s\n"
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    84
                % (h.encode('ascii'), response.getheader(h).encode('ascii'))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
    85
            )
47582
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
    86
    if headeronly:
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
    87
        # still read the body to prevent windows to be unhappy about that
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
    88
        # (this might some flakyness in test-hgweb-filelog.t on Windows)
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
    89
        data = response.read()
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
    90
    else:
36576
cfd0c1df5e33 get-with-headers: use bytes stdout thoroughly
Yuya Nishihara <yuya@tcha.org>
parents: 36276
diff changeset
    91
        stdout.write(b'\n')
23409
dc4d2cd3aa3e hgweb: send proper HTTP response after uncaught exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 19865
diff changeset
    92
        data = response.read()
24543
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
    93
35781
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    94
        if args.bodyfile:
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    95
            bodyfh = open(args.bodyfile, 'wb')
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    96
        else:
36576
cfd0c1df5e33 get-with-headers: use bytes stdout thoroughly
Yuya Nishihara <yuya@tcha.org>
parents: 36276
diff changeset
    97
            bodyfh = stdout
35781
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
    98
24543
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
    99
        # Pretty print JSON. This also has the beneficial side-effect
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
   100
        # of verifying emitted JSON is well-formed.
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
   101
        if formatjson:
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
   102
            # json.dumps() will print trailing newlines. Eliminate them
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
   103
            # to make tests easier to write.
43380
579672b347d2 py3: define and use json.loads polyfill
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43076
diff changeset
   104
            data = pycompat.json_loads(data)
24543
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
   105
            lines = json.dumps(data, sort_keys=True, indent=2).splitlines()
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
   106
            for line in lines:
40154
fe11fc7e541f py3: encode JSON str to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36576
diff changeset
   107
                bodyfh.write(pycompat.sysbytes(line.rstrip()))
35781
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
   108
                bodyfh.write(b'\n')
24543
747401086a38 get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23409
diff changeset
   109
        else:
35781
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
   110
            bodyfh.write(data)
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
   111
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
   112
        if args.bodyfile:
c6ef8e841873 tests: teach get-with-headers.py some new tricks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35780
diff changeset
   113
            bodyfh.close()
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
   114
31791
39f6333e968c tests: store ETag when using --headeronly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30764
diff changeset
   115
    if twice and response.getheader('ETag', None):
39f6333e968c tests: store ETag when using --headeronly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30764
diff changeset
   116
        tag = response.getheader('ETag')
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
   117
47582
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
   118
    # further try to please the windows-flakyness deity
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
   119
    conn.close()
6bceecb28806 windows: make sure we fully read and cleanly close the connection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47500
diff changeset
   120
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
   121
    return response.status
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
   122
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40154
diff changeset
   123
35780
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
   124
status = request(args.host, args.path, args.show)
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
   125
if twice:
35780
32317f8bbe2a tests: use argparse in get-with-headers.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31791
diff changeset
   126
    status = request(args.host, args.path, args.show)
12182
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
   127
1121af239761 tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10905
diff changeset
   128
if 200 <= status <= 305:
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 2532
diff changeset
   129
    sys.exit(0)
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 2532
diff changeset
   130
sys.exit(1)