44from collections import UserDict
55from enum import Enum
66from functools import reduce
7- from typing import TypeVar , Iterable , Callable , Mapping , Optional , Any , List , FrozenSet , Set , Sized , Final , Iterator , Tuple , Dict , Union , Literal
8-
9- T = TypeVar ('T' )
10- S = TypeVar ('S' )
11- R = TypeVar ('R' )
12- K = TypeVar ('K' )
13- V = TypeVar ('V' )
7+ from typing import (
8+ TypeVar ,
9+ Iterable ,
10+ Callable ,
11+ Mapping ,
12+ Optional ,
13+ Any ,
14+ List ,
15+ FrozenSet ,
16+ Set ,
17+ Sized ,
18+ Final ,
19+ Iterator ,
20+ Tuple ,
21+ Dict ,
22+ Union ,
23+ Literal ,
24+ overload ,
25+ )
26+
27+ T = TypeVar ("T" )
28+ S = TypeVar ("S" )
29+ R = TypeVar ("R" )
30+ K = TypeVar ("K" )
31+ V = TypeVar ("V" )
1432
1533
1634def fluent (iterable : Iterable [T ]) -> "FluentIterable[T]" :
@@ -31,7 +49,9 @@ def fluent_of(*args):
3149 return FluentIterableWrapper (args )
3250
3351
34- def fluent_dict (mapping_or_iterable : Union [Mapping [K , V ], Iterable [Tuple [K , V ]], None ] = None , ** kwargs ) -> "FluentMapping[K,V]" :
52+ def fluent_dict (
53+ mapping_or_iterable : Union [Mapping [K , V ], Iterable [Tuple [K , V ]], None ] = None , ** kwargs
54+ ) -> "FluentMapping[K,V]" :
3555 """
3656 Creates a FluentMapping wrapping a dict created from arguments.
3757 The arguments have the same semantics as the built-in dict() method.
@@ -95,7 +115,7 @@ def zip(self, *with_iterables: Iterable) -> "FluentIterable[Tuple]":
95115
96116 def zip_longest (self , * with_iterables : Iterable , fillvalue = None ) -> "FluentIterable[Tuple]" :
97117 """Returns a sequence of tuples built from the elements of this iterable and other given iterables with the same index.
98- The resulting Iterable is as long as the longest input, missing values are substituted with `fillvalue`."""
118+ The resulting Iterable is as long as the longest input, missing values are substituted with `fillvalue`."""
99119 iterable = self ._iterable ()
100120 return FluentFactoryWrapper (lambda : itertools .zip_longest (iterable , * with_iterables , fillvalue = fillvalue ))
101121
@@ -140,7 +160,9 @@ def dropwhile(self, predicate: Callable[[T], Any]) -> "FluentIterable[T]":
140160 iterable = self ._iterable ()
141161 return FluentFactoryWrapper (lambda : itertools .dropwhile (predicate , iterable ))
142162
143- def slice (self , start : Optional [int ] = None , stop : Optional [int ] = None , step : Optional [int ] = None ) -> "FluentIterable[T]" :
163+ def slice (
164+ self , start : Optional [int ] = None , stop : Optional [int ] = None , step : Optional [int ] = None
165+ ) -> "FluentIterable[T]" :
144166 """
145167 Returns a FluentIterable over selected elements from this iterable.
146168 The parameters have the same semantics as for Python list slicing (see also the `slice()` function) or for `itertool.islice()`.
@@ -153,7 +175,7 @@ def slice(self, start: Optional[int] = None, stop: Optional[int] = None, step: O
153175
154176 def compress (self , selectors : Iterable [Any ]) -> "FluentIterable[T]" :
155177 """Returns a FluentIterable that filters elements from this iterable returning only those that have a corresponding element in `selectors` that evaluates to True.
156- Stops when either the data or selectors iterables has been exhausted."""
178+ Stops when either the data or selectors iterables has been exhausted."""
157179 iterable = self ._iterable ()
158180 return FluentFactoryWrapper (lambda : itertools .compress (iterable , selectors ))
159181
@@ -323,20 +345,23 @@ def any(self, predicate: Optional[Callable[[T], bool]] = None) -> bool:
323345
324346 def empty (self ) -> bool :
325347 """Returns true if and only if this iterable does not contain any elements.
326- Note that if the underlying iterable cannot be consumed repeatedly, this method can consume the first element."""
348+ Note that if the underlying iterable cannot be consumed repeatedly, this method can consume the first element.
349+ """
327350 return not self .not_empty ()
328351
329352 def not_empty (self ) -> bool :
330353 """Returns true if and only if this iterable contains at least one element.
331- Note that if the underlying iterable cannot be consumed repeatedly, this method can consume the first element."""
354+ Note that if the underlying iterable cannot be consumed repeatedly, this method can consume the first element.
355+ """
332356 return any (True for _ in self ._iterable ())
333357
334- def len (self ) -> int :
358+ def len (self ) -> int :
335359 """Returns the number of elements in this iterable.
336- Note that evaluation may result in iterating over the iterable if the wrapped collections doesn't implement the Sized contract."""
360+ Note that evaluation may result in iterating over the iterable if the wrapped collections doesn't implement the Sized contract.
361+ """
337362 it = self .__iter__ ()
338363 if hasattr (it , "__len__" ):
339- return it .__len__ ()
364+ return it .__len__ () # type: ignore
340365 else :
341366 count = 0
342367 for _ in it :
@@ -345,7 +370,8 @@ def len(self) -> int:
345370
346371 def __len__ (self ) -> int :
347372 """Returns the number of elements in this iterable.
348- Note that evaluation may result in iterating over the iterable if the wrapped collections doesn't implement the Sized contract."""
373+ Note that evaluation may result in iterating over the iterable if the wrapped collections doesn't implement the Sized contract.
374+ """
349375 return self .len ()
350376
351377 def sum (self ):
@@ -366,7 +392,11 @@ def max(self, key: Optional[Callable[[T], Any]] = None, default: Optional[T] = N
366392 """
367393 return max (self ._iterable (), key = key , default = default )
368394
369- def reduce (self , function : Callable [[Union [S , T , R ], T ], R ], initial : Union [S , None , Literal [_Sentinel .INITIAL_MISSING ]] = _Sentinel .INITIAL_MISSING ) -> R :
395+ def reduce (
396+ self ,
397+ function : Callable [[Union [S , T , R ], T ], R ],
398+ initial : Union [S , None , Literal [_Sentinel .INITIAL_MISSING ]] = _Sentinel .INITIAL_MISSING ,
399+ ) -> R :
370400 """
371401 Accumulates value starting with `default`, if given, or the first element otherwise, and applying `function` from to current accumulator value and each element of this iterable.
372402 E.g., [1,2,3].reduce(lambda x, y: x+y, 0) calculates (((0+1)+2)+3).
@@ -385,6 +415,7 @@ def first(self) -> Optional[T]:
385415
386416class FluentIterableWrapper (FluentIterable [T ]):
387417 """Implementation that wraps an existing reusable Iterable"""
418+
388419 inner : Final [Iterable ]
389420
390421 def __init__ (self , iterable : Iterable [T ]):
@@ -397,6 +428,7 @@ def _iterable(self):
397428 return self .inner
398429
399430
431+
400432class FluentFactoryWrapper (FluentIterable [T ]):
401433 """Implementation for cases where a known factory to a non-reusable Iterator is available"""
402434
@@ -429,13 +461,15 @@ def _iterable(self):
429461 ######
430462 def filter_keys (self , predicate : Optional [Callable [[K ], Any ]] = None ) -> "FluentMapping[K,V]" :
431463 """Returns a FluentMapping that wraps dictionary created from this mapping by omitting items
432- for which applying `predicate` to the key evaluates to false, or for which the key itself evaluates to false if predicate is not given."""
464+ for which applying `predicate` to the key evaluates to false, or for which the key itself evaluates to false if predicate is not given.
465+ """
433466 predicate = predicate or _identity
434467 return FluentMapping ({k : v for k , v in self .items () if predicate (k )})
435468
436469 def filter_values (self , predicate : Optional [Callable [[V ], Any ]] = None ) -> "FluentMapping[K,V]" :
437470 """Returns a FluentMapping that wraps dictionary created from this mapping by omitting items
438- for which applying `predicate` to the value evaluates to false, or for which the value itself evaluates to false if predicate is not given."""
471+ for which applying `predicate` to the value evaluates to false, or for which the value itself evaluates to false if predicate is not given.
472+ """
439473 predicate = predicate or _identity
440474 return FluentMapping ({k : v for k , v in self .items () if predicate (v )})
441475
@@ -454,7 +488,9 @@ def map_items(self, transform: Callable[[K, V], R]) -> "FluentMapping[K, R]":
454488 def sort_items (self , key : Callable [[K , V ], Any ], reverse : bool = False ) -> "FluentMapping[K, R]" :
455489 """Returns a FluentMapping with the same (key, value) pairs but which has its iterating order determined by the result of the `key` function applied to each pair."""
456490 # Note that dictionaries preserve insertion order (guaranteed since 3.7, CPython implementation detail before)
457- return FluentMapping ({k : self .data [k ] for k , v in sorted (self .items (), key = lambda kv_pair : key (* kv_pair ), reverse = reverse )})
491+ return FluentMapping (
492+ {k : self .data [k ] for k , v in sorted (self .items (), key = lambda kv_pair : key (* kv_pair ), reverse = reverse )}
493+ )
458494
459495 ######
460496 # Operations with side-effects
0 commit comments