diff --git a/README.md b/README.md index 0b14ea0..60a5c63 100644 --- a/README.md +++ b/README.md @@ -237,9 +237,21 @@ R.equals(float('nan'), float('nan')) # True Similar to `hasPath`. -- [ ] hasIn -- [x] hasPath +- [x] hasIn + +works for both dict and object +```python +class Obj: + def __init__(self, v): + self.v = v + +obj1 = Obj(1) +R.hasIn('v', obj1) # True +R.hasIn('v', {'v': 1}) # True +``` + +- [x] hasPath Support both dict and object. ```python diff --git a/ramda/__init__.py b/ramda/__init__.py index 3545346..d462584 100644 --- a/ramda/__init__.py +++ b/ramda/__init__.py @@ -43,6 +43,7 @@ from .gt import gt from .gte import gte from .has import has +from .hasIn import hasIn from .hasPath import hasPath from .head import head from .identity import identity diff --git a/ramda/hasIn.py b/ramda/hasIn.py new file mode 100644 index 0000000..b05d572 --- /dev/null +++ b/ramda/hasIn.py @@ -0,0 +1,12 @@ +from .isNil import isNil +from .private._curry2 import _curry2 +from .private._has import _has + + +def inner_hasIn(prop, obj): + if isNil(obj): + return False + return _has(obj, prop) + + +hasIn = _curry2(inner_hasIn) diff --git a/test/test_hasIn.py b/test/test_hasIn.py new file mode 100644 index 0000000..96ec856 --- /dev/null +++ b/test/test_hasIn.py @@ -0,0 +1,68 @@ + +import unittest + +import ramda as R +from ramda.private._isFunction import _isFunction + +""" +https://github.com/ramda/ramda/blob/master/test/hasIn.js +""" + +dictFred = {'name': 'Fred', 'age': 23} +dictAnon = {'age': 99} + + +class Fred: + def __init__(self, name, age): + self.name = name + self.age = age + + +class Anon: + def __init__(self, age): + self.age = age + + +fred = Fred('Fred', 23) +anon = Anon(99) + + +class TestHasInForDict(unittest.TestCase): + def test_returns_a_function_that_checks_the_appropiate_property(self): + nm = R.hasIn('name') + self.assertEqual(True, _isFunction(nm)) + self.assertEqual(True, nm(dictFred)) + self.assertEqual(False, nm(dictAnon)) + + +class TestHasInForObject(unittest.TestCase): + def test_returns_a_function_that_checks_the_appropiate_property(self): + nm = R.hasIn('name') + self.assertEqual(True, _isFunction(nm)) + self.assertEqual(True, nm(fred)) + self.assertEqual(False, nm(anon)) + + def test_checks_properties_from_parent(self): + class Person: + def __init__(self, name): + self.name = name + + class Bob(Person): + def __init__(self, name, age): + super().__init__(name) + self.age = age + bob = Bob('Bob', 23) + self.assertEqual(True, R.hasIn('name', bob)) + + +class TestHasInForOthers(unittest.TestCase): + def test_works_properly_when_called_with_two_arguments(self): + self.assertEqual(True, R.hasIn('name', fred)) + self.assertEqual(False, R.hasIn('name', anon)) + + def test_returns_false_when_non_existent_object(self): + self.assertEqual(False, R.hasIn('name', None)) + + +if __name__ == '__main__': + unittest.main()