Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,19 @@ R.equals(float('nan'), float('nan')) # True
- [ ] groupWith
- [x] 0.1.2 gt
- [x] 0.1.2 gte
- [ ] has
- [x] has

Similar to `hasPath`.

- [ ] hasIn
- [x] hasPath

Support both dict and object.

```python

R.hasPath(['a', 'b'], {'a': {'b': 42}}) # True

class Obj:
def __init__(self, v):
self.v = v
Expand All @@ -251,11 +257,11 @@ R.hasPath(['v', 'child'], obj) # False
R.hasPath(['v'], {'v': 1}) # True
R.hasPath(['v', 'child'], {'v': 1}) # False

# Also support static variable
# Does not include static variable
class Obj:
v = 1
obj = Obj()
R.hasPath(['v'], obj) # True
R.hasPath(['v'], obj) # False

# Also support inherited variable
class Parent:
Expand All @@ -270,8 +276,6 @@ R.hasPath(['a'], child) # True
R.hasPath(['b'], child) # True
```

````

- [x] 0.1.2 head
- [ ] identical
- [x] 0.1.2 identity
Expand Down Expand Up @@ -337,6 +341,8 @@ this is for checking if the given value is None or not.
- [x] 0.1.4 juxt
- [x] 0.1.2 keys

For object, `keys` does not return object's methods.

```python
# When using R.keys(obj) and obj is a class instance, we use obj.__dict__ as keys.
class A:
Expand Down Expand Up @@ -376,6 +382,8 @@ R.keys({'a': 1, 'b': 2}) # ['a', 'b']

- [x] 0.2.0 keysIn

For object, `keysIn` does not return object's methods.

Different from `keys`, `keysIn` will return all attributes of the object, including super class attributes and class static variables.

```python
Expand Down
1 change: 1 addition & 0 deletions ramda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from .groupBy import groupBy
from .gt import gt
from .gte import gte
from .has import has
from .hasPath import hasPath
from .head import head
from .identity import identity
Expand Down
4 changes: 4 additions & 0 deletions ramda/has.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .hasPath import hasPath
from .private._curry2 import _curry2

has = _curry2(lambda prop, obj: hasPath([prop], obj))
4 changes: 2 additions & 2 deletions ramda/hasPath.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .isNil import isNil
from .private._curry2 import _curry2
from .private._has import _has
from .private._hasOwn import _hasOwn
from .private._helper import getAttribute


Expand All @@ -10,7 +10,7 @@ def inner_hasPath(path, obj):
val = obj
idx = 0
while idx < len(path):
if not isNil(val) and _has(val, path[idx]):
if not isNil(val) and _hasOwn(val, path[idx]):
val = getAttribute(val, path[idx])
idx += 1
else:
Expand Down
14 changes: 14 additions & 0 deletions ramda/private/_hasOwn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from ._isArrayLike import _isArrayLike


def _hasOwn(obj, prop):
if prop is None:
return isinstance(obj, dict) and prop in obj
if isinstance(obj, dict):
return prop in obj
if _isArrayLike(obj):
if isinstance(prop, int):
return prop < len(obj)
if hasattr(obj, '__dict__'):
return prop in obj.__dict__
return False
55 changes: 55 additions & 0 deletions test/private/test__has.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import unittest

from ramda.private._has import _has


class Test_has(unittest.TestCase):
def test_array(self):
self.assertEqual(False, _has([], 0))
self.assertEqual(True, _has([1, 2, 3], 0))
self.assertEqual(True, _has([1, 2, 3], 1))
self.assertEqual(True, _has([1, 2, 3], 2))
self.assertEqual(False, _has([1, 2, 3], 3))

def test_dict(self):
self.assertEqual(False, _has({}, 'a'))
self.assertEqual(True, _has({'a': False, 'b': {'c': 1}}, 'a'))
self.assertEqual(False, _has({'a': False, 'b': {'c': 1}}, 'c')) # do not support nested dict
self.assertEqual(True, _has({'a': False, 'b': {'c': 1}}, 'get')) # do not check method

def test_object(self):
class Parent:
c = 'parent static'

def __init__(self):
self.d = 'parent instance'

def foo(self):
return 'parent method'

class Obj(Parent):
a = 'static'

def __init__(self, b):
super().__init__()
self.b = b

def bar(self):
return 'obj method'

obj = Obj('b')

self.assertEqual(True, _has(obj, 'a'))
self.assertEqual(True, _has(obj, 'b'))
self.assertEqual(True, _has(obj, 'c'))
self.assertEqual(True, _has(obj, 'd'))
self.assertEqual(True, _has(obj, 'foo'))
self.assertEqual(True, _has(obj, 'bar'))

def test_if_key_is_none(self):
self.assertEqual(True, _has({None: False}, None))
self.assertEqual(False, _has({'None': True}, None))


if __name__ == '__main__':
unittest.main()
55 changes: 55 additions & 0 deletions test/private/test__hasOwn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import unittest

from ramda.private._hasOwn import _hasOwn


class Test_HasOwn(unittest.TestCase):
def test_array(self):
self.assertEqual(False, _hasOwn([], 0))
self.assertEqual(True, _hasOwn([1, 2, 3], 0))
self.assertEqual(True, _hasOwn([1, 2, 3], 1))
self.assertEqual(True, _hasOwn([1, 2, 3], 2))
self.assertEqual(False, _hasOwn([1, 2, 3], 3))

def test_dict(self):
self.assertEqual(False, _hasOwn({}, 'a'))
self.assertEqual(True, _hasOwn({'a': False, 'b': {'c': 1}}, 'a'))
self.assertEqual(False, _hasOwn({'a': False, 'b': {'c': 1}}, 'c')) # do not support nested dict
self.assertEqual(False, _hasOwn({'a': False, 'b': {'c': 1}}, 'get')) # do not check method

def test_object(self):
class Parent:
c = 'parent static'

def __init__(self):
self.d = 'parent instance'

def foo(self):
return 'parent method'

class Obj(Parent):
a = 'static'

def __init__(self, b):
super().__init__()
self.b = b

def bar(self):
return 'obj method'

obj = Obj('b')

self.assertEqual(False, _hasOwn(obj, 'a'))
self.assertEqual(True, _hasOwn(obj, 'b'))
self.assertEqual(False, _hasOwn(obj, 'c'))
self.assertEqual(True, _hasOwn(obj, 'd'))
self.assertEqual(False, _hasOwn(obj, 'foo'))
self.assertEqual(False, _hasOwn(obj, 'bar'))

def test_if_key_is_none(self):
self.assertEqual(True, _hasOwn({None: False}, None))
self.assertEqual(False, _hasOwn({'None': True}, None))


if __name__ == '__main__':
unittest.main()
67 changes: 67 additions & 0 deletions test/test_has.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@

import unittest

import ramda as R

"""
https://github.com/ramda/ramda/blob/master/test/has.js
"""

dictFred = {'name': 'Fred', 'age': 23}
dictAnon = {'age': 99}


class Fred:
def __init__(self):
self.name = 'Fred'
self.age = 23


class Anon:
def __init__(self):
self.age = 99


fred = Fred()
anon = Anon()


class TestHasForDict(unittest.TestCase):
def test_returns_true_if_the_specified_property_is_present(self):
self.assertEqual(True, R.has('name', dictFred))

def test_returns_false_if_the_specified_property_is_absent(self):
self.assertEqual(False, R.has('name', dictAnon))


class TestHasForObject(unittest.TestCase):
def test_returns_true_if_the_specified_property_is_present(self):
self.assertEqual(True, R.has('name', fred))

def test_returns_false_if_the_specified_property_is_absent(self):
self.assertEqual(False, R.has('name', anon))


class TestHasForOthers(unittest.TestCase):
def test_does_not_check_static(self):
class Person:
static_var = 'static'
def __init__(self):
self.name = 'bob'
bob = Person()

self.assertEqual(True, R.has('name', bob))
self.assertEqual(False, R.has('static_var', bob))

def test_returns_false_for_non_objects(self):
self.assertEqual(False, R.has('a', None))
self.assertEqual(False, R.has('a', True))
self.assertEqual(False, R.has('a', False))
self.assertEqual(False, R.has('a', ''))

def test_currying(self):
self.assertEqual(True, R.has('a')({'a': {'b': 1}}))


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion test/test_hasPath.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def test_static_variables(self):
class A:
static_a = 'static a'
a = A()
self.assertEqual(True, R.hasPath(['static_a'], a))
self.assertEqual(False, R.hasPath(['static_a'], a))

def test_inherited_variables(self):
class Parent:
Expand Down
5 changes: 5 additions & 0 deletions test/test_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ def test_works_with_primitives(self):
self.assertEqual([], R.keys([]))
self.assertEqual([], R.keys({}))

def test_works_with_methods_properties(self):
self.assertEqual(['foo'], R.keys({'foo': lambda x: x}))

# keys does not work with methods in object


if __name__ == '__main__':
unittest.main()