From e780f95a77b80ac861125f3573b6e32d40f15160 Mon Sep 17 00:00:00 2001 From: zyd Date: Thu, 2 Jun 2022 12:32:04 +0900 Subject: [PATCH 1/2] Add method keysIn --- README.md | 26 +++++++++++++++++++- ramda/__init__.py | 1 + ramda/keysIn.py | 26 ++++++++++++++++++++ test/test_keysIn.py | 59 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 ramda/keysIn.py create mode 100644 test/test_keysIn.py diff --git a/README.md b/README.md index 1a3263e..2ecf16a 100644 --- a/README.md +++ b/README.md @@ -271,9 +271,33 @@ c = C(4) R.keys(a) # ['a'] R.keys(b) # ['a', 'b'] R.keys(c) # ['c'], because c does not call super().__init__() + +# For normal dict +R.keys({'a': 1, 'b': 2}) # ['a', 'b'] +``` + +- [x] keysIn + +Different from `keys`, `keysIn` will return all attributes of the object, including super class attributes and class static variables. + +```python +class A: + a_static = 1 + def __init__(self): + self.a = 1 +class B(A): + b_static = 2 + def __init__(self, b): + super().__init__() + self.b = b + +R.keysIn(A()) # ['a_static', 'a'] +R.keysIn(B(2)) # ['a_static', 'a', 'b_static', 'b'] + +# For normal dict +R.keysIn({'a': 1, 'b': 2}) # ['a', 'b'] ``` -- [ ] keysIn - [x] 0.1.4 last - [x] 0.1.2 lastIndexOf - [ ] length diff --git a/ramda/__init__.py b/ramda/__init__.py index 71aad9e..c3e1dde 100644 --- a/ramda/__init__.py +++ b/ramda/__init__.py @@ -44,6 +44,7 @@ from .join import join from .juxt import juxt from .keys import keys +from .keysIn import keysIn from .last import last from .lastIndexOf import lastIndexOf from .lt import lt diff --git a/ramda/keysIn.py b/ramda/keysIn.py new file mode 100644 index 0000000..85fcb0b --- /dev/null +++ b/ramda/keysIn.py @@ -0,0 +1,26 @@ +from .keys import keys +from .private._curry1 import _curry1 + + +def static_keysIn(clazz): + ks = [v for v, m in vars(clazz).items() if not (v.startswith('_') or callable(m))] + for base in clazz.__bases__: + ks += static_keysIn(base) + return ks + + +def inner_keysIn(obj): + ks = [] + primitives = (int, float, bool, str) + # ignore primitive types + if isinstance(obj, primitives): + return ks + # extract all static variables + ks += static_keysIn(obj.__class__) + # extract all instance variables + ks += keys(obj) + + return ks + + +keysIn = _curry1(inner_keysIn) diff --git a/test/test_keysIn.py b/test/test_keysIn.py new file mode 100644 index 0000000..ce911a5 --- /dev/null +++ b/test/test_keysIn.py @@ -0,0 +1,59 @@ + +import unittest + +import ramda as R + +""" +https://github.com/ramda/ramda/blob/master/test/keysIn.js +""" + + +class TestKeysIn(unittest.TestCase): + def test_returns_an_array_of_the_given_dict_keys(self): + d = {'a': 100, 'b': [1, 2, 3], 'c': {'x': 200, 'y': 300}, 'd': 'D', 'e': None} + self.assertEqual(['a', 'b', 'c', 'd', 'e'], R.keysIn(d)) + + def test_returns_an_array_of_the_given_obj_keys(self): + class Obj: + def __init__(self, a, b, c, d, e): + self.a = a + self.b = b + self.c = c + self.d = d + self.e = e + obj = Obj(100, [1, 2, 3], {'x': 200, 'y': 300}, 'D', None) + self.assertEqual(['a', 'b', 'c', 'd', 'e'], R.keysIn(obj)) + + def test_returns_an_array_of_the_given_obj_with_parent_keys(self): + class Parent: + ps1 = 'parent static 1' + ps2 = 'parent static 2' + + def __init__(self, p1, p2): + self.p1 = p1 + self.p2 = p2 + + class Child(Parent): + cs1 = 'child static 1' + cs2 = 'child static 2' + + def __init__(self, p1, p2, c1, c2): + super().__init__(p1, p2) + self.c1 = c1 + self.c2 = c2 + + child = Child('p1', 'p2', 'c1', 'c2') + self.assertEqual(['cs1', 'cs2', 'ps1', 'ps2', 'p1', 'p2', 'c1', 'c2'], R.keysIn(child)) + + def test_works_for_primitives(self): + self.assertEqual([], R.keysIn(None)) + self.assertEqual([], R.keysIn(0)) + self.assertEqual([], R.keysIn(False)) + self.assertEqual([], R.keysIn(True)) + self.assertEqual([], R.keysIn('')) + self.assertEqual([], R.keysIn([])) + self.assertEqual([], R.keysIn({})) + + +if __name__ == '__main__': + unittest.main() From 18a1d2468878349cb6472916af3f1a366568aec5 Mon Sep 17 00:00:00 2001 From: zyd Date: Thu, 2 Jun 2022 12:55:25 +0900 Subject: [PATCH 2/2] Fix by latest pylint warnings --- ramda/filter.py | 5 ++--- ramda/join.py | 3 +++ ramda/private/_Set.py | 2 +- ramda/private/_createReduce.py | 2 +- ramda/private/_equals.py | 6 +----- ramda/private/_xfBase.py | 1 - ramda/where.py | 5 +---- 7 files changed, 9 insertions(+), 15 deletions(-) diff --git a/ramda/filter.py b/ramda/filter.py index 71166d2..2145b49 100644 --- a/ramda/filter.py +++ b/ramda/filter.py @@ -23,11 +23,10 @@ def inner_reduce(acc, key): if isinstance(filterable, dict) or _has(filterable, 'get'): if pred(filterable.get(key)): acc[key] = filterable.get(key) - else: + elif not pred(getattr(filterable, key, None)): # This is special, because we deepcopy the original object, # so we delete attr from original object if not match - if not pred(getattr(filterable, key, None)): - delattr(acc, key) + delattr(acc, key) return acc return _reduce(inner_reduce, {} if isinstance(filterable, dict) or _has(filterable, 'get') else copy.deepcopy(filterable), keys(filterable)) diff --git a/ramda/join.py b/ramda/join.py index d5f4fa7..fe5a7f4 100644 --- a/ramda/join.py +++ b/ramda/join.py @@ -1,2 +1,5 @@ +from .map import map + + def join(separator, xs): return separator.join(map(str, xs)) diff --git a/ramda/private/_Set.py b/ramda/private/_Set.py index bafaf98..9f0579b 100644 --- a/ramda/private/_Set.py +++ b/ramda/private/_Set.py @@ -4,7 +4,7 @@ class _Set(set): def add(self, item): - if filter(equals(item), list(self.__iter__())): + if filter(equals(item), list(iter(self))): return False super().add(item) return True diff --git a/ramda/private/_createReduce.py b/ramda/private/_createReduce.py index 7819345..9d4cc22 100644 --- a/ramda/private/_createReduce.py +++ b/ramda/private/_createReduce.py @@ -1,4 +1,4 @@ -from typing import Iterable +from collections.abc import Iterable from ._helper import getAttribute from ._isArrayLike import _isArrayLike diff --git a/ramda/private/_equals.py b/ramda/private/_equals.py index d9e048e..12ace98 100644 --- a/ramda/private/_equals.py +++ b/ramda/private/_equals.py @@ -19,11 +19,7 @@ def _equals(a, b): # Array-like if len(a) != len(b): return False - # pylint: disable=consider-using-enumerate - for i in range(len(a)): - if not _equals(a[i], b[i]): - return False - return True + return all(_equals(a[i], b[i]) for i in range(len(a))) if _isFunction(getAttribute(a, 'equals')) and _isFunction(getAttribute(b, 'equals')): # dispatch to objects' own equals method return a.equals(b) and b.equals(a) diff --git a/ramda/private/_xfBase.py b/ramda/private/_xfBase.py index a3689ed..f8b97ce 100644 --- a/ramda/private/_xfBase.py +++ b/ramda/private/_xfBase.py @@ -16,7 +16,6 @@ def init(self): def result(self, result): return getAttribute(self.xf, '@@transducer/result')(result) - # pylint: disable=no-self-use def step(self, result, _input): raise Exception('Child class should implement this') diff --git a/ramda/where.py b/ramda/where.py index e7ef5f4..f84c300 100644 --- a/ramda/where.py +++ b/ramda/where.py @@ -4,10 +4,7 @@ def inner_where(spec, testObj): - for prop in spec: - if _has(spec, prop) and not spec[prop](getAttribute(testObj, prop)): - return False - return True + return not any((_has(spec, prop) and not spec[prop](getAttribute(testObj, prop))) for prop in spec) where = _curry2(inner_where)