1# -*- coding: utf-8 -*- 2# Copyright (c) 2018 gevent community 3# 4# Permission is hereby granted, free of charge, to any person obtaining a copy 5# of this software and associated documentation files (the "Software"), to deal 6# in the Software without restriction, including without limitation the rights 7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8# copies of the Software, and to permit persons to whom the Software is 9# furnished to do so, subject to the following conditions: 10# 11# The above copyright notice and this permission notice shall be included in 12# all copies or substantial portions of the Software. 13# 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20# THE SOFTWARE. 21 22""" 23Test environment setup. 24 25This establishes the resources that are available for use, 26which are tested with `support.is_resource_enabled`. 27 28""" 29from __future__ import absolute_import, division, print_function 30 31# This file may be imported early, so it should take care not to import 32# things it doesn't need, which means deferred imports. 33 34 35def get_ALL_RESOURCES(): 36 "Return a fresh list of resource names." 37 # RESOURCE_NAMES is the list of all known resources, including those that 38 # shouldn't be enabled by default or when asking for "all" resources. 39 # ALL_RESOURCES is the list of resources enabled by default or with "all" resources. 40 41 try: 42 # 3.6 and 3.7 43 from test.libregrtest import ALL_RESOURCES 44 except ImportError: 45 # 2.7 through 3.5 46 47 # Don't do this: 48 ## from test.regrtest import ALL_RESOURCES 49 50 # On Python 2.7 to 3.5, importing regrtest iterates 51 # sys.modules and does modifications. That doesn't work well 52 # when it's imported from another module at module scope. 53 # Also, it makes some assumptions about module __file__ that 54 # may not hold true (at least on 2.7), especially when six or 55 # other module proxy objects are involved. 56 # So we hardcode the list. This is from 2.7, which is a superset 57 # of the defined resources through 3.5. 58 59 ALL_RESOURCES = ( 60 'audio', 'curses', 'largefile', 'network', 'bsddb', 61 'decimal', 'cpu', 'subprocess', 'urlfetch', 'gui', 62 'xpickle' 63 ) 64 65 return list(ALL_RESOURCES) + [ 66 # Do we test the stdlib monkey-patched? 67 'gevent_monkey', 68 ] 69 70 71def parse_resources(resource_str=None): 72 # str -> Sequence[str] 73 74 # Parse it like libregrtest.cmdline documents: 75 76 # -u is used to specify which special resource intensive tests to run, 77 # such as those requiring large file support or network connectivity. 78 # The argument is a comma-separated list of words indicating the 79 # resources to test. Currently only the following are defined: 80 81 # all - Enable all special resources. 82 # 83 # none - Disable all special resources (this is the default). 84 # <snip> 85 # network - It is okay to run tests that use external network 86 # resource, e.g. testing SSL support for sockets. 87 # <snip> 88 # 89 # subprocess Run all tests for the subprocess module. 90 # <snip> 91 # 92 # To enable all resources except one, use '-uall,-<resource>'. For 93 # example, to run all the tests except for the gui tests, give the 94 # option '-uall,-gui'. 95 96 # We make a change though: we default to 'all' resources, instead of 97 # 'none'. Encountering either of those later in the string resets 98 # it, for ease of working with appending to environment variables. 99 100 if resource_str is None: 101 import os 102 resource_str = os.environ.get('GEVENTTEST_USE_RESOURCES') 103 104 resources = get_ALL_RESOURCES() 105 106 if not resource_str: 107 return resources 108 109 requested_resources = resource_str.split(',') 110 111 for requested_resource in requested_resources: 112 # empty strings are ignored; this can happen when working with 113 # the environment variable if not already set: 114 # ENV=$ENV,-network 115 if not requested_resource: 116 continue 117 if requested_resource == 'all': 118 resources = get_ALL_RESOURCES() 119 elif requested_resource == 'none': 120 resources = [] 121 elif requested_resource.startswith('-'): 122 if requested_resource[1:] in resources: 123 resources.remove(requested_resource[1:]) 124 else: 125 # TODO: Produce a warning if it's an unknown resource? 126 resources.append(requested_resource) 127 128 return resources 129 130def unparse_resources(resources): 131 """ 132 Given a list of enabled resources, produce the correct environment variable 133 setting to enable (only) that list. 134 """ 135 # By default, we assume all resources are enabled, so explicitly 136 # listing them here doesn't actually disable anything. To do that, we want to 137 # list the ones that are disabled. This is usually shorter than starting with 138 # 'none', and manually adding them back in one by one. 139 # 140 # 'none' must be special cased because an empty option string 141 # means 'all'. Still, we're explicit about that. 142 # 143 # TODO: Make this produce the minimal output; sometimes 'none' and 144 # adding would be shorter. 145 146 all_resources = set(get_ALL_RESOURCES()) 147 enabled = set(resources) 148 149 if enabled == all_resources: 150 result = 'all' 151 elif resources: 152 explicitly_disabled = all_resources - enabled 153 result = ''.join(sorted('-' + x for x in explicitly_disabled)) 154 else: 155 result = 'none' 156 return result 157 158 159def setup_resources(resources=None): 160 """ 161 Call either with a list of resources or a resource string. 162 163 If ``None`` is given, get the resource string from the environment. 164 """ 165 166 if isinstance(resources, str) or resources is None: 167 resources = parse_resources(resources) 168 169 from . import support 170 support.use_resources = list(resources) 171 support.gevent_has_setup_resources = True 172 173 return resources 174 175def ensure_setup_resources(): 176 # Call when you don't know if resources have been setup and you want to 177 # get the environment variable if needed. 178 # Returns an object with `is_resource_enabled`. 179 from . import support 180 if not support.gevent_has_setup_resources: 181 setup_resources() 182 183 return support 184 185def exit_without_resource(resource): 186 """ 187 Call this in standalone test modules that can't use unittest.SkipTest. 188 189 Exits with a status of 0 if the resource isn't enabled. 190 """ 191 192 if not ensure_setup_resources().is_resource_enabled(resource): 193 print("Skipped: %r not enabled" % (resource,)) 194 import sys 195 sys.exit(0) 196 197def skip_without_resource(resource, reason=''): 198 requires = 'Requires resource %r' % (resource,) 199 if not reason: 200 reason = requires 201 else: 202 reason = reason + ' (' + requires + ')' 203 204 if not ensure_setup_resources().is_resource_enabled(resource): 205 import unittest 206 raise unittest.SkipTest(reason) 207 208if __name__ == '__main__': 209 print(setup_resources()) 210