Skip to content

Commit

Permalink
Made it so that named tuples are not wrapped by things like get item
Browse files Browse the repository at this point in the history
  • Loading branch information
EntilZha committed Nov 10, 2015
1 parent 1c0dc93 commit 924eb19
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
### Internal Changes
* Changed all relative imports to absolute imports with `__future__.absolute_import`

### Bug Fixes
* Fixed case where `_wrap` is changing named tuples to arrays when it should preserve them

## Release 0.4.1
Fix python 3 build error due to wheel installation of enum34. Package no longer depends on enum34

Expand Down
4 changes: 2 additions & 2 deletions functional/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import future.builtins as builtins

from functional.lineage import Lineage
from functional.util import is_iterable, is_primitive, identity, CSV_WRITE_MODE
from functional.util import is_iterable, is_primitive, is_namedtuple, identity, CSV_WRITE_MODE
from functional import transformations


Expand Down Expand Up @@ -1436,7 +1436,7 @@ def _wrap(value):
"""
if is_primitive(value):
return value
if isinstance(value, dict) or isinstance(value, set):
if isinstance(value, dict) or isinstance(value, set) or is_namedtuple(value):
return value
elif isinstance(value, collections.Iterable):
return Sequence(value)
Expand Down
5 changes: 3 additions & 2 deletions functional/test/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,8 +710,9 @@ def test_wrap(self):
self.assert_type(_wrap((1, 2)))
self.assert_not_type(_wrap(1))
self.assert_not_type(_wrap(1.0))
self.assert_not_type("test")
self.assert_not_type(True)
self.assert_not_type(_wrap("test"))
self.assert_not_type(_wrap(True))
self.assert_not_type(_wrap(Data(1, 2)))

def test_wrap_objects(self):
class A(object):
Expand Down
12 changes: 11 additions & 1 deletion functional/test/test_util.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from __future__ import absolute_import

import unittest
from functional.util import ReusableFile
from collections import namedtuple

from functional.util import ReusableFile, is_namedtuple

Data = namedtuple('Tuple', 'x y')


class TestUtil(unittest.TestCase):
Expand All @@ -12,3 +16,9 @@ def test_reusable_file(self):
iter_1 = iter(license_file_lf)
iter_2 = iter(license_file_lf)
self.assertEqual(list(iter_1), list(iter_2))

def test_is_namedtuple(self):
self.assertTrue(is_namedtuple(Data(1, 2)))
self.assertFalse(is_namedtuple((1, 2, 3)))
self.assertFalse(is_namedtuple([1, 2, 3]))
self.assertFalse(is_namedtuple(1))
17 changes: 17 additions & 0 deletions functional/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ def is_primitive(val):
or isinstance(val, bytes)


def is_namedtuple(val):
"""
Use Duck Typing to check if val is a named tuple. Checks that val is of type tuple and contains
the attribute _fields which is defined for named tuples.
:param val: value to check type of
:return: True if val is a namedtuple
"""
val_type = type(val)
bases = val_type.__bases__
if len(bases) != 1 or bases[0] != tuple:
return False
fields = getattr(val_type, '_fields', None)
if not isinstance(fields, tuple):
return False
return all(isinstance(n, str) for n in fields)


def identity(arg):
"""
Function which returns the argument. Used as a default lambda function.
Expand Down

0 comments on commit 924eb19

Please sign in to comment.