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
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,34 @@ R.equals(float('nan'), float('nan')) # True
- [ ] invert
- [ ] invertObj
- [x] 0.1.2 invoker
- [ ] is
- [x] is

This is a language specific feature.
So we check all python built-in types as many as we can.

```python
R.Is(int, 1) # True
R.Is(float, 1.0) # True
R.Is(str, '1') # True
R.Is(list, [1,2,3]) # True
R.Is(dict, {'a': 1}) # True
R.Is(set, {1,2,3}) # True
R.Is(tuple, (1,2,3)) # True
R.Is(None, None) # True
R.Is(bool, True) # True
R.Is(bool, False) # True

# For user-defined object
class Parent:
pass
class Child(Parent):
pass
R.Is(Parent, Parent()) # True
R.Is(Parent, Child()) # True
R.Is(Child, Child()) # True
R.Is(Child, Parent()) # False
```

- [x] 0.1.2 isEmpty

```python
Expand Down Expand Up @@ -413,7 +440,7 @@ Python modulo on negative numbers has different behavior than JS.
- [ ] nthArg
- [ ] o
- [x] 0.1.2 objOf
- [ ] of
- [x] of
- [x] 0.1.2 omit

we support both `dict` type and `object` type.
Expand Down
10 changes: 10 additions & 0 deletions ramda/Is.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from .private._curry2 import _curry2


def inner_is(Ctor, val):
if val is None:
return val is None
return isinstance(val, Ctor)


Is = _curry2(inner_is)
2 changes: 2 additions & 0 deletions ramda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from .intersection import intersection
from .into import into
from .invoker import invoker
from .Is import Is
from .isEmpty import isEmpty
from .join import join
from .juxt import juxt
Expand All @@ -65,6 +66,7 @@
from .Not import Not
from .nth import nth
from .objOf import objOf
from .of import of
from .omit import omit
from .once import once
from .Or import Or
Expand Down
14 changes: 14 additions & 0 deletions ramda/of.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from .private._curry2 import _curry2
from .private._helper import getAttribute
from .private._isFunction import _isFunction


def inner_of(Ctor, val):
if _isFunction(getAttribute(Ctor, 'fantasy-land/of')):
return getAttribute(Ctor, 'fantasy-land/of')(val)
if _isFunction(getAttribute(Ctor, 'of')):
return getAttribute(Ctor, 'of')(val)
return [val]


of = _curry2(inner_of)
20 changes: 16 additions & 4 deletions ramda/private/_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,20 @@ def get(self, type):
t = T()
init_fn = getAttribute(t, '@@transducer/init')

method case:
method case 1:
class Mapper:
def map(fn):
return fn
m = Mapper()
map_fn = getAttribute(m, 'map')

method case 2:
class Mapper:
def map(self, fn):
return fn
m = Mapper()
map_fn = getAttribute(m, 'map')

return: function got from key, otherwise None
"""
if isinstance(v, dict) and key in v:
Expand All @@ -54,10 +61,15 @@ def map(fn):
return getattr(v, key, None)
if _has(v, 'get'):
try:
return v.get(key, None)
# Case that get is (key, default) -> value signature
return v.get(key, default=None)
except TypeError:
# in case v has get method but with different signature
return None
try:
# Case that get is a instance method with (self, key, default) -> value signature
return v.get(v, key, default=None)
except TypeError:
# Unknown signature
return None


def safeLen(x):
Expand Down
108 changes: 108 additions & 0 deletions test/test_is.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@

import unittest

import ramda as R

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


class TestIs(unittest.TestCase):
def test_works_with_built_in_types(self):

# Numeric types
self.assertTrue(R.Is(int, 1))
self.assertTrue(R.Is(float, 1.1))
self.assertTrue(R.Is(complex, 1 + 1j))

self.assertFalse(R.Is(int, 1.1))
self.assertFalse(R.Is(float, 1))
self.assertFalse(R.Is(complex, 1))

# Sequence types
self.assertTrue(R.Is(list, []))
self.assertTrue(R.Is(tuple, ()))

self.assertTrue(R.Is(list, [1, 2, 3]))
self.assertTrue(R.Is(tuple, (1, 2, 3)))

self.assertFalse(R.Is(tuple, [1, 2, 3]))
self.assertFalse(R.Is(list, (1, 2, 3)))

# Text Sequence types
self.assertTrue(R.Is(str, ""))
self.assertTrue(R.Is(str, 'abc'))
self.assertTrue(R.Is(str, '''abc'''))
self.assertTrue(R.Is(str, u'abc'))
self.assertTrue(R.Is(str, f'abc'))
self.assertTrue(R.Is(str, r'abc'))

self.assertFalse(R.Is(str, b'abc'))

# Binary Sequence types
self.assertTrue(R.Is(bytes, b""))
self.assertTrue(R.Is(bytearray, bytearray(b"")))
self.assertTrue(R.Is(memoryview, memoryview(b"")))

# Set types
self.assertTrue(R.Is(set, set()))
self.assertTrue(R.Is(frozenset, frozenset()))

self.assertTrue(R.Is(set, set([1, 2, 3])))
self.assertTrue(R.Is(frozenset, frozenset([1, 2, 3])))

self.assertFalse(R.Is(frozenset, set([1, 2, 3])))
self.assertFalse(R.Is(set, frozenset([1, 2, 3])))

# Mapping types
self.assertTrue(R.Is(dict, {}))
self.assertTrue(R.Is(dict, {'a': 1, 'b': 2}))
self.assertTrue(R.Is(dict, dict()))
self.assertTrue(R.Is(dict, dict(a=1, b=2)))

# Union types
u = int | str
self.assertTrue(R.Is(u, 1))
self.assertTrue(R.Is(u, "1"))

# None type
self.assertTrue(R.Is(None, None))

# Boolean types
self.assertTrue(R.Is(bool, True))
self.assertTrue(R.Is(bool, False))

def test_works_with_objects(self):
class A:
pass

class B(A):
pass

class C(B):
pass

a = A()
b = B()
c = C()

self.assertTrue(R.Is(A, a))
self.assertFalse(R.Is(B, a))
self.assertFalse(R.Is(C, a))

self.assertTrue(R.Is(A, b))
self.assertTrue(R.Is(B, b))
self.assertFalse(R.Is(C, b))

self.assertTrue(R.Is(A, c))
self.assertTrue(R.Is(B, c))
self.assertTrue(R.Is(C, c))

def test_does_not_coerce(self):
self.assertFalse(R.Is(int, "1"))
self.assertFalse(R.Is(float, "1"))


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

import unittest

import ramda as R

from .helpers.Maybe import Just, Maybe

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


class TestOf(unittest.TestCase):
def test_returns_its_argument_as_an_array(self):
self.assertEqual([100], R.of(list, 100))
self.assertEqual([[100]], R.of(list, [100]))
self.assertEqual([None], R.of(list, None))
self.assertEqual([[]], R.of(list, []))

def test_dispatches_to_an_available_of_method(self):
class MaybeWithOf(Maybe):
def of(x):
return Just(x)

just = R.of(MaybeWithOf, 100)
self.assertTrue(R.equals(just, Just(100)))

def test_dispatches_to_an_available_fantasy_land_of_method(self):
class MaybeWithOf(Maybe):
def get(self, name, default=None):
if name == 'fantasy-land/of':
return lambda x: Just(x)

just = R.of(MaybeWithOf, 100)
self.assertTrue(R.equals(just, Just(100)))


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