summaryrefslogtreecommitdiff
path: root/python-pyfunctional.spec
diff options
context:
space:
mode:
Diffstat (limited to 'python-pyfunctional.spec')
-rw-r--r--python-pyfunctional.spec510
1 files changed, 510 insertions, 0 deletions
diff --git a/python-pyfunctional.spec b/python-pyfunctional.spec
new file mode 100644
index 0000000..8cb7607
--- /dev/null
+++ b/python-pyfunctional.spec
@@ -0,0 +1,510 @@
+%global _empty_manifest_terminate_build 0
+Name: python-pyfunctional
+Version: 1.4.3
+Release: 1
+Summary: Package for creating data pipelines with chain functional programming
+License: MIT
+URL: https://github.com/EntilZha/PyFunctional
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/65/b8/134bf0187d5db42641e93a23c90e0ea20dcda2a8c148147ccc07ecde56e4/PyFunctional-1.4.3.tar.gz
+BuildArch: noarch
+
+Requires: python3-dill
+Requires: python3-tabulate
+Requires: python3-pandas
+
+%description
+`map(func)/select(func)` | Maps `func` onto elements of sequence | transformation
+`starmap(func)/smap(func)` | Apply `func` to sequence with `itertools.starmap` | transformation
+`filter(func)/where(func)` | Filters elements of sequence to only those where `func(element)` is `True` | transformation
+`filter_not(func)` | Filters elements of sequence to only those where `func(element)` is `False` | transformation
+`flatten()` | Flattens sequence of lists to a single sequence | transformation
+`flat_map(func)` | `func` must return an iterable. Maps `func` to each element, then merges the result to one flat sequence | transformation
+`group_by(func)` | Groups sequence into `(key, value)` pairs where `key=func(element)` and `value` is from the original sequence | transformation
+`group_by_key()` | Groups sequence of `(key, value)` pairs by `key` | transformation
+`reduce_by_key(func)` | Reduces list of `(key, value)` pairs using `func` | transformation
+`count_by_key()` | Counts occurrences of each `key` in list of `(key, value)` pairs | transformation
+`count_by_value()` | Counts occurrence of each value in a list | transformation
+`union(other)` | Union of unique elements in sequence and `other` | transformation
+`intersection(other)` | Intersection of unique elements in sequence and `other` | transformation
+`difference(other)` | New sequence with unique elements present in sequence but not in `other` | transformation
+`symmetric_difference(other)` | New sequence with unique elements present in sequence or `other`, but not both | transformation
+`distinct()` | Returns distinct elements of sequence. Elements must be hashable | transformation
+`distinct_by(func)` | Returns distinct elements of sequence using `func` as a key | transformation
+`drop(n)` | Drop the first `n` elements of the sequence | transformation
+`drop_right(n)` | Drop the last `n` elements of the sequence | transformation
+`drop_while(func)` | Drop elements while `func` evaluates to `True`, then returns the rest | transformation
+`take(n)` | Returns sequence of first `n` elements | transformation
+`take_while(func)` | Take elements while `func` evaluates to `True`, then drops the rest | transformation
+`init()` | Returns sequence without the last element | transformation
+`tail()` | Returns sequence without the first element | transformation
+`inits()` | Returns consecutive inits of sequence | transformation
+`tails()` | Returns consecutive tails of sequence | transformation
+`zip(other)` | Zips the sequence with `other` | transformation
+`zip_with_index(start=0)` | Zips the sequence with the index starting at `start` on the right side | transformation
+`enumerate(start=0)` | Zips the sequence with the index starting at `start` on the left side | transformation
+`cartesian(*iterables, repeat=1)` | Returns cartesian product from itertools.product | transformation
+`inner_join(other)` | Returns inner join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`outer_join(other)` | Returns outer join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`left_join(other)` | Returns left join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`right_join(other)` | Returns right join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`join(other, join_type='inner')` | Returns join of sequence with other as specified by `join_type`. Must be a sequence of `(key, value)` pairs | transformation
+`partition(func)` | Partitions the sequence into elements which satisfy `func(element)` and those that don't | transformation
+`grouped(size)` | Partitions the elements into groups of size `size` | transformation
+`sorted(key=None, reverse=False)/order_by(func)` | Returns elements sorted according to python `sorted` | transformation
+`reverse()` | Returns the reversed sequence | transformation
+`slice(start, until)` | Sequence starting at `start` and including elements up to `until` | transformation
+`head()` / `first()` | Returns first element in sequence | action
+`head_option()` | Returns first element in sequence or `None` if its empty | action
+`last()` | Returns last element in sequence | action
+`last_option()` | Returns last element in sequence or `None` if its empty | action
+`len()` / `size()` | Returns length of sequence | action
+`count(func)` | Returns count of elements in sequence where `func(element)` is True | action
+`empty()` | Returns `True` if the sequence has zero length | action
+`non_empty()` | Returns `True` if sequence has non-zero length | action
+`all()` | Returns `True` if all elements in sequence are truthy | action
+`exists(func)` | Returns `True` if `func(element)` for any element in the sequence is `True` | action
+`for_all(func)` | Returns `True` if `func(element)` is `True` for all elements in the sequence | action
+`find(func)` | Returns the element that first evaluates `func(element)` to `True` | action
+`any()` | Returns `True` if any element in sequence is truthy | action
+`max()` | Returns maximal element in sequence | action
+`min()` | Returns minimal element in sequence | action
+`max_by(func)` | Returns element with maximal value `func(element)` | action
+`min_by(func)` | Returns element with minimal value `func(element)` | action
+`sum()/sum(projection)` | Returns the sum of elements possibly using a projection | action
+`product()/product(projection)` | Returns the product of elements possibly using a projection | action
+`average()/average(projection)` | Returns the average of elements possibly using a projection | action
+`aggregate(func)/aggregate(seed, func)/aggregate(seed, func, result_map)` | Aggregate using `func` starting with `seed` or first element of list then apply `result_map` to the result | action
+`fold_left(zero_value, func)` | Reduces element from left to right using `func` and initial value `zero_value` | action
+`fold_right(zero_value, func)` | Reduces element from right to left using `func` and initial value `zero_value` | action
+`make_string(separator)` | Returns string with `separator` between each `str(element)` | action
+`dict(default=None)` / `to_dict(default=None)` | Converts a sequence of `(Key, Value)` pairs to a `dictionary`. If `default` is not None, it must be a value or zero argument callable which will be used to create a `collections.defaultdict` | action
+`list()` / `to_list()` | Converts sequence to a list | action
+`set() / to_set()` | Converts sequence to a set | action
+`to_file(path)` | Saves the sequence to a file at path with each element on a newline | action
+`to_csv(path)` | Saves the sequence to a csv file at path with each element representing a row | action
+`to_jsonl(path)` | Saves the sequence to a jsonl file with each element being transformed to json and printed to a new line | action
+`to_json(path)` | Saves the sequence to a json file. The contents depend on if the json root is an array or dictionary | action
+`to_sqlite3(conn, tablename_or_query, *args, **kwargs)` | Save the sequence to a SQLite3 db. The target table must be created in advance. | action
+`to_pandas(columns=None)` | Converts the sequence to a pandas DataFrame | action
+`cache()` | Forces evaluation of sequence immediately and caches the result | action
+`for_each(func)` | Executes `func` on each element of the sequence | action
+### Lazy Execution
+Whenever possible, `PyFunctional` will compute lazily. This is accomplished by tracking the list
+of transformations that have been applied to the sequence and only evaluating them when an action is
+called. In `PyFunctional` this is called tracking lineage. This is also responsible for the
+ability for `PyFunctional` to cache results of computation to prevent expensive re-computation.
+This is predominantly done to preserve sensible behavior and used sparingly. For example, calling
+`size()` will cache the underlying sequence. If this was not done and the input was an iterator,
+then further calls would operate on an expired iterator since it was used to compute the length.
+Similarly, `repr` also caches since it is most often used during interactive sessions where its
+undesirable to keep recomputing the same value. Below are some examples of inspecting lineage.
+```python
+def times_2(x):
+ print(x)
+ return 2 * x
+elements = seq(1, 1, 2, 3, 4).map(times_2).distinct()
+elements._lineage
+# Lineage: sequence -> map(times_2) -> distinct
+l_elements = elements.to_list()
+# Prints: 1
+# Prints: 1
+# Prints: 2
+# Prints: 3
+# Prints: 4
+elements._lineage
+# Lineage: sequence -> map(times_2) -> distinct -> cache
+l_elements = elements.to_list()
+# The cached result is returned so times_2 is not called and nothing is printed
+```
+Files are given special treatment if opened through the `seq.open` and related APIs.
+`functional.util.ReusableFile` implements a wrapper around the standard python file to support
+multiple iteration over a single file object while correctly handling iteration termination and
+file closing.
+## Road Map Idea
+* SQL based query planner and interpreter
+* `_` lambda operator
+## Contributing and Bug Fixes
+Any contributions or bug reports are welcome. Thus far, there is a 100% acceptance rate for pull
+requests and contributors have offered valuable feedback and critique on code. It is great to hear
+from users of the package, especially what it is used for, what works well, and what could be
+improved.
+To contribute, create a fork of `PyFunctional`, make your changes, then make sure that they pass.
+In order to be merged, all pull requests must:
+* Pass all the unit tests
+* Pass all the pylint tests, or ignore warnings with explanation of why its correct to do so
+* Not significantly reduce covrage without a good reason [coveralls.io](coveralls.io/github/EntilZha/PyFunctional))
+* Edit the `CHANGELOG.md` file in the `Next Release` heading with changes
+## Contact
+[Gitter for chat](https://gitter.im/EntilZha/PyFunctional)
+## Supported Python Versions
+* `PyFunctional` 1.4 and above supports and is tested against Python 3.6, Python 3.7, and PyPy3
+* `PyFunctional` 1.4 and above does not support python 2.7
+* `PyFunctional` 1.4 and above works in Python 3.5, but is not tested against it
+* `PyFunctional` 1.4 and above partially works in 3.8, parallel processing currently has issues, but other feature work fine
+* `PyFunctional` 1.3 and below supports and was tested against Python 2.7, Python 3.5, Python 3.6, PyPy2, and PyPy3
+## Changelog
+[Changelog](https://github.com/EntilZha/PyFunctional/blob/master/CHANGELOG.md)
+## About me
+To learn more about me (the author) visit my webpage at
+[pedro.ai](https://www.pedro.ai).
+I created `PyFunctional` while using Python extensivel, and finding that I missed the
+ease of use for manipulating data that Spark RDDs and Scala collections have. The project takes the
+best ideas from these APIs as well as LINQ to provide an easy way to manipulate data when using
+Scala is not an option or PySpark is overkill.
+## Contributors
+These people have generously contributed their time to improving `PyFunctional`
+* [versae](https://github.com/versae)
+* [adrian17](https://github.com/adrian17)
+* [lucidfrontier45](https://github.com/lucidfrontier45)
+* [Digenis](https://github.com/Digenis)
+* [ChuyuHsu](https://github.com/ChuyuHsu)
+* [jsemric](https://github.com/jsemric)
+
+%package -n python3-pyfunctional
+Summary: Package for creating data pipelines with chain functional programming
+Provides: python-pyfunctional
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-pyfunctional
+`map(func)/select(func)` | Maps `func` onto elements of sequence | transformation
+`starmap(func)/smap(func)` | Apply `func` to sequence with `itertools.starmap` | transformation
+`filter(func)/where(func)` | Filters elements of sequence to only those where `func(element)` is `True` | transformation
+`filter_not(func)` | Filters elements of sequence to only those where `func(element)` is `False` | transformation
+`flatten()` | Flattens sequence of lists to a single sequence | transformation
+`flat_map(func)` | `func` must return an iterable. Maps `func` to each element, then merges the result to one flat sequence | transformation
+`group_by(func)` | Groups sequence into `(key, value)` pairs where `key=func(element)` and `value` is from the original sequence | transformation
+`group_by_key()` | Groups sequence of `(key, value)` pairs by `key` | transformation
+`reduce_by_key(func)` | Reduces list of `(key, value)` pairs using `func` | transformation
+`count_by_key()` | Counts occurrences of each `key` in list of `(key, value)` pairs | transformation
+`count_by_value()` | Counts occurrence of each value in a list | transformation
+`union(other)` | Union of unique elements in sequence and `other` | transformation
+`intersection(other)` | Intersection of unique elements in sequence and `other` | transformation
+`difference(other)` | New sequence with unique elements present in sequence but not in `other` | transformation
+`symmetric_difference(other)` | New sequence with unique elements present in sequence or `other`, but not both | transformation
+`distinct()` | Returns distinct elements of sequence. Elements must be hashable | transformation
+`distinct_by(func)` | Returns distinct elements of sequence using `func` as a key | transformation
+`drop(n)` | Drop the first `n` elements of the sequence | transformation
+`drop_right(n)` | Drop the last `n` elements of the sequence | transformation
+`drop_while(func)` | Drop elements while `func` evaluates to `True`, then returns the rest | transformation
+`take(n)` | Returns sequence of first `n` elements | transformation
+`take_while(func)` | Take elements while `func` evaluates to `True`, then drops the rest | transformation
+`init()` | Returns sequence without the last element | transformation
+`tail()` | Returns sequence without the first element | transformation
+`inits()` | Returns consecutive inits of sequence | transformation
+`tails()` | Returns consecutive tails of sequence | transformation
+`zip(other)` | Zips the sequence with `other` | transformation
+`zip_with_index(start=0)` | Zips the sequence with the index starting at `start` on the right side | transformation
+`enumerate(start=0)` | Zips the sequence with the index starting at `start` on the left side | transformation
+`cartesian(*iterables, repeat=1)` | Returns cartesian product from itertools.product | transformation
+`inner_join(other)` | Returns inner join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`outer_join(other)` | Returns outer join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`left_join(other)` | Returns left join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`right_join(other)` | Returns right join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`join(other, join_type='inner')` | Returns join of sequence with other as specified by `join_type`. Must be a sequence of `(key, value)` pairs | transformation
+`partition(func)` | Partitions the sequence into elements which satisfy `func(element)` and those that don't | transformation
+`grouped(size)` | Partitions the elements into groups of size `size` | transformation
+`sorted(key=None, reverse=False)/order_by(func)` | Returns elements sorted according to python `sorted` | transformation
+`reverse()` | Returns the reversed sequence | transformation
+`slice(start, until)` | Sequence starting at `start` and including elements up to `until` | transformation
+`head()` / `first()` | Returns first element in sequence | action
+`head_option()` | Returns first element in sequence or `None` if its empty | action
+`last()` | Returns last element in sequence | action
+`last_option()` | Returns last element in sequence or `None` if its empty | action
+`len()` / `size()` | Returns length of sequence | action
+`count(func)` | Returns count of elements in sequence where `func(element)` is True | action
+`empty()` | Returns `True` if the sequence has zero length | action
+`non_empty()` | Returns `True` if sequence has non-zero length | action
+`all()` | Returns `True` if all elements in sequence are truthy | action
+`exists(func)` | Returns `True` if `func(element)` for any element in the sequence is `True` | action
+`for_all(func)` | Returns `True` if `func(element)` is `True` for all elements in the sequence | action
+`find(func)` | Returns the element that first evaluates `func(element)` to `True` | action
+`any()` | Returns `True` if any element in sequence is truthy | action
+`max()` | Returns maximal element in sequence | action
+`min()` | Returns minimal element in sequence | action
+`max_by(func)` | Returns element with maximal value `func(element)` | action
+`min_by(func)` | Returns element with minimal value `func(element)` | action
+`sum()/sum(projection)` | Returns the sum of elements possibly using a projection | action
+`product()/product(projection)` | Returns the product of elements possibly using a projection | action
+`average()/average(projection)` | Returns the average of elements possibly using a projection | action
+`aggregate(func)/aggregate(seed, func)/aggregate(seed, func, result_map)` | Aggregate using `func` starting with `seed` or first element of list then apply `result_map` to the result | action
+`fold_left(zero_value, func)` | Reduces element from left to right using `func` and initial value `zero_value` | action
+`fold_right(zero_value, func)` | Reduces element from right to left using `func` and initial value `zero_value` | action
+`make_string(separator)` | Returns string with `separator` between each `str(element)` | action
+`dict(default=None)` / `to_dict(default=None)` | Converts a sequence of `(Key, Value)` pairs to a `dictionary`. If `default` is not None, it must be a value or zero argument callable which will be used to create a `collections.defaultdict` | action
+`list()` / `to_list()` | Converts sequence to a list | action
+`set() / to_set()` | Converts sequence to a set | action
+`to_file(path)` | Saves the sequence to a file at path with each element on a newline | action
+`to_csv(path)` | Saves the sequence to a csv file at path with each element representing a row | action
+`to_jsonl(path)` | Saves the sequence to a jsonl file with each element being transformed to json and printed to a new line | action
+`to_json(path)` | Saves the sequence to a json file. The contents depend on if the json root is an array or dictionary | action
+`to_sqlite3(conn, tablename_or_query, *args, **kwargs)` | Save the sequence to a SQLite3 db. The target table must be created in advance. | action
+`to_pandas(columns=None)` | Converts the sequence to a pandas DataFrame | action
+`cache()` | Forces evaluation of sequence immediately and caches the result | action
+`for_each(func)` | Executes `func` on each element of the sequence | action
+### Lazy Execution
+Whenever possible, `PyFunctional` will compute lazily. This is accomplished by tracking the list
+of transformations that have been applied to the sequence and only evaluating them when an action is
+called. In `PyFunctional` this is called tracking lineage. This is also responsible for the
+ability for `PyFunctional` to cache results of computation to prevent expensive re-computation.
+This is predominantly done to preserve sensible behavior and used sparingly. For example, calling
+`size()` will cache the underlying sequence. If this was not done and the input was an iterator,
+then further calls would operate on an expired iterator since it was used to compute the length.
+Similarly, `repr` also caches since it is most often used during interactive sessions where its
+undesirable to keep recomputing the same value. Below are some examples of inspecting lineage.
+```python
+def times_2(x):
+ print(x)
+ return 2 * x
+elements = seq(1, 1, 2, 3, 4).map(times_2).distinct()
+elements._lineage
+# Lineage: sequence -> map(times_2) -> distinct
+l_elements = elements.to_list()
+# Prints: 1
+# Prints: 1
+# Prints: 2
+# Prints: 3
+# Prints: 4
+elements._lineage
+# Lineage: sequence -> map(times_2) -> distinct -> cache
+l_elements = elements.to_list()
+# The cached result is returned so times_2 is not called and nothing is printed
+```
+Files are given special treatment if opened through the `seq.open` and related APIs.
+`functional.util.ReusableFile` implements a wrapper around the standard python file to support
+multiple iteration over a single file object while correctly handling iteration termination and
+file closing.
+## Road Map Idea
+* SQL based query planner and interpreter
+* `_` lambda operator
+## Contributing and Bug Fixes
+Any contributions or bug reports are welcome. Thus far, there is a 100% acceptance rate for pull
+requests and contributors have offered valuable feedback and critique on code. It is great to hear
+from users of the package, especially what it is used for, what works well, and what could be
+improved.
+To contribute, create a fork of `PyFunctional`, make your changes, then make sure that they pass.
+In order to be merged, all pull requests must:
+* Pass all the unit tests
+* Pass all the pylint tests, or ignore warnings with explanation of why its correct to do so
+* Not significantly reduce covrage without a good reason [coveralls.io](coveralls.io/github/EntilZha/PyFunctional))
+* Edit the `CHANGELOG.md` file in the `Next Release` heading with changes
+## Contact
+[Gitter for chat](https://gitter.im/EntilZha/PyFunctional)
+## Supported Python Versions
+* `PyFunctional` 1.4 and above supports and is tested against Python 3.6, Python 3.7, and PyPy3
+* `PyFunctional` 1.4 and above does not support python 2.7
+* `PyFunctional` 1.4 and above works in Python 3.5, but is not tested against it
+* `PyFunctional` 1.4 and above partially works in 3.8, parallel processing currently has issues, but other feature work fine
+* `PyFunctional` 1.3 and below supports and was tested against Python 2.7, Python 3.5, Python 3.6, PyPy2, and PyPy3
+## Changelog
+[Changelog](https://github.com/EntilZha/PyFunctional/blob/master/CHANGELOG.md)
+## About me
+To learn more about me (the author) visit my webpage at
+[pedro.ai](https://www.pedro.ai).
+I created `PyFunctional` while using Python extensivel, and finding that I missed the
+ease of use for manipulating data that Spark RDDs and Scala collections have. The project takes the
+best ideas from these APIs as well as LINQ to provide an easy way to manipulate data when using
+Scala is not an option or PySpark is overkill.
+## Contributors
+These people have generously contributed their time to improving `PyFunctional`
+* [versae](https://github.com/versae)
+* [adrian17](https://github.com/adrian17)
+* [lucidfrontier45](https://github.com/lucidfrontier45)
+* [Digenis](https://github.com/Digenis)
+* [ChuyuHsu](https://github.com/ChuyuHsu)
+* [jsemric](https://github.com/jsemric)
+
+%package help
+Summary: Development documents and examples for pyfunctional
+Provides: python3-pyfunctional-doc
+%description help
+`map(func)/select(func)` | Maps `func` onto elements of sequence | transformation
+`starmap(func)/smap(func)` | Apply `func` to sequence with `itertools.starmap` | transformation
+`filter(func)/where(func)` | Filters elements of sequence to only those where `func(element)` is `True` | transformation
+`filter_not(func)` | Filters elements of sequence to only those where `func(element)` is `False` | transformation
+`flatten()` | Flattens sequence of lists to a single sequence | transformation
+`flat_map(func)` | `func` must return an iterable. Maps `func` to each element, then merges the result to one flat sequence | transformation
+`group_by(func)` | Groups sequence into `(key, value)` pairs where `key=func(element)` and `value` is from the original sequence | transformation
+`group_by_key()` | Groups sequence of `(key, value)` pairs by `key` | transformation
+`reduce_by_key(func)` | Reduces list of `(key, value)` pairs using `func` | transformation
+`count_by_key()` | Counts occurrences of each `key` in list of `(key, value)` pairs | transformation
+`count_by_value()` | Counts occurrence of each value in a list | transformation
+`union(other)` | Union of unique elements in sequence and `other` | transformation
+`intersection(other)` | Intersection of unique elements in sequence and `other` | transformation
+`difference(other)` | New sequence with unique elements present in sequence but not in `other` | transformation
+`symmetric_difference(other)` | New sequence with unique elements present in sequence or `other`, but not both | transformation
+`distinct()` | Returns distinct elements of sequence. Elements must be hashable | transformation
+`distinct_by(func)` | Returns distinct elements of sequence using `func` as a key | transformation
+`drop(n)` | Drop the first `n` elements of the sequence | transformation
+`drop_right(n)` | Drop the last `n` elements of the sequence | transformation
+`drop_while(func)` | Drop elements while `func` evaluates to `True`, then returns the rest | transformation
+`take(n)` | Returns sequence of first `n` elements | transformation
+`take_while(func)` | Take elements while `func` evaluates to `True`, then drops the rest | transformation
+`init()` | Returns sequence without the last element | transformation
+`tail()` | Returns sequence without the first element | transformation
+`inits()` | Returns consecutive inits of sequence | transformation
+`tails()` | Returns consecutive tails of sequence | transformation
+`zip(other)` | Zips the sequence with `other` | transformation
+`zip_with_index(start=0)` | Zips the sequence with the index starting at `start` on the right side | transformation
+`enumerate(start=0)` | Zips the sequence with the index starting at `start` on the left side | transformation
+`cartesian(*iterables, repeat=1)` | Returns cartesian product from itertools.product | transformation
+`inner_join(other)` | Returns inner join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`outer_join(other)` | Returns outer join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`left_join(other)` | Returns left join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`right_join(other)` | Returns right join of sequence with other. Must be a sequence of `(key, value)` pairs | transformation
+`join(other, join_type='inner')` | Returns join of sequence with other as specified by `join_type`. Must be a sequence of `(key, value)` pairs | transformation
+`partition(func)` | Partitions the sequence into elements which satisfy `func(element)` and those that don't | transformation
+`grouped(size)` | Partitions the elements into groups of size `size` | transformation
+`sorted(key=None, reverse=False)/order_by(func)` | Returns elements sorted according to python `sorted` | transformation
+`reverse()` | Returns the reversed sequence | transformation
+`slice(start, until)` | Sequence starting at `start` and including elements up to `until` | transformation
+`head()` / `first()` | Returns first element in sequence | action
+`head_option()` | Returns first element in sequence or `None` if its empty | action
+`last()` | Returns last element in sequence | action
+`last_option()` | Returns last element in sequence or `None` if its empty | action
+`len()` / `size()` | Returns length of sequence | action
+`count(func)` | Returns count of elements in sequence where `func(element)` is True | action
+`empty()` | Returns `True` if the sequence has zero length | action
+`non_empty()` | Returns `True` if sequence has non-zero length | action
+`all()` | Returns `True` if all elements in sequence are truthy | action
+`exists(func)` | Returns `True` if `func(element)` for any element in the sequence is `True` | action
+`for_all(func)` | Returns `True` if `func(element)` is `True` for all elements in the sequence | action
+`find(func)` | Returns the element that first evaluates `func(element)` to `True` | action
+`any()` | Returns `True` if any element in sequence is truthy | action
+`max()` | Returns maximal element in sequence | action
+`min()` | Returns minimal element in sequence | action
+`max_by(func)` | Returns element with maximal value `func(element)` | action
+`min_by(func)` | Returns element with minimal value `func(element)` | action
+`sum()/sum(projection)` | Returns the sum of elements possibly using a projection | action
+`product()/product(projection)` | Returns the product of elements possibly using a projection | action
+`average()/average(projection)` | Returns the average of elements possibly using a projection | action
+`aggregate(func)/aggregate(seed, func)/aggregate(seed, func, result_map)` | Aggregate using `func` starting with `seed` or first element of list then apply `result_map` to the result | action
+`fold_left(zero_value, func)` | Reduces element from left to right using `func` and initial value `zero_value` | action
+`fold_right(zero_value, func)` | Reduces element from right to left using `func` and initial value `zero_value` | action
+`make_string(separator)` | Returns string with `separator` between each `str(element)` | action
+`dict(default=None)` / `to_dict(default=None)` | Converts a sequence of `(Key, Value)` pairs to a `dictionary`. If `default` is not None, it must be a value or zero argument callable which will be used to create a `collections.defaultdict` | action
+`list()` / `to_list()` | Converts sequence to a list | action
+`set() / to_set()` | Converts sequence to a set | action
+`to_file(path)` | Saves the sequence to a file at path with each element on a newline | action
+`to_csv(path)` | Saves the sequence to a csv file at path with each element representing a row | action
+`to_jsonl(path)` | Saves the sequence to a jsonl file with each element being transformed to json and printed to a new line | action
+`to_json(path)` | Saves the sequence to a json file. The contents depend on if the json root is an array or dictionary | action
+`to_sqlite3(conn, tablename_or_query, *args, **kwargs)` | Save the sequence to a SQLite3 db. The target table must be created in advance. | action
+`to_pandas(columns=None)` | Converts the sequence to a pandas DataFrame | action
+`cache()` | Forces evaluation of sequence immediately and caches the result | action
+`for_each(func)` | Executes `func` on each element of the sequence | action
+### Lazy Execution
+Whenever possible, `PyFunctional` will compute lazily. This is accomplished by tracking the list
+of transformations that have been applied to the sequence and only evaluating them when an action is
+called. In `PyFunctional` this is called tracking lineage. This is also responsible for the
+ability for `PyFunctional` to cache results of computation to prevent expensive re-computation.
+This is predominantly done to preserve sensible behavior and used sparingly. For example, calling
+`size()` will cache the underlying sequence. If this was not done and the input was an iterator,
+then further calls would operate on an expired iterator since it was used to compute the length.
+Similarly, `repr` also caches since it is most often used during interactive sessions where its
+undesirable to keep recomputing the same value. Below are some examples of inspecting lineage.
+```python
+def times_2(x):
+ print(x)
+ return 2 * x
+elements = seq(1, 1, 2, 3, 4).map(times_2).distinct()
+elements._lineage
+# Lineage: sequence -> map(times_2) -> distinct
+l_elements = elements.to_list()
+# Prints: 1
+# Prints: 1
+# Prints: 2
+# Prints: 3
+# Prints: 4
+elements._lineage
+# Lineage: sequence -> map(times_2) -> distinct -> cache
+l_elements = elements.to_list()
+# The cached result is returned so times_2 is not called and nothing is printed
+```
+Files are given special treatment if opened through the `seq.open` and related APIs.
+`functional.util.ReusableFile` implements a wrapper around the standard python file to support
+multiple iteration over a single file object while correctly handling iteration termination and
+file closing.
+## Road Map Idea
+* SQL based query planner and interpreter
+* `_` lambda operator
+## Contributing and Bug Fixes
+Any contributions or bug reports are welcome. Thus far, there is a 100% acceptance rate for pull
+requests and contributors have offered valuable feedback and critique on code. It is great to hear
+from users of the package, especially what it is used for, what works well, and what could be
+improved.
+To contribute, create a fork of `PyFunctional`, make your changes, then make sure that they pass.
+In order to be merged, all pull requests must:
+* Pass all the unit tests
+* Pass all the pylint tests, or ignore warnings with explanation of why its correct to do so
+* Not significantly reduce covrage without a good reason [coveralls.io](coveralls.io/github/EntilZha/PyFunctional))
+* Edit the `CHANGELOG.md` file in the `Next Release` heading with changes
+## Contact
+[Gitter for chat](https://gitter.im/EntilZha/PyFunctional)
+## Supported Python Versions
+* `PyFunctional` 1.4 and above supports and is tested against Python 3.6, Python 3.7, and PyPy3
+* `PyFunctional` 1.4 and above does not support python 2.7
+* `PyFunctional` 1.4 and above works in Python 3.5, but is not tested against it
+* `PyFunctional` 1.4 and above partially works in 3.8, parallel processing currently has issues, but other feature work fine
+* `PyFunctional` 1.3 and below supports and was tested against Python 2.7, Python 3.5, Python 3.6, PyPy2, and PyPy3
+## Changelog
+[Changelog](https://github.com/EntilZha/PyFunctional/blob/master/CHANGELOG.md)
+## About me
+To learn more about me (the author) visit my webpage at
+[pedro.ai](https://www.pedro.ai).
+I created `PyFunctional` while using Python extensivel, and finding that I missed the
+ease of use for manipulating data that Spark RDDs and Scala collections have. The project takes the
+best ideas from these APIs as well as LINQ to provide an easy way to manipulate data when using
+Scala is not an option or PySpark is overkill.
+## Contributors
+These people have generously contributed their time to improving `PyFunctional`
+* [versae](https://github.com/versae)
+* [adrian17](https://github.com/adrian17)
+* [lucidfrontier45](https://github.com/lucidfrontier45)
+* [Digenis](https://github.com/Digenis)
+* [ChuyuHsu](https://github.com/ChuyuHsu)
+* [jsemric](https://github.com/jsemric)
+
+%prep
+%autosetup -n pyfunctional-1.4.3
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-pyfunctional -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Mon Apr 10 2023 Python_Bot <Python_Bot@openeuler.org> - 1.4.3-1
+- Package Spec generated