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

""" 

Generic test utilities. 

 

""" 

 

from __future__ import division, print_function, absolute_import 

 

import os 

import re 

import sys 

 

 

__all__ = ['PytestTester', 'check_free_memory'] 

 

 

class FPUModeChangeWarning(RuntimeWarning): 

"""Warning about FPU mode change""" 

pass 

 

 

class PytestTester(object): 

""" 

Pytest test runner entry point. 

""" 

 

def __init__(self, module_name): 

self.module_name = module_name 

 

def __call__(self, label="fast", verbose=1, extra_argv=None, doctests=False, 

coverage=False, tests=None): 

import pytest 

 

module = sys.modules[self.module_name] 

module_path = os.path.abspath(module.__path__[0]) 

 

pytest_args = ['-l'] 

 

if doctests: 

raise ValueError("Doctests not supported") 

 

if extra_argv: 

pytest_args += list(extra_argv) 

 

if verbose and int(verbose) > 1: 

pytest_args += ["-" + "v"*(int(verbose)-1)] 

 

if coverage: 

pytest_args += ["--cov=" + module_path] 

 

if label == "fast": 

pytest_args += ["-m", "not slow"] 

elif label != "full": 

pytest_args += ["-m", label] 

 

if tests is None: 

tests = [self.module_name] 

 

pytest_args += ['--pyargs'] + list(tests) 

 

try: 

code = pytest.main(pytest_args) 

except SystemExit as exc: 

code = exc.code 

 

return (code == 0) 

 

 

def check_free_memory(free_mb): 

""" 

Check *free_mb* of memory is available, otherwise do pytest.skip 

""" 

import pytest 

 

try: 

mem_free = _parse_size(os.environ['SCIPY_AVAILABLE_MEM']) 

msg = '{0} MB memory required, but environment SCIPY_AVAILABLE_MEM={1}'.format( 

free_mb, os.environ['SCIPY_AVAILABLE_MEM']) 

except KeyError: 

mem_free = _get_mem_available() 

if mem_free is None: 

pytest.skip("Could not determine available memory; set SCIPY_AVAILABLE_MEM " 

"variable to free memory in MB to run the test.") 

msg = '{0} MB memory required, but {1} MB available'.format( 

free_mb, mem_free/1e6) 

 

if mem_free < free_mb * 1e6: 

pytest.skip(msg) 

 

 

def _parse_size(size_str): 

suffixes = {'': 1e6, 

'b': 1.0, 

'k': 1e3, 'M': 1e6, 'G': 1e9, 'T': 1e12, 

'kb': 1e3, 'Mb': 1e6, 'Gb': 1e9, 'Tb': 1e12, 

'kib': 1024.0, 'Mib': 1024.0**2, 'Gib': 1024.0**3, 'Tib': 1024.0**4} 

m = re.match(r'^\s*(\d+)\s*({0})\s*$'.format('|'.join(suffixes.keys())), 

size_str, 

re.I) 

if not m or m.group(2) not in suffixes: 

raise ValueError("Invalid size string") 

 

return float(m.group(1)) * suffixes[m.group(2)] 

 

 

def _get_mem_available(): 

""" 

Get information about memory available, not counting swap. 

""" 

try: 

import psutil 

return psutil.virtual_memory().available 

except (ImportError, AttributeError): 

pass 

 

if sys.platform.startswith('linux'): 

info = {} 

with open('/proc/meminfo', 'r') as f: 

for line in f: 

p = line.split() 

info[p[0].strip(':').lower()] = float(p[1]) * 1e3 

 

if 'memavailable' in info: 

# Linux >= 3.14 

return info['memavailable'] 

else: 

return info['memfree'] + info['cached'] 

 

return None