From 54beee6333d1a244f3b6e2625e61dd59e75c77e4 Mon Sep 17 00:00:00 2001 From: gaogaotiantian Date: Thu, 28 Apr 2022 22:02:05 -0700 Subject: [PATCH] Update docs and tests for attr_pattern (#66) --- README.md | 23 +++++++++++++++++++---- tests/test_objprint.py | 8 ++++++++ tests/test_objstr.py | 9 +++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 29424ad..1d45aa0 100644 --- a/README.md +++ b/README.md @@ -239,10 +239,22 @@ Or you can use it for ``op()`` functions individually with some conditions op(obj, enable=check_do_print()) ``` -### include/exclude attributes +### attribute selection -You can include/exclude attributes using regular expression so ```objprint``` will only print -out the attributes you are interested in. +You can customize which attribute to print with name filters. + +``objprint`` will try to match the attribute name with ``attr_pattern`` regex. The default +``attr_pattern`` is ``r"(!_).*"``, which means anything that does NOT start with an `_`. + +You can customize ``attr_pattern`` to select the attributes you want to print: + +```python +# This will print all the attributes that do not start with __ +op(Player(), attr_pattern=r"(!__).*") +``` + +You can also use ``include`` and ``exclude`` to specify attributes to print with regular expression +so ```objprint``` will only print out the attributes you are interested in. ```python op(Player(), include=["name"]) @@ -271,7 +283,7 @@ op(Player(), exclude=[".*s"]) If you specify both ``include`` and ``exclude``, it will do a inclusive check first, then filter out the attributes that match exclusive check. -```include``` and ```exclude``` arguments work on ```objprint```, ```objstr``` and ```@add_objprint```. +```attr_pattern```, ```include``` and ```exclude``` arguments work on ```objprint```, ```objstr``` and ```@add_objprint```. ### config @@ -288,6 +300,9 @@ that match exclusive check. * ``arg_name(False)`` - whether to print the argument expression before the argument value * ``skip_recursion(True)`` - whether skip printing recursive data, which would cause infinite recursion without ``depth`` constraint * ``honor_existing(True)`` - whether to use the existing user defined ``__repr__`` or ``__str__`` method +* ``attr_pattern(r"(!_).*")`` - the regex pattern for attribute selection +* ``include([])`` - the list of attribute regex to do an inclusive filter +* ``exclude([])`` - the list of attribute regex to do an exclusive filter You can set the configs globally using ``config`` function diff --git a/tests/test_objprint.py b/tests/test_objprint.py index 22fc714..580cfbe 100644 --- a/tests/test_objprint.py +++ b/tests/test_objprint.py @@ -189,6 +189,14 @@ def test_arg_name(self): output = buf.getvalue() self.assertIn("Unknown", output.split("\n")[0]) + def test_config_attr_pattern(self): + with io.StringIO() as buf, redirect_stdout(buf): + obj = ObjTest({"elem1": 1, "elem2": 2, "attr3": 3}) + op(obj, indent=1, attr_pattern=r"elem.") + output = buf.getvalue() + expected = r"\n" + self.assertRegex(output, expected) + def test_config_include(self): with io.StringIO() as buf, redirect_stdout(buf): obj = ObjTest({"elem1": 1, "elem2": 2, "elem3": 3}) diff --git a/tests/test_objstr.py b/tests/test_objstr.py index 170ab02..d9687a9 100644 --- a/tests/test_objstr.py +++ b/tests/test_objstr.py @@ -59,6 +59,15 @@ def test_id(self): self.assertIn(hex(obj_id), objstr(obj, color=True)) self.assertIn(hex(obj_id), objstr(obj, color=False)) + def test_attr_pattern(self): + t = ObjTest({"pos1": "in", "pos2": "out", "other3": "ex"}) + output = objstr(t, attr_pattern=r"pos.") + self.assertIn("pos1", output) + self.assertIn("pos2", output) + self.assertNotIn("other3", output) + with self.assertRaises(TypeError): + output = objstr(t, attr_pattern=[r"pos."]) + def test_include(self): t = ObjTest({"pos1": "in", "pos2": "out", "pos3": "ex"}) output = objstr(t, include=['pos1'])