def cassette_setup_and_teardown_decorator(func): """ Decorator that triggers `cassette_setup` method to be run before the test method. """ if hasattr(func, REQURE_SETUP_APPLIED_ATTRIBUTE_NAME): return func func_cassette = (getattr(func, REQURE_CASSETTE_ATTRIBUTE_NAME) if hasattr( func, REQURE_CASSETTE_ATTRIBUTE_NAME) else None) cassette_int = func_cassette or Cassette() @functools.wraps(func) def cassette_setup_inner(self, *args, **kwargs): if hasattr(self, "cassette_setup"): self.cassette_setup(cassette=cassette_int) if ("cassette" in inspect.getfullargspec(func).annotations and inspect.getfullargspec(func).annotations["cassette"] == Cassette and "cassette" not in kwargs): kwargs["cassette"] = cassette_int return_value = func(self, *args, **kwargs) if hasattr(self, "cassette_teardown"): self.cassette_teardown(cassette=cassette_int) return return_value setattr(cassette_setup_inner, REQURE_CASSETTE_ATTRIBUTE_NAME, cassette_int) setattr(cassette_setup_inner, REQURE_SETUP_APPLIED_ATTRIBUTE_NAME, True) return cassette_setup_inner
def recording( what: str, decorate: Optional[Union[List[Callable], Callable]] = None, replace: Optional[Callable] = None, storage_file: Optional[str] = None, storage_keys_strategy=StorageKeysInspectSimple, ): """ Context manager which can be used to store calls of the function and and replay responses on the next run. :param what: str - full path of function inside module :param decorate: function decorator what will be applied to what, could be also list of decorators, to be able to apply more decorators on one function eg. store files and store output :param replace: replace original function by given one :param storage_file: path for storage file if you don't want to use default location :param storage_keys_strategy: you can change key strategy for storing data default simple one avoid to store stack information """ cassette = Cassette() cassette.storage_file = storage_file cassette.data_miner.key_stategy_cls = storage_keys_strategy # ensure that directory structure exists already os.makedirs(os.path.dirname(cassette.storage_file), exist_ok=True) # use default decorator for context manager if not given. if decorate is None and replace is None: logger.info(f"Using default decorator for {what}") decorate = Guess.decorator_plain(cassette=cassette) elif decorate is not None and replace is not None: raise ValueError( "right one from [decorate, replace] parameter has to be set.") # Store values and their replacements for modules to be able to _revert_modules changes back module_list = _parse_and_replace_sys_modules(what=what, cassette=cassette, decorate=decorate, replace=replace) try: yield cassette finally: # dump data to storage file cassette.dump() _revert_modules(module_list)
def replace_decorator(func): func_cassette = (getattr( func, REQURE_CASSETTE_ATTRIBUTE_NAME) if hasattr( func, REQURE_CASSETTE_ATTRIBUTE_NAME) else None) cassette_int = cassette or func_cassette or Cassette() @functools.wraps(func) def _replaced_function(*args, **kwargs): # set storage if not set to default one, based on function name if cassette_int.storage_file is None: change_storage_file(cassette=cassette_int, func=func, args=args) cassette_int.data_miner.key_stategy_cls = storage_keys_strategy # ensure that directory structure exists already os.makedirs(os.path.dirname(cassette_int.storage_file), exist_ok=True) # Store values and their replacements for modules # to be able to _revert_modules changes back module_list = _parse_and_replace_sys_modules(what=what, cassette=cassette_int, decorate=decorate, replace=replace) try: # pass current cassette to underneath decorator and do not overwrite if set there if ("cassette" in inspect.getfullargspec(func).annotations and inspect.getfullargspec(func).annotations["cassette"] == Cassette and "cassette" not in kwargs): kwargs["cassette"] = cassette_int # execute content output = func(*args, **kwargs) except Exception as e: raise (e) finally: # dump data to storage file cassette_int.dump() _revert_modules(module_list) return output setattr(_replaced_function, REQURE_CASSETTE_ATTRIBUTE_NAME, cassette_int) return _replaced_function
def _pr_comments_test(self): token = os.environ.get("GITHUB_TOKEN") cassette = Cassette() if cassette.mode == StorageMode.write and (not token): raise EnvironmentError( f"You are in Requre write mode, please set proper GITHUB_TOKEN" f" env variables {cassette.storage_file}") # possible to check before reading values because in other case values are removed # and in write mode is does have sense at the end if cassette.mode == StorageMode.read: self.assertIn(self.id(), cassette.storage_file) self.assertIn("LGTM", str(cassette.storage_object)) self.assertTrue( cassette.storage_object["requests.sessions"]["send"]["GET"] ["https://api.github.com:443/repos/packit-service/ogr"]) service = GithubService(token=token) ogr_project = service.get_project(namespace="packit-service", repo="ogr") pr_comments = ogr_project.get_pr_comments(9) assert pr_comments assert len(pr_comments) == 2 assert pr_comments[0].body.endswith("fixed") assert pr_comments[1].body.startswith("LGTM")
def __init__(self): super().__init__() self.cassette = Cassette()
from requre.helpers.files import StoreFiles from requre.cassette import Cassette from tempfile import mkdtemp import os cassette = Cassette() cassette.storage_file = "/tmp/files.yaml" temp_dir = mkdtemp() @StoreFiles.where_arg_references(key_position_params_dict={"dir_name": 0}, cassette=cassette) def return_result(dir_name): file_name = input("enter file name: ") with open(os.path.join(dir_name, file_name), "w") as fd: fd.write("empty") return file_name print("returned file name:", return_result(temp_dir)) print("dir name (current):", temp_dir) print("files:", os.listdir(temp_dir)) cassette.dump()
) @replace_module_match(what="math.sin", decorate=Simple.decorator(item_list=[])) def testReadMultiple(self, cassette: Cassette): assert cassette if cassette.mode == StorageMode.write: self.reset() sin_output = math.sin(1.5) else: sin_output = math.sin(4) response = requests.get("http://example.com") self.assertIn("This domain is for use", response.text) self.assertAlmostEqual(0.9974949866040544, sin_output, delta=0.0005) new_cassette = Cassette() @apply_decorator_to_all_methods( replace_module_match(what="math.sin", decorate=Simple.decorator_plain(), cassette=new_cassette)) @record_requests(cassette=new_cassette) class DecoratorClassApply(unittest.TestCase): # when regeneration, comment lines with assert equals, because checks for equality does not work def setUp(self): new_cassette.storage_file = None def test0(self, cassette: Cassette): if cassette.mode == StorageMode.read: self.assertEqual(len(new_cassette.storage_object["math"]["sin"]),