Recording decorators & Filter formats¶
There are two types of decorators, be aware to not mix these.
- Decorators for modification of loaded libraries - These decorators are in online_replacing and modules_decorate_all_methods files.
- Shortcut of decorators for some sets applicable to the whole class.
- Class decorators - Apply replacements decorators to all methods.
- Method decorators - Apply replacements decorators to the method.
- Replacement decorators wokflow - These decorators are part of helpers subdirectory and objects file where is the base class with main implementation.
- Decorators for functions what should be modified (basic unit for working with object storage)
Class decorators¶
There are shortcuts for decorating the whole class by decorators for tests methods. You can define also setup and teardown methods for cassette as callback methods:
cassette_setup(self, cassette)
- Setup cassette before test execution. It is executed afterself.setUp
method of unittest.cassette_teardown(self, cassette)
- Tear down method for cassette after test execution. It is executed beforeself.tearDown
method of unittest.
Generic usage¶
It applies selected decorator to all methods of class. Structure is:
- class decorator - apply_decorator_to_all_methods - Applies argument to all test methods (
test.*
).- type of matching - replace_module_match - Decorates already loaded modules via modify of
sys.modules
- what will be decorated -
math.sin
- Which module method will be decorated.- decorated by -
Simple.decorator_plain()
- This is the decorator for selected method in module.
@apply_decorator_to_all_methods(
replace_module_match(
what="math.sin", decorate=Simple.decorator_plain()
)
)
Shortcuts for selected modules¶
The most user-friendly way how to work with requre, but just some modules or their parts are handled by these (focused on usage requre in packit projects).
They are stored in requre/modules_decorate_all_methods.py
file.
- record_tempfile_module - Workaround random file names via tempfile module. It changes it to use predictable names.
- record_git_module - The git module handling, it allows to restore remote git operations like fetch, push, pull.
- record_requests_module - Store all remote operations via requests module, it changes
requests.Session.send
method, so it should be very generic.
Test methods decorators¶
These decorators apply a decorator to the test method.
class Test(unittest.TestCase):
@replace_module_match(
what="requests.sessions.Session.request",
decorate=RequestResponseHandling.decorator(item_list=["method", "url"]),
)
def test(self):
response = requests.get("http://example.com")
self.assertIn("This domain is for use", response.text)
Filters for transparent mode¶
This filters are used for transparent mode as part of improved import system, also deprecated usage for normal tests. The file could look like:
from requre.import_system import UpgradeImportSystem
from requre.helpers.simple_object import Simple
FILTERS = UpgradeImportSystem().decorate("time.sleep", Simple.decorator_plain())
Customization rules¶
from requre import decorate
from requre.helpers.requests import RequestResponseHandling
decorate("Session.send", RequestResponseHandling.decorator_plain())
It says
- What to replace
- Which decorator/replacements to use for the method
- What to replace:
Session.send
- There is used
"."
syntax to deep dive into object/module model. In this example, it means in full sense decoratesend
method ofSession
class inrequests
module
- What to replace:
- Object to be used:
RequestResponseHandling.decorator_plain()
- It is function/object/method to be applied as decorator for
Session.send
.
- Object to be used:
Filter object model¶
Replacements¶
- There are two functions/methods that can be used
- decorate
- replace
Example with replace
with replace(what="tempfile.mktemp", replacement=lambda x: lambda: "/tmp/random"):
import tempfile
tmpfile = tempfile.mktemp()
assert "/tmp/random" == tmpfile
Reverting¶
Requre supports reverting import system to previous state,
when used with with
statement
- Without reverting
- Usage without reverting back
replace(what="tempfile.mktemp", replacement=lambda x: "/tmp/random")
import tempfile
tmpfile = tempfile.mktemp()
- With reverting
- when used
with
statement import system is returned to previous state
with replace(what="tempfile.mktemp", replacement=lambda x: "/tmp/random"):
import tempfile
tmpfile = tempfile.mktemp()
assert "/tmp/random" == tmpfile
Chaining of operations¶
with replace(what="tempfile.mktemp", replacement=lambda x: "/tmp/random").\
decorate(what="tempfile.mkdtemp", replacement=lambda x: lambda: os.makedirs("/tmp/randomdir"))
):
import tempfile
tmpfile = tempfile.mktemp()
tempdir = tempfile.mkdtemp()