diff --git a/functional/chain.py b/functional/chain.py index 72016c5..3c90a82 100644 --- a/functional/chain.py +++ b/functional/chain.py @@ -41,6 +41,16 @@ def _get_base_sequence(self): else: return self.sequence + def __getattr__(self, item): + """ + Extends attribute access to any attributes that the underlying sequence may have. Since + __getattr__ is used instead of __getattribute__, attributes in FunctionalSequence take precedent + + :param item: attribute to get + :return: either result of getting the item attribute from the sequence or an error + """ + return getattr(self.sequence, item) + def __eq__(self, other): """ Checks for equality with the sequence's equality operator diff --git a/test/test_functional.py b/test/test_functional.py index e62e17e..51ca562 100644 --- a/test/test_functional.py +++ b/test/test_functional.py @@ -1,4 +1,5 @@ import unittest +from collections import namedtuple from functional.chain import seq, FunctionalSequence, _wrap @@ -17,6 +18,15 @@ def test_base_sequence(self): self.assertType(seq(seq(l))) self.assertNotType(seq(seq(l)).sequence) + def test_get_attr(self): + CustomTuple = namedtuple("CustomTuple", 'x y') + t = CustomTuple(1, 2) + s = seq(t) + self.assertType(s) + self.assertEqual(s.sum(), 3) + self.assertEqual(s.x, 1) + self.assertEqual(s.y, 2) + def test_eq(self): l = [1, 2, 3] self.assertEqual(seq(l), seq(l))