From 261169b70eb7af32e76efc586de611174d7d5b6a Mon Sep 17 00:00:00 2001 From: debugtalk Date: Sun, 25 Mar 2018 21:15:43 +0800 Subject: [PATCH] refactor compatibility, learned from requests --- httprunner/__about__.py | 2 +- httprunner/built_in.py | 12 +++++----- httprunner/cli.py | 5 ++-- httprunner/client.py | 4 ++-- httprunner/compat.py | 53 +++++++++++++++++++++++++++++++++++++++++ httprunner/context.py | 2 +- httprunner/response.py | 4 ++-- httprunner/task.py | 3 ++- httprunner/testcase.py | 6 ++--- httprunner/utils.py | 15 +++--------- tests/data/debugtalk.py | 4 ---- tests/test_utils.py | 8 +++---- 12 files changed, 80 insertions(+), 38 deletions(-) create mode 100644 httprunner/compat.py diff --git a/httprunner/__about__.py b/httprunner/__about__.py index e9280236..b6313d10 100644 --- a/httprunner/__about__.py +++ b/httprunner/__about__.py @@ -1,7 +1,7 @@ __title__ = 'HttpRunner' __description__ = 'One-stop solution for HTTP(S) testing.' __url__ = 'https://github.com/HttpRunner/HttpRunner' -__version__ = '1.3.2' +__version__ = '1.3.3' __author__ = 'debugtalk' __author_email__ = 'mail@debugtalk.com' __license__ = 'MIT' diff --git a/httprunner/built_in.py b/httprunner/built_in.py index 32bbb851..1fe4bc0f 100644 --- a/httprunner/built_in.py +++ b/httprunner/built_in.py @@ -1,15 +1,15 @@ """ Built-in dependent functions used in YAML/JSON testcases. """ -import json import datetime +import json import random import re import string import time +from httprunner.compat import basestring from httprunner.exception import ParamsError -from httprunner.utils import string_type def gen_random_string(str_len): @@ -76,11 +76,11 @@ def length_less_than_or_equals(check_value, expect_value): assert len(check_value) <= expect_value def contains(check_value, expect_value): - assert isinstance(check_value, (list, tuple, dict, string_type)) + assert isinstance(check_value, (list, tuple, dict, basestring)) assert expect_value in check_value def contained_by(check_value, expect_value): - assert isinstance(expect_value, (list, tuple, dict, string_type)) + assert isinstance(expect_value, (list, tuple, dict, basestring)) assert check_value in expect_value def type_match(check_value, expect_value): @@ -98,8 +98,8 @@ def type_match(check_value, expect_value): assert isinstance(check_value, get_type(expect_value)) def regex_match(check_value, expect_value): - assert isinstance(expect_value, string_type) - assert isinstance(check_value, string_type) + assert isinstance(expect_value, basestring) + assert isinstance(check_value, basestring) assert re.match(expect_value, check_value) def startswith(check_value, expect_value): diff --git a/httprunner/cli.py b/httprunner/cli.py index 83462dcc..67eaeb52 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -7,8 +7,9 @@ import unittest from httprunner import logger from httprunner.__about__ import __version__ from httprunner.task import HttpRunner -from httprunner.utils import (create_scaffold, load_dot_env_file, print_output, - string_type, validate_json_file, prettify_json_file) +from httprunner.utils import (create_scaffold, load_dot_env_file, + prettify_json_file, print_output, + validate_json_file) def main_hrun(): diff --git a/httprunner/client.py b/httprunner/client.py index 3d091af2..82f20fdf 100644 --- a/httprunner/client.py +++ b/httprunner/client.py @@ -4,8 +4,8 @@ import time import requests import urllib3 from httprunner import logger +from httprunner.compat import is_py2 from httprunner.exception import ParamsError -from httprunner.utils import PYTHON_VERSION from requests import Request, Response from requests.exceptions import (InvalidSchema, InvalidURL, MissingSchema, RequestException) @@ -116,7 +116,7 @@ class HttpSession(requests.Session): self.meta_data["response_headers"] = response.headers self.meta_data["response_body"] = response.text - if PYTHON_VERSION == 2 and isinstance(self.meta_data["response_body"], unicode): + if is_py2 and isinstance(self.meta_data["response_body"], unicode): self.meta_data["response_body"] = self.meta_data["response_body"].encode("utf-8") logger.log_debug("response status_code: {}".format(self.meta_data["status_code"])) diff --git a/httprunner/compat.py b/httprunner/compat.py new file mode 100644 index 00000000..056c5aff --- /dev/null +++ b/httprunner/compat.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- + +""" +httprunner.compat +~~~~~~~~~~~~~~~~~ + +This module handles import compatibility issues between Python 2 and +Python 3. +""" + +import sys + +# ------- +# Pythons +# ------- + +# Syntax sugar. +_ver = sys.version_info + +#: Python 2.x? +is_py2 = (_ver[0] == 2) + +#: Python 3.x? +is_py3 = (_ver[0] == 3) + +try: + import simplejson as json +except ImportError: + import json + +# --------- +# Specifics +# --------- + +if is_py2: + from urllib3.packages.ordered_dict import OrderedDict + + builtin_str = str + bytes = str + str = unicode + basestring = basestring + numeric_types = (int, long, float) + integer_types = (int, long) + +elif is_py3: + from collections import OrderedDict + + builtin_str = str + str = str + bytes = bytes + basestring = (str, bytes) + numeric_types = (int, float) + integer_types = (int,) diff --git a/httprunner/context.py b/httprunner/context.py index 5fd2ea5e..eded3e88 100644 --- a/httprunner/context.py +++ b/httprunner/context.py @@ -2,9 +2,9 @@ import copy import os import re import sys -from collections import OrderedDict from httprunner import exception, testcase, utils +from httprunner.compat import OrderedDict class Context(object): diff --git a/httprunner/response.py b/httprunner/response.py index 3813a951..86e13e73 100644 --- a/httprunner/response.py +++ b/httprunner/response.py @@ -1,7 +1,7 @@ import re -from collections import OrderedDict from httprunner import exception, logger, testcase, utils +from httprunner.compat import OrderedDict, basestring from requests.structures import CaseInsensitiveDict text_extractor_regexp_compile = re.compile(r".*\(.*\).*") @@ -116,7 +116,7 @@ class ResponseObject(object): extract_binds_order_dict = utils.convert_to_order_dict(extractors) for key, field in extract_binds_order_dict.items(): - if not isinstance(field, utils.string_type): + if not isinstance(field, basestring): raise exception.ParamsError("invalid extractors in testcase!") extracted_variables_mapping[key] = self.extract_field(field) diff --git a/httprunner/task.py b/httprunner/task.py index f9033b75..4636355f 100644 --- a/httprunner/task.py +++ b/httprunner/task.py @@ -3,6 +3,7 @@ import sys import unittest from httprunner import exception, logger, runner, testcase, utils +from httprunner.compat import is_py3 from httprunner.report import HtmlTestResult, get_summary @@ -120,7 +121,7 @@ class TestSuite(unittest.TestSuite): return parametered_variables_list def _add_test_to_suite(self, testcase_name, test_runner, testcase_dict): - if utils.PYTHON_VERSION == 3: + if is_py3: TestCase.runTest.__doc__ = testcase_name else: TestCase.runTest.__func__.__doc__ = testcase_name diff --git a/httprunner/testcase.py b/httprunner/testcase.py index 4d673b4b..a8e303bb 100644 --- a/httprunner/testcase.py +++ b/httprunner/testcase.py @@ -6,10 +6,10 @@ import json import os import random import re -from collections import OrderedDict import yaml from httprunner import exception, logger, utils +from httprunner.compat import OrderedDict, numeric_types variable_regexp = r"\$([\w_]+)" function_regexp = r"\$\{([\w_]+\([\$\w\.\-_ =,]*\))\}" @@ -541,7 +541,7 @@ def substitute_variables_with_mapping(content, mapping): if isinstance(content, bool): return content - if isinstance(content, (int, utils.long_type, float, complex)): + if isinstance(content, (numeric_types, type)): return content if not content: @@ -852,7 +852,7 @@ class TestcaseParser(object): return evaluated_data - if isinstance(content, (int, utils.long_type, float, complex)): + if isinstance(content, (numeric_types, type)): return content # content is in string format here diff --git a/httprunner/utils.py b/httprunner/utils.py index dab42104..077d4ea4 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -10,20 +10,11 @@ import random import re import string import types -from collections import OrderedDict from httprunner import exception, logger +from httprunner.compat import OrderedDict, is_py2, is_py3 from requests.structures import CaseInsensitiveDict -try: - string_type = basestring - long_type = long - PYTHON_VERSION = 2 -except NameError: - string_type = str - long_type = int - PYTHON_VERSION = 3 - SECRET_KEY = "DebugTalk" @@ -205,7 +196,7 @@ def get_imported_module_from_file(file_path): """ import module from python file path and return imported module """ - if PYTHON_VERSION == 3: + if is_py3: imported_module = importlib.machinery.SourceFileLoader( 'module_name', file_path).load_module() else: @@ -355,7 +346,7 @@ def print_output(outputs): content = "" for variable, value in in_out.items(): - if PYTHON_VERSION == 2: + if is_py2: if isinstance(variable, unicode): variable = variable.encode("utf-8") if isinstance(value, unicode): diff --git a/tests/data/debugtalk.py b/tests/data/debugtalk.py index 68049a81..b6553f70 100644 --- a/tests/data/debugtalk.py +++ b/tests/data/debugtalk.py @@ -7,12 +7,8 @@ import string import time try: - string_type = basestring - PYTHON_VERSION = 2 import urllib except NameError: - string_type = str - PYTHON_VERSION = 3 import urllib.parse as urllib SECRET_KEY = "DebugTalk" diff --git a/tests/test_utils.py b/tests/test_utils.py index 84a8b0c1..b3a0883b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,8 +1,8 @@ import os import shutil -from collections import OrderedDict from httprunner import exception, utils +from httprunner.compat import OrderedDict from tests.base import ApiServerUnittest @@ -180,11 +180,11 @@ class TestUtils(ApiServerUnittest): def test_filter_module_functions(self): imported_module = utils.get_imported_module("httprunner.utils") - self.assertIn("PYTHON_VERSION", dir(imported_module)) + self.assertIn("is_py3", dir(imported_module)) functions_dict = utils.filter_module(imported_module, "function") self.assertIn("filter_module", functions_dict) - self.assertNotIn("PYTHON_VERSION", functions_dict) + self.assertNotIn("is_py3", functions_dict) def test_get_imported_module_from_file(self): imported_module = utils.get_imported_module_from_file("tests/data/debugtalk.py") @@ -192,7 +192,7 @@ class TestUtils(ApiServerUnittest): functions_dict = utils.filter_module(imported_module, "function") self.assertIn("gen_md5", functions_dict) - self.assertNotIn("PYTHON_VERSION", functions_dict) + self.assertNotIn("urllib", functions_dict) with self.assertRaises(exception.FileNotFoundError): utils.get_imported_module_from_file("tests/data/debugtalk2.py")