Skip to content

Commit 1e32eb9

Browse files
committed
First Commit
1 parent de33476 commit 1e32eb9

11 files changed

+307
-425
lines changed

pyresttest/benchmarks.py

+18-34
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
import math
22
import json
33
import pycurl
4-
import sys
54

6-
from . import tests
7-
from .tests import Test
8-
from . import parsing
9-
from .parsing import *
5+
from constants import DEFAULT_TIMEOUT
6+
from tests import Test, coerce_to_string
7+
from parsing import *
108

11-
# Python 2/3 switches
12-
if sys.version_info[0] > 2:
13-
from past.builtins import basestring
149

15-
# Python 3 compatibility shims
16-
from . import six
17-
from .six import binary_type
18-
from .six import text_type
1910

2011
"""
2112
Encapsulates logic related to benchmarking
@@ -109,10 +100,7 @@ def std_deviation(array):
109100

110101
average = AGGREGATES['mean_arithmetic'](array)
111102
variance = map(lambda x: (x - average)**2, array)
112-
try:
113-
len(variance)
114-
except TypeError: # Python 3.3 workaround until can use the statistics module from 3.4
115-
variance = list(variance)
103+
variance = list(variance)
116104
stdev = AGGREGATES['mean_arithmetic'](variance)
117105
return math.sqrt(stdev)
118106

@@ -193,13 +181,9 @@ def realize_partial(self, context=None):
193181
# Enhanceme - once extract is done, check if variables already bound,
194182
# in that case template out
195183
return self
196-
else:
197-
copyout = copy.cop
198-
199-
pass
200184

201185

202-
def configure_curl(self, timeout=tests.DEFAULT_TIMEOUT, context=None, curl_handle=None):
186+
def configure_curl(self, timeout=DEFAULT_TIMEOUT, context=None, curl_handle=None):
203187
curl = super().configure_curl(self, timeout=timeout,
204188
context=context, curl_handle=curl_handle)
205189
# Simulate results from different users hitting server
@@ -229,42 +213,42 @@ def parse_benchmark(base_url, node):
229213
else:
230214
raise ValueError('Invalid benchmark output format: ' + format)
231215
elif key == u'output_file':
232-
if not isinstance(value, basestring):
216+
if not isinstance(value, str):
233217
raise ValueError("Invalid output file format")
234218
benchmark.output_file = value
235219
elif key == u'metrics':
236-
if isinstance(value, basestring):
220+
if isinstance(value, str):
237221
# Single value
238-
benchmark.add_metric(tests.coerce_to_string(value))
222+
benchmark.add_metric(coerce_to_string(value))
239223
# FIXME refactor the parsing of metrics here, lots of duplicated logic
240224
elif isinstance(value, list) or isinstance(value, set):
241225
# List of single values or list of {metric:aggregate, ...}
242226
for metric in value:
243227
if isinstance(metric, dict):
244228
for metricname, aggregate in metric.items():
245-
if not isinstance(metricname, basestring):
229+
if not isinstance(metricname, str):
246230
raise TypeError(
247231
"Invalid metric input: non-string metric name")
248-
if not isinstance(aggregate, basestring):
232+
if not isinstance(aggregate, str):
249233
raise TypeError(
250234
"Invalid aggregate input: non-string aggregate name")
251235
# TODO unicode-safe this
252-
benchmark.add_metric(tests.coerce_to_string(metricname),
253-
tests.coerce_to_string(aggregate))
236+
benchmark.add_metric(coerce_to_string(metricname),
237+
coerce_to_string(aggregate))
254238

255-
elif isinstance(metric, basestring):
256-
benchmark.add_metric(tests.coerce_to_string(metric))
239+
elif isinstance(metric, str):
240+
benchmark.add_metric(coerce_to_string(metric))
257241
elif isinstance(value, dict):
258242
# Dictionary of metric-aggregate pairs
259243
for metricname, aggregate in value.items():
260-
if not isinstance(metricname, basestring):
244+
if not isinstance(metricname, str):
261245
raise TypeError(
262246
"Invalid metric input: non-string metric name")
263-
if not isinstance(aggregate, basestring):
247+
if not isinstance(aggregate, str):
264248
raise TypeError(
265249
"Invalid aggregate input: non-string aggregate name")
266-
benchmark.add_metric(tests.coerce_to_string(metricname),
267-
tests.coerce_to_string(aggregate))
250+
benchmark.add_metric(coerce_to_string(metricname),
251+
coerce_to_string(aggregate))
268252
else:
269253
raise TypeError(
270254
"Invalid benchmark metric datatype: " + str(value))

pyresttest/constants.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from dataclasses import dataclass
2+
3+
DEFAULT_TIMEOUT = 10
4+
5+
6+
@dataclass(frozen=True)
7+
class YamlKeyWords:
8+
IMPORT = 'import'
9+
TEST = 'test'
10+
URL = 'url'
11+
BENCHMARK = 'benchmark'
12+
CONFIG = 'config'
13+
# Configurations
14+
TIMEOUT = 'timeout'
15+
LOG_BODY = 'print_bodies'
16+
VARS = 'variable_binds'
17+
GENERATORS = 'generators'
18+
RETRIES = 'retries'
19+

pyresttest/contenthandling.py

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
import os
2-
import sys
3-
4-
from . import parsing
5-
from .parsing import *
6-
7-
# Python 2/3 switches
8-
PYTHON_MAJOR_VERSION = sys.version_info[0]
9-
if PYTHON_MAJOR_VERSION > 2:
10-
from past.builtins import basestring
2+
from pyresttest.parsing import *
113

124

135
"""
@@ -72,7 +64,7 @@ def create_noread_version(self):
7264

7365
def setup(self, input, is_file=False, is_template_path=False, is_template_content=False):
7466
""" Self explanatory, input is inline content or file path. """
75-
if not isinstance(input, basestring):
67+
if not isinstance(input, str):
7668
raise TypeError("Input is not a string")
7769
if is_file:
7870
input = os.path.abspath(input)
@@ -103,7 +95,7 @@ def parse_content(node):
10395

10496
while (node and not is_done): # Dive through the configuration tree
10597
# Finally we've found the value!
106-
if isinstance(node, basestring):
98+
if isinstance(node, str):
10799
output.content = node
108100
output.setup(node, is_file=is_file, is_template_path=is_template_path,
109101
is_template_content=is_template_content)
@@ -118,7 +110,7 @@ def parse_content(node):
118110
flat = lowercase_keys(flatten_dictionaries(node))
119111
for key, value in flat.items():
120112
if key == u'template':
121-
if isinstance(value, basestring):
113+
if isinstance(value, str):
122114
if is_file:
123115
value = os.path.abspath(value)
124116
output.content = value
@@ -134,7 +126,7 @@ def parse_content(node):
134126
break
135127

136128
elif key == 'file':
137-
if isinstance(value, basestring):
129+
if isinstance(value, str):
138130
output.content = os.path.abspath(value)
139131
output.is_file = True
140132
output.is_template_content = is_template_content

pyresttest/ext/extractor_jmespath.py

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
import traceback
21
import json
32
import sys
4-
PYTHON_MAJOR_VERSION = sys.version_info[0]
53

6-
import yaml
7-
import ast
4+
85
import jmespath
96

107
try: # First try to load pyresttest from global namespace
@@ -18,6 +15,7 @@
1815
from .. import parsing
1916
from .. import contenthandling
2017

18+
2119
class JMESPathExtractor(validators.AbstractExtractor):
2220
""" Extractor that uses JMESPath syntax
2321
See http://jmespath.org/specification.html for details
@@ -26,13 +24,11 @@ class JMESPathExtractor(validators.AbstractExtractor):
2624
is_body_extractor = True
2725

2826
def extract_internal(self, query=None, args=None, body=None, headers=None):
29-
mybody = body
30-
if PYTHON_MAJOR_VERSION > 2:
31-
if isinstance(mybody, bytes):
32-
mybody = str(mybody, 'utf-8')
27+
if isinstance(body, bytes):
28+
body = str(body, 'utf-8')
3329

3430
try:
35-
res = jmespath.search(query, json.loads(mybody)) # Better way
31+
res = jmespath.search(query, json.loads(body))
3632
return res
3733
except Exception as e:
3834
raise ValueError("Invalid query: " + query + " : " + str(e))
@@ -41,6 +37,6 @@ def extract_internal(self, query=None, args=None, body=None, headers=None):
4137
def parse(cls, config):
4238
base = JMESPathExtractor()
4339
return cls.configure_base(config, base)
44-
return base
40+
4541

4642
EXTRACTORS = {'jmespath': JMESPathExtractor.parse}

pyresttest/generators.py

+25-26
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,7 @@
22
import string
33
import os
44
import logging
5-
import sys
6-
7-
from . import parsing
8-
from .parsing import flatten_dictionaries, lowercase_keys, safe_to_bool
9-
10-
# Python 3 compatibility
11-
if sys.version_info[0] > 2:
12-
from builtins import range as xrange
13-
from past.builtins import basestring
5+
from pyresttest.parsing import flatten_dictionaries, lowercase_keys
146

157
""" Collection of generators to be used in templating for test data
168
@@ -29,8 +21,8 @@
2921
'ascii_uppercase': string.ascii_uppercase,
3022
'digits': string.digits,
3123
'hexdigits': string.hexdigits,
32-
'hex_lower': string.digits + 'abcdef',
33-
'hex_upper': string.digits + 'ABCDEF',
24+
'hex_lower': string.digits + 'abcdef',
25+
'hex_upper': string.digits + 'ABCDEF',
3426
'letters': string.ascii_letters,
3527
'lowercase': string.ascii_lowercase,
3628
'octdigits': string.octdigits,
@@ -49,12 +41,14 @@
4941
def factory_generate_ids(starting_id=1, increment=1):
5042
""" Return function generator for ids starting at starting_id
5143
Note: needs to be called with () to make generator """
44+
5245
def generate_started_ids():
5346
val = starting_id
5447
local_increment = increment
55-
while(True):
48+
while (True):
5649
yield val
5750
val += local_increment
51+
5852
return generate_started_ids
5953

6054

@@ -76,14 +70,15 @@ def factory_generate_text(legal_characters=string.ascii_letters, min_length=8, m
7670
7771
For hex digits, combine with string.hexstring, etc
7872
"""
73+
7974
def generate_text():
8075
local_min_len = min_length
8176
local_max_len = max_length
8277
rand = random.Random()
83-
while(True):
78+
while True:
8479
length = random.randint(local_min_len, local_max_len)
8580
array = [random.choice(legal_characters)
86-
for x in xrange(0, length)]
81+
for x in range(0, length)]
8782
yield ''.join(array)
8883

8984
return generate_text
@@ -95,10 +90,11 @@ def factory_fixed_sequence(values):
9590
def seq_generator():
9691
my_list = list(values)
9792
i = 0
98-
while(True):
93+
while (True):
9994
yield my_list[i]
10095
if i == len(my_list):
10196
i = 0
97+
10298
return seq_generator
10399

104100

@@ -118,8 +114,9 @@ def factory_choice_generator(values):
118114
def choice_generator():
119115
my_list = list(values)
120116
rand = random.Random()
121-
while(True):
117+
while (True):
122118
yield random.choice(my_list)
119+
123120
return choice_generator
124121

125122

@@ -138,7 +135,7 @@ def factory_env_variable(env_variable):
138135

139136
def return_variable():
140137
variable_name = env_variable
141-
while(True):
138+
while (True):
142139
yield os.environ.get(variable_name)
143140

144141
return return_variable
@@ -149,11 +146,12 @@ def factory_env_string(env_string):
149146

150147
def return_variable():
151148
my_input = env_string
152-
while(True):
149+
while (True):
153150
yield os.path.expandvars(my_input)
154151

155152
return return_variable
156153

154+
157155
""" Implements the parsing logic for YAML, and acts as single point for reading configuration """
158156

159157

@@ -190,13 +188,13 @@ def parse_random_text_generator(configuration):
190188

191189

192190
# List of valid generator types
193-
GENERATOR_TYPES = set(['env_variable',
194-
'env_string',
195-
'number_sequence',
196-
'random_int',
197-
'random_text',
198-
'fixed_sequence'
199-
])
191+
GENERATOR_TYPES = {'env_variable',
192+
'env_string',
193+
'number_sequence',
194+
'random_int',
195+
'random_text',
196+
'fixed_sequence'
197+
}
200198

201199
GENERATOR_PARSING = {'fixed_sequence': parse_fixed_sequence}
202200

@@ -206,7 +204,7 @@ def register_generator(typename, parse_function):
206204
typename is the new generator type name (must not already exist)
207205
parse_function will parse a configuration object (dict)
208206
"""
209-
if not isinstance(typename, basestring):
207+
if not isinstance(typename, str):
210208
raise TypeError(
211209
'Generator type name {0} is invalid, must be a string'.format(typename))
212210
if typename in GENERATOR_TYPES:
@@ -215,6 +213,7 @@ def register_generator(typename, parse_function):
215213
GENERATOR_TYPES.add(typename)
216214
GENERATOR_PARSING[typename] = parse_function
217215

216+
218217
# Try registering a new generator
219218
register_generator('choice', parse_choice_generator)
220219

0 commit comments

Comments
 (0)