Repository: dunossauro/splitty

Issue:
Regex support on find_elements
`find_elements` function works only in full match case.

```Python
>>> list_to_be_splited = ['spam', 1, 2, 3, 'eggs', 1, 2, 3, 'foo', 1, 2, 3]
>>> split_by = ['spam', 'eggs', 'foo']

>>> splited = find_elements(list_to_be_splited, split_by)
# [(0, 'spam'), (4, 'eggs'), (8, 'foo')]
```
And `list_by_re_pattern` matches one regex.

In my opinion using splitty yesterday with @rg3915, we saw a dependency. Something like that:

```
root      1978  0.2  0.8 1534468 69680 ?       Ssl  09:12   0:01 /usr/bin/dockerd -H fd://
root      2141  0.1  0.4 1244864 34892 ?       Ssl  09:12   0:01 docker-containerd --config /var/run/docker/containerd/containerd.toml
root      2706  0.0  0.0 379496  3832 ?        Sl   09:12   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5432 -container-ip 192.202.112.2
...
eduardo+  6136  0.0  0.0  14440  1108 pts/0    S+   09:24   0:00 grep --color=auto docker
```

If i need catch all docker process intervals, or we list all docker commands or create a biggest regex.

in that case it would be simpler a basix expression in list_by_list:

```Python
>>> list_to_be_splited = '''
root      1978  0.2  0.8 1534468 69680 ?       Ssl  09:12   0:01 /usr/bin/dockerd -H fd://
root      2141  0.1  0.4 1244864 34892 ?       Ssl  09:12   0:01 docker-containerd --config /var/run/docker/containerd/containerd.toml
root      2706  0.0  0.0 379496  3832 ?        Sl   09:12   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5432 -container-ip 192.202.112.2
...
eduardo+  6136  0.0  0.0  14440  1108 pts/0    S+   09:24   0:00 grep --color=auto docker
'''

>>> split_by = [r'/usr/bin/docker-\w+, r' /var/run/docker/.+\.toml', 'foo', 'bar']
```

Discussion:

Patch:
diff --git a/pylava.ini b/pylava.ini
index 1c20fd4..a52bd1d 100644
--- a/pylava.ini
+++ b/pylava.ini
@@ -5,8 +5,5 @@ linters=pep8,pep257,pyflakes
 [pylava:pep8]
 max_line_length = 80
 
-[pylava:*/__init__.py]
-ignore=D104
-
 [pylava:*/test_*]
 ignore=D100,D101,D102
diff --git a/splitty/__init__.py b/splitty/__init__.py
index c200706..6355269 100644
--- a/splitty/__init__.py
+++ b/splitty/__init__.py
@@ -1,1 +1,24 @@
-from .splitty import *  # NOQA
+"""
+Splitty.
+
+Functional approach to work with iterables in python
+"""
+from .splitty import (
+    clear_list_strings,
+    list_by_list,
+    list_by_re_pattern,
+    find_elements,
+    make_intervals,
+    apply_intervals,
+    chunks,
+)
+
+__all__ = [
+    'clear_list_strings',
+    'list_by_list',
+    'list_by_re_pattern',
+    'find_elements',
+    'make_intervals',
+    'apply_intervals',
+    'chunks',
+]
diff --git a/splitty/splitty.py b/splitty/splitty.py
index 959eb91..c8dff52 100644
--- a/splitty/splitty.py
+++ b/splitty/splitty.py
@@ -4,6 +4,8 @@ Splitty.
 Functional approach to work with iterables in python
 """
 from re import match
+from functools import singledispatch
+from numbers import Number
 
 
 def clear_list_strings(strings: list) -> list:
@@ -41,6 +43,45 @@ def list_by_list(list_with_elements: list,
                                              list_with_intervals), start))
 
 
+@singledispatch
+def nun_or_match(matcher, element):
+    r"""
+    Discover if matcher ir a Number or String and match then.
+
+    >>> nun_or_match(7, 7)
+    True
+
+    >>> nun_or_match('\w+', 'Hello')
+    <re.Match object; span=(0, 5), match='Hello'>
+
+    >>> nun_or_match('spam', 'spam')
+    <re.Match object; span=(0, 4), match='spam'>
+    """
+    ...
+
+
+@nun_or_match.register(str)
+def str_eq(matcher, element):
+    r"""
+    Match strings or regex using re.match, called by nun_or_match.
+
+    >>> nun_or_match('\w+', 'Hello')
+    <re.Match object; span=(0, 5), match='Hello'>
+    """
+    return match(matcher, str(element))
+
+
+@nun_or_match.register(Number)
+def number_eq(matcher, element):
+    r"""
+    Match numbers , called by nun_or_match.
+
+    >>> nun_or_match(7, 7)
+    True
+    """
+    return matcher == element
+
+
 def find_elements(full_list: list, list_with_values: list) -> list:
     """
     Find occurrences in a list and make a index related.
@@ -50,7 +91,7 @@ def find_elements(full_list: list, list_with_values: list) -> list:
     """
     return [(x, val) for x, val in enumerate(full_list)
             for y in list_with_values
-            if y == val]
+            if nun_or_match(y, val)]
 
 
 def list_by_re_pattern(list_to_be_splited: list,


Test patch:
diff --git a/tests/test_splitty.py b/tests/test_splitty.py
index 7e2c4f8..683f5bd 100644
--- a/tests/test_splitty.py
+++ b/tests/test_splitty.py
@@ -4,16 +4,65 @@ from unittest import TestCase, main
 from splitty import *  # NOQA
 
 
+class TestInit(TestCase):
+    def test_module_shouldnt_call_functions_out_all(self):
+        import splitty
+        with self.assertRaises(AttributeError):
+            splitty.nun_or_match()
+
+
+class TestNunOrMatch(TestCase):
+    def setUp(self):
+        from splitty.splitty import nun_or_match
+        self.nom = nun_or_match
+
+    def test_num_or_match_should_return_True_when_mach_same_number(self):
+        self.assertTrue(self.nom(7, 7))
+
+    def test_num_or_match_should_return_False_when_mach_different_number(self):
+        self.assertFalse(self.nom(7, 8))
+
+    def test_num_or_match_should_return_regex_match_when_compare_strings(self):
+        import re
+        self.assertIsInstance(self.nom('sa', 'sa'), re.Match)
+
+    def test_num_or_match_should_return_regex_match_when_non_match_regex(self):
+        self.assertIsNone(self.nom('sa', 's1a'))
+
+
 class TestFindListElements(TestCase):
-    def test_find_list_elements(self):
+    def test_find_list_should_return_positions_and_strings(self):
         split_by = ['spam', 'eggs', 'foo']
-        list_to_be_splited = ['spam', 1, 2, 3,
-                              'eggs', 1, 2, 3,
-                              'foo', 1, 2, 3]
-
+        list_to_be_splited = [
+            'spam', 1, 2, 3,
+            'eggs', 1, 2, 3,
+            'foo', 1, 2, 3
+        ]
         self.assertEqual(find_elements(list_to_be_splited, split_by),
                          [(0, 'spam'), (4, 'eggs'), (8, 'foo')])
 
+    def test_find_list_should_return_positions_and_strings_with_regex(self):
+        split_by = [r'spa\w', r'\wggs', r'f\wo', r'b.r']
+        list_to_be_splited = [
+            'spam', 1, 2, 3,
+            'eggs', 1, 2, 3,
+            'foo', 1, 2, 3,
+            'bar', 1, 2, 3
+        ]
+        self.assertEqual(find_elements(list_to_be_splited, split_by),
+                         [(0, 'spam'), (4, 'eggs'), (8, 'foo'), (12, 'bar')])
+
+    def test_find_list_should_return_positions_and_strings_with_mixin_regex_and_string(self):
+        split_by = [r'spa\w', 'eggs', r'f\wo', 'bar']
+        list_to_be_splited = [
+            'spam', 1, 2, 3,
+            'eggs', 1, 2, 3,
+            'foo', 1, 2, 3,
+            'bar', 1, 2, 3
+        ]
+        self.assertEqual(find_elements(list_to_be_splited, split_by),
+                         [(0, 'spam'), (4, 'eggs'), (8, 'foo'), (12, 'bar')])
+
     def test_should_be_blank_list_if_splited_by_blank_list(self):
         list_to_be_splited = ['spam', 1, 2, 3,
                               'eggs', 1, 2, 3,
@@ -135,7 +184,3 @@ class TestClearListString(TestCase):
         _list = ['\r\nHello', 'how', '\r', 'r', 'u\n', '\r']
         expected = ['Hello', 'how', 'r', 'u']
         self.assertEqual(clear_list_strings(_list), expected)
-
-
-if __name__ == '__main__':
-    main()