• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / zope.testbrowser / 16098871825

05 Mar 2025 04:01PM UTC coverage: 91.403%. Remained the same
16098871825

push

github

icemac
Back to development: 7.1

427 of 520 branches covered (82.12%)

Branch coverage included in aggregate %.

1859 of 1981 relevant lines covered (93.84%)

0.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.67
/src/zope/testbrowser/ftests/wsgitestapp.py
1
##############################################################################
2
#
3
# Copyright (c) 2010 Zope Foundation and Contributors.
4
# All Rights Reserved.
5
#
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
12
#
13
##############################################################################
14
"""A minimal WSGI application used as a test fixture."""
15

16
import html
1✔
17
import mimetypes
1✔
18
import os
1✔
19
from datetime import datetime
1✔
20

21
from webob import Request
1✔
22
from webob import Response
1✔
23

24

25
class NotFound(Exception):
1✔
26
    pass
1✔
27

28

29
_HERE = os.path.dirname(__file__)
1✔
30

31

32
class WSGITestApplication:
1✔
33

34
    def __init__(self):
1✔
35
        self.request_log = []
1✔
36

37
    def __call__(self, environ, start_response):
1✔
38
        req = Request(environ)
1✔
39
        self.request_log.append(req)
1✔
40
        handler = {'/set_status.html': set_status,
1✔
41
                   '/echo.html': echo,
42
                   '/echo_one.html': echo_one,
43
                   '/redirect.html': redirect,
44
                   '/@@/testbrowser/forms.html': forms,
45
                   '/set_header.html': set_header,
46
                   '/set_cookie.html': set_cookie,
47
                   '/get_cookie.html': get_cookie,
48
                   '/inner/set_cookie.html': set_cookie,
49
                   '/inner/get_cookie.html': get_cookie,
50
                   '/inner/path/set_cookie.html': set_cookie,
51
                   '/inner/path/get_cookie.html': get_cookie,
52
                   }.get(req.path_info)
53
        if handler is None and req.path_info.startswith('/@@/testbrowser/'):
1✔
54
            handler = handle_resource
1✔
55
        if handler is None:
1✔
56
            handler = handle_notfound
1✔
57
        try:
1✔
58
            resp = handler(req)
1✔
59
        except Exception as exc:
1✔
60
            if not environ.get('wsgi.handleErrors', True):
1✔
61
                raise
1✔
62
            resp = Response()
1✔
63
            status = 500
1✔
64
            if isinstance(exc, NotFound):
1!
65
                status = 404
1✔
66
            resp.status = status
1✔
67
        return resp(environ, start_response)
1✔
68

69

70
def handle_notfound(req):
1✔
71
    raise NotFound(req.path_info)
1✔
72

73

74
class ParamsWrapper:
1✔
75

76
    def __init__(self, params):
1✔
77
        self.params = params
1✔
78

79
    def __getitem__(self, key):
1✔
80
        if key in self.params:
1✔
81
            return html.escape(self.params[key])
1✔
82
        return ''
1✔
83

84

85
def handle_resource(req, extra=None):
1✔
86
    filename = req.path_info.split('/')[-1]
1✔
87
    type, _ = mimetypes.guess_type(filename)
1✔
88
    path = os.path.join(_HERE, filename)
1✔
89
    with open(path, 'rb') as f:
1✔
90
        contents = f.read()
1✔
91
    if type == 'text/html':
1✔
92
        params = {}
1✔
93
        params.update(req.params)
1✔
94
        if extra is not None:
1✔
95
            params.update(extra)
1✔
96
        contents = contents.decode('latin1')
1✔
97
        contents = contents % ParamsWrapper(params)
1✔
98
        contents = contents.encode('latin1')
1✔
99
    return Response(contents, content_type=type)
1✔
100

101

102
def forms(req):
1✔
103
    extra = {}
1✔
104
    if 'hidden-4' in req.params and 'submit-4' not in req.params:
1✔
105
        extra['no-submit-button'] = 'Submitted without the submit button.'
1✔
106
    return handle_resource(req, extra)
1✔
107

108

109
def get_cookie(req):
1✔
110
    cookies = ['%s: %s' % i for i in sorted(req.cookies.items())]
1✔
111
    return Response('\n'.join(cookies))
1✔
112

113

114
def set_cookie(req):
1✔
115
    cookie_parms = {'path': None}
1✔
116
    cookie_parms.update({str(k): str(v)
1✔
117
                         for k, v in req.params.items()})
118
    name = cookie_parms.pop('name')
1✔
119
    value = cookie_parms.pop('value')
1✔
120
    if 'max-age' in cookie_parms:
1✔
121
        cookie_parms['max_age'] = int(cookie_parms.pop('max-age'))
1✔
122
    if 'expires' in cookie_parms:
1✔
123
        cookie_parms['expires'] = datetime.strptime(
1✔
124
            cookie_parms.pop('expires'), '%a, %d %b %Y %H:%M:%S GMT')
125
    resp = Response()
1✔
126
    resp.set_cookie(name, value, **cookie_parms)
1✔
127
    return resp
1✔
128

129

130
def set_header(req):
1✔
131
    resp = Response()
1✔
132
    body = ["Set Headers:"]
1✔
133
    for k, v in sorted(req.params.items()):
1✔
134
        if not isinstance(k, str):
1!
135
            k = k.encode('latin1')
×
136
        if not isinstance(v, str):
1!
137
            v = v.encode('latin1')
×
138
        body.extend([k, v])
1✔
139
        resp.headers.add(k, v)
1✔
140
    resp.unicode_body = '\n'.join(body)
1✔
141
    return resp
1✔
142

143

144
_interesting_environ = ('CONTENT_LENGTH',
1✔
145
                        'CONTENT_TYPE',
146
                        'HTTP_ACCEPT_LANGUAGE',
147
                        'HTTP_CONNECTION',
148
                        'HTTP_HOST',
149
                        'HTTP_USER_AGENT',
150
                        'PATH_INFO',
151
                        'REQUEST_METHOD')
152

153

154
def echo(req):
1✔
155
    items = []
1✔
156
    for k in _interesting_environ:
1✔
157
        v = req.environ.get(k, None)
1✔
158
        if v is None:
1✔
159
            continue
1✔
160
        items.append('{}: {}'.format(k, v))
1✔
161
    items.extend('%s: %s' % x for x in sorted(req.params.items()))
1✔
162
    if (req.method == 'POST' and
1✔
163
            req.content_type == 'application/x-www-form-urlencoded'):
164
        body = b''
1✔
165
    else:
166
        body = req.body
1✔
167
    items.append("Body: '%s'" % body.decode('utf8'))
1✔
168
    return Response('\n'.join(items))
1✔
169

170

171
def redirect(req):
1✔
172
    loc = req.params['to']
1✔
173
    resp = Response("You are being redirected to %s" % loc)
1✔
174
    resp.location = loc
1✔
175
    resp.status = int(req.params.get('type', 302))
1✔
176
    return resp
1✔
177

178

179
def echo_one(req):
1✔
180
    resp = repr(req.environ.get(req.params['var']))
1✔
181
    return Response(resp)
1✔
182

183

184
def set_status(req):
1✔
185
    status = req.params.get('status')
1✔
186
    body = req.params.get('body', 'Just set a status of %s' % status)
1✔
187
    if status:
1✔
188
        return Response(body, status=int(status))
1✔
189
    return Response('Everything fine')
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc