Пример #1
0
 def _copy_logic(
     cls,
     cassette: Cassette,
     pathname: str,
     keys: list,
     ret_store_cls: Any,
     return_value: Any,
 ) -> Any:
     """
     Internal function. Copy files to or back from persisten storage
     It will create tar archive with tar_compression and stores it to Persistent Storage
     """
     FILENAME = "filename"
     TARGET_PATH = "target_path"
     RETURNED = "return_value"
     serialization = ret_store_cls(store_keys=["not_important"],
                                   cassette=cassette)
     logger.debug(f"Copy files {pathname} -> {keys}")
     logger.debug(f"Persistent Storage mode: {cassette.mode}")
     original_cwd = os.getcwd()
     if cassette.do_store(keys=cls.basic_ps_keys + keys):
         try:
             artifact_name = os.path.basename(pathname)
             artifact_path = os.path.dirname(pathname)
             os.chdir(artifact_path)
             with BytesIO() as fileobj:
                 with tarfile.open(mode=f"x:{cls.tar_compression}",
                                   fileobj=fileobj) as tar_store:
                     tar_store.add(name=artifact_name)
                 metadata = {cassette.data_miner.LATENCY_KEY: 0}
                 file_name = cls.store_file_content(
                     cassette=cassette,
                     file_name=os.path.basename(pathname),
                     content=fileobj.getvalue(),
                 )
                 serialized = serialization.to_serializable(return_value)
                 output = {
                     FILENAME: file_name,
                     RETURNED: serialized,
                     TARGET_PATH: pathname,
                 }
                 cassette.store(
                     keys=cls.basic_ps_keys + keys,
                     values=output,
                     metadata=metadata,
                 )
         finally:
             os.chdir(original_cwd)
     else:
         output = cassette[cls.basic_ps_keys + keys]
         pathname = pathname or output[RETURNED]
         content = cls.read_file_content(cassette=cassette,
                                         file_name=output[FILENAME])
         # WORKAROUND: some parts expects old dir and some new one. so copy to both to ensure.
         # mainly when creating complex objects.
         for item in [pathname, output[TARGET_PATH]]:
             cls.__write_file(content, item)
         return_value = serialization.from_serializable(output[RETURNED])
     return return_value
Пример #2
0
 def testWrite(self, cassette: Cassette):
     self.reset()
     response = requests.get("http://example.com")
     self.assertIn("This domain is for use", response.text)
     self.assertFalse(os.path.exists(cassette.storage_file))
     cassette.dump()
     self.assertTrue(os.path.exists(cassette.storage_file))
     os.remove(cassette.storage_file)
    def test_regex_write(self, cassette: Cassette):
        self.assertIsNotNone(cassette)

        self.use_requests()

        self.assertIn("requests.sessions", cassette.storage_object)

        self.assertFalse(Path(cassette.storage_file).exists())
        cassette.dump()
        self.assertTrue(Path(cassette.storage_file).exists())
        Path(cassette.storage_file).unlink()
    def test_write(self, cassette: Cassette):
        self.assertIsNotNone(cassette)
        self.assertEqual(self.count_cassette_setup_triggered, 1)
        self.assertEqual(self.count_cassette_teardown_triggered, 0)

        self.use_requests()

        self.assertIn("requests.sessions", cassette.storage_object)

        self.assertFalse(Path(cassette.storage_file).exists())
        cassette.dump()
        self.assertTrue(Path(cassette.storage_file).exists())
        Path(cassette.storage_file).unlink()
Пример #5
0
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
Пример #6
0
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)
Пример #7
0
def change_storage_file(cassette: Cassette,
                        func,
                        args,
                        storage_file: Optional[str] = None):
    """
    Internal function that try to construct persistent data file based on various
    possibilities.

    :param cassette: Cassette instance to pass inside object to work with
    """
    if storage_file:
        cassette.storage_file = storage_file
    else:
        if len(args):
            try:
                cassette.storage_file = get_datafile_filename(args[0])
            except NameError:
                cassette.storage_file = get_datafile_filename(func)
        else:
            cassette.storage_file = get_datafile_filename(func)
    original_storage_file = cassette.storage_file
    return original_storage_file
Пример #8
0
    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
Пример #9
0
    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")
Пример #10
0
 def __init__(self):
     super().__init__()
     self.cassette = Cassette()
Пример #11
0
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()
Пример #12
0
import tempfile
from requre.cassette import Cassette

keys = ["basic", "keys", 0.1]
value1 = {"cat": "tom", "mouse": "jerry"}
value2 = {"cat1": "pa", "cat2": "pi"}

cassette = Cassette()
cassette.storage_file = tempfile.mktemp()

cassette.store(keys, value1, metadata={})
cassette.store(keys, value2, metadata={})
cassette.dump()

cassette.storage_object = {}
cassette.load()
print(cassette.storage_object)
print(cassette.read(keys))
print(cassette.read(keys))
Пример #13
0
from requre.objects import ObjectStorage
from requre.cassette import Cassette

cassette = Cassette()


@ObjectStorage.decorator_plain(cassette=cassette)
def return_result():
    return {"value": input("insert value: ")}


cassette.storage_file = "values.yaml"
value = return_result()

cassette.dump()
print(cassette.storage_object)
print(value)
Пример #14
0
 def test_write(self, cassette: Cassette):
     cassette.storage_file = tempfile.mktemp()
     out = RetTuple().ret(1)
     self.assertEqual(out, ("ret", 1))
Пример #15
0
    )
    @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"]),