Skip to content

Commit 2f840cd

Browse files
committed
remove todo, tweak ci, typing adjustments
1 parent 8a7fbaa commit 2f840cd

File tree

6 files changed

+60
-49
lines changed

6 files changed

+60
-49
lines changed

.github/workflows/pythonpackage.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,21 @@ jobs:
3434
run: poetry run pylint functional
3535
- name: black
3636
run: poetry run black --check --diff --color functional
37-
if: always()
37+
if: success() || failure()
3838
- name: Test with pytest
3939
run: poetry run pytest --cov=functional --cov-report=xml
40-
if: always()
40+
if: success() || failure()
4141
- name: mypy
4242
run: poetry run mypy --warn-unused-configs --check-untyped-defs --warn-redundant-casts --warn-unused-ignores --extra-checks functional
43-
if: always()
43+
if: success() || failure()
4444
- uses: tsuyoshicho/action-mypy@v4
4545
with:
4646
github_token: ${{ secrets.GITHUB_TOKEN }}
4747
reporter: github-pr-review
4848
level: warning
4949
execute_command: poetry run mypy --strict
5050
filter_mode: nofilter
51-
if: matrix.python-version == '3.11' # run only on latest to avoid duplicate warnings
51+
if: (success() || failure()) && matrix.python-version == '3.11' # run only on latest to avoid duplicate warnings
5252
- uses: codecov/codecov-action@v1
5353
with:
5454
file: ./coverage.xml

functional/io.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
import gzip
66
import io
77
import lzma
8-
from os import PathLike
8+
from pathlib import Path
99
from typing import Any, Optional
1010

1111
from typing_extensions import TypeAlias
1212

13-
# from typeshed
14-
StrOrBytesPath: TypeAlias = str | bytes | PathLike
13+
# adapted from typeshed
14+
StrOrBytesPath: TypeAlias = str | bytes | Path
1515
FileDescriptorOrPath: TypeAlias = int | StrOrBytesPath
1616

1717
WRITE_MODE = "wt"
@@ -28,7 +28,7 @@ class ReusableFile:
2828
# pylint: disable=too-many-instance-attributes
2929
def __init__(
3030
self,
31-
path: FileDescriptorOrPath,
31+
path: StrOrBytesPath,
3232
delimiter: Optional[str] = None,
3333
mode: str = "r",
3434
buffering: int = -1,
@@ -91,7 +91,7 @@ class CompressedFile(ReusableFile):
9191
# pylint: disable=too-many-instance-attributes
9292
def __init__(
9393
self,
94-
path: FileDescriptorOrPath,
94+
path: StrOrBytesPath,
9595
delimiter: Optional[str] = None,
9696
mode: str = "rt",
9797
buffering: int = -1,
@@ -122,7 +122,7 @@ class GZFile(CompressedFile):
122122
# pylint: disable=too-many-instance-attributes
123123
def __init__(
124124
self,
125-
path: FileDescriptorOrPath,
125+
path: StrOrBytesPath,
126126
delimiter: Optional[str] = None,
127127
mode: str = "rt",
128128
buffering: int = -1,
@@ -177,7 +177,7 @@ class BZ2File(CompressedFile):
177177
# pylint: disable=too-many-instance-attributes
178178
def __init__(
179179
self,
180-
path: FileDescriptorOrPath,
180+
path: StrOrBytesPath,
181181
delimiter: Optional[str] = None,
182182
mode: str = "rt",
183183
buffering: int = -1,
@@ -299,7 +299,7 @@ def get_read_function(filename: FileDescriptorOrPath, disable_compression: bool)
299299

300300

301301
def universal_write_open(
302-
path: FileDescriptorOrPath,
302+
path: StrOrBytesPath,
303303
mode: str,
304304
buffering: int = -1,
305305
encoding: Optional[str] = None,

functional/pipeline.py

+22-20
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
from __future__ import annotations
6+
import builtins
67

78
import collections
89
import csv
@@ -23,6 +24,7 @@
2324
Optional,
2425
TypeVar,
2526
Union,
27+
cast,
2628
overload,
2729
)
2830

@@ -31,7 +33,7 @@
3133

3234
from functional import transformations
3335
from functional.execution import ExecutionEngine, ExecutionStrategies
34-
from functional.io import WRITE_MODE, FileDescriptorOrPath, universal_write_open
36+
from functional.io import WRITE_MODE, StrOrBytesPath, universal_write_open
3537
from functional.lineage import Lineage
3638
from functional.util import (
3739
SupportsRichComparisonT,
@@ -173,7 +175,7 @@ def __nonzero__(self) -> bool:
173175
"""
174176
return self.len() != 0
175177

176-
def __getitem__(self, item: int) -> T | Sequence: # TODO
178+
def __getitem__(self, item: int) -> T | Sequence:
177179
"""
178180
Gets item at given index.
179181
@@ -212,7 +214,7 @@ def __add__(self, other) -> Sequence[T]:
212214
else:
213215
return Sequence(self.sequence + other, no_wrap=self.no_wrap)
214216

215-
def _evaluate(self) -> Iterable[str]:
217+
def _evaluate(self) -> Iterable:
216218
"""
217219
Creates and returns an iterator which applies all the transformations in the lineage
218220
@@ -1483,7 +1485,7 @@ def to_dict(
14831485
...
14841486

14851487
def to_dict(
1486-
self: Sequence[tuple[U, V]], default: Optional[Callable[[], V]] = None
1488+
self: Sequence[tuple[U, V]], default: Callable[[], V] | V | None = None
14871489
) -> dict[U, V] | collections.defaultdict[U, V]:
14881490
"""
14891491
Converts sequence of (Key, Value) pairs to a dictionary.
@@ -1505,7 +1507,7 @@ def to_dict(
15051507
return dictionary
15061508
else:
15071509
return collections.defaultdict(
1508-
default if callable(default) else lambda: default, dictionary
1510+
default if callable(default) else lambda: cast(V, default), dictionary
15091511
)
15101512

15111513
@overload
@@ -1541,19 +1543,19 @@ def dict(
15411543
# pylint: disable=too-many-locals
15421544
def to_file(
15431545
self,
1544-
path: FileDescriptorOrPath,
1545-
delimiter=None,
1546-
mode="wt",
1547-
buffering=-1,
1548-
encoding=None,
1549-
errors=None,
1550-
newline=None,
1551-
compresslevel=9,
1552-
format=None,
1553-
check=-1,
1554-
preset=None,
1555-
filters=None,
1556-
compression=None,
1546+
path: StrOrBytesPath,
1547+
delimiter: Optional[str] = None,
1548+
mode: str = "wt",
1549+
buffering: int = -1,
1550+
encoding: Optional[str] = None,
1551+
errors: Optional[str] = None,
1552+
newline: Optional[str] = None,
1553+
compresslevel: int = 9,
1554+
format: Optional[int] = None,
1555+
check: int = -1,
1556+
preset: Optional[int] = None,
1557+
filters: Optional[Iterable[builtins.dict]] = None,
1558+
compression: Optional[str] = None,
15571559
):
15581560
"""
15591561
Saves the sequence to a file by executing str(self) which becomes str(self.to_list()). If
@@ -1594,9 +1596,9 @@ def to_file(
15941596

15951597
def to_jsonl(
15961598
self,
1597-
path: FileDescriptorOrPath,
1599+
path: StrOrBytesPath,
15981600
mode: str = "wb",
1599-
compression: Optional[bool] = None,
1601+
compression: Optional[str] = None,
16001602
):
16011603
"""
16021604
Saves the sequence to a jsonl file. Each element is mapped using json.dumps then written

functional/streams.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import builtins
44
import csv as csvapi
55
import json as jsonapi
6+
from pathlib import Path
67
import re
78
import sqlite3 as sqlite3api
89
from itertools import chain
@@ -218,7 +219,7 @@ def csv(
218219
:param fmt_params: options passed to csv.reader
219220
:return: Sequence wrapping csv file
220221
"""
221-
if isinstance(csv_file, FileDescriptorOrPath):
222+
if isinstance(csv_file, (int, str, bytes, Path)):
222223
file_open = get_read_function(csv_file, self.disable_compression)
223224
input_file = file_open(csv_file)
224225
elif hasattr(csv_file, "next") or hasattr(csv_file, "__next__"):
@@ -240,7 +241,7 @@ def csv_dict_reader(
240241
dialect="excel",
241242
**kwds,
242243
):
243-
if isinstance(csv_file, FileDescriptorOrPath):
244+
if isinstance(csv_file, (int, str, bytes, Path)):
244245
file_open = get_read_function(csv_file, self.disable_compression)
245246
input_file = file_open(csv_file)
246247
elif hasattr(csv_file, "next") or hasattr(csv_file, "__next__"):
@@ -273,7 +274,7 @@ def jsonl(self, jsonl_file: FileDescriptorOrPath | Iterable[str]):
273274
:param jsonl_file: path or file containing jsonl content
274275
:return: Sequence wrapping jsonl file
275276
"""
276-
if isinstance(jsonl_file, FileDescriptorOrPath):
277+
if isinstance(jsonl_file, (int, str, bytes, Path)):
277278
file_open = get_read_function(jsonl_file, self.disable_compression)
278279
input_file = file_open(jsonl_file)
279280
else:
@@ -298,7 +299,7 @@ def json(self, json_file: FileDescriptorOrPath | IO) -> Sequence[Any]:
298299
:param json_file: path or file containing json content
299300
:return: Sequence wrapping jsonl file
300301
"""
301-
if isinstance(json_file, FileDescriptorOrPath):
302+
if isinstance(json_file, (str, bytes, Path)):
302303
file_open = get_read_function(json_file, self.disable_compression)
303304
input_file = file_open(json_file)
304305
json_input = jsonapi.load(input_file)

functional/transformations.py

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from __future__ import annotations
22

33
import collections
4+
import collections.abc
45
import types
5-
import typing
6-
from collections.abc import Callable, Iterable
6+
from collections.abc import Callable, Iterable, Set
77
from functools import partial
88
from itertools import (
99
accumulate,
@@ -15,20 +15,26 @@
1515
starmap,
1616
takewhile,
1717
)
18-
from typing import NamedTuple, Optional, TypeVar
18+
from typing import TYPE_CHECKING, NamedTuple, Optional, TypeVar
19+
1920
from functional.execution import ExecutionStrategies
21+
from functional.util import identity
22+
23+
if TYPE_CHECKING:
24+
from functional.pipeline import Sequence
2025

2126

2227
class Transformation(NamedTuple):
2328
name: str
24-
function: Optional[Callable[[Iterable], Iterable]]
25-
execution_strategies: set[ExecutionStrategies] = {}
29+
function: Callable[[Iterable], Iterable]
30+
execution_strategies: Set[int] = frozenset()
2631

2732

2833
T = TypeVar("T")
2934

3035
#: Cache transformation
31-
CACHE_T = Transformation("cache", None)
36+
CACHE_T = Transformation("cache", identity)
37+
# this identity will not be used but it's to comply with typing
3238

3339

3440
def name(function: Callable) -> str:
@@ -43,13 +49,13 @@ def name(function: Callable) -> str:
4349
return str(function)
4450

4551

46-
def listify(sequence: Iterable[T]) -> typing.Sequence[T]:
52+
def listify(sequence: Iterable[T]) -> collections.abc.Sequence[T]:
4753
"""
4854
Convert an iterable to a list
4955
:param sequence: sequence to convert
5056
:return: list
5157
"""
52-
if isinstance(sequence, typing.Sequence):
58+
if isinstance(sequence, collections.abc.Sequence):
5359
return sequence
5460
return list(sequence)
5561

@@ -107,7 +113,7 @@ def _reverse_iter(iterable: Iterable[T]) -> Iterable[T]:
107113
:return: reversed iterable
108114
"""
109115
try: # avoid a copy if we can
110-
return reversed(iterable)
116+
return reversed(iterable) # type: ignore
111117
except TypeError:
112118
return reversed(list(iterable))
113119

@@ -278,7 +284,7 @@ def tail_t() -> Transformation:
278284
return Transformation("tail", lambda sequence: islice(sequence, 1, None))
279285

280286

281-
def _inits(sequence: Iterable[T], wrap) -> list[typing.Sequence[T]]:
287+
def _inits(sequence: Iterable[T], wrap) -> list[Sequence[T]]:
282288
"""
283289
Implementation for inits_t
284290
:param sequence: sequence to inits
@@ -297,7 +303,7 @@ def inits_t(wrap):
297303
return Transformation("inits", partial(_inits, wrap=wrap))
298304

299305

300-
def _tails(sequence: Iterable[T], wrap) -> list[typing.Sequence[T]]:
306+
def _tails(sequence: Iterable[T], wrap) -> list[Sequence[T]]:
301307
"""
302308
Implementation for tails_t
303309
:param sequence: sequence to tails

functional/util.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from functools import reduce
66
from itertools import chain, count, islice, takewhile
77
from multiprocessing import Pool, cpu_count
8-
from typing import Any, Callable, Optional, Protocol, Sized, TypeVar, Union
8+
from typing import Any, Callable, Optional, Protocol, Sized, TypeVar, Union, cast
99

1010
import dill as serializer # type: ignore
1111
from typing_extensions import TypeAlias
@@ -190,7 +190,9 @@ def lazy_parallelize(
190190
processes = CPU_COUNT
191191
else:
192192
processes = min(processes, CPU_COUNT)
193-
partition_size = partition_size or compute_partition_size(seq, processes)
193+
partition_size = partition_size or compute_partition_size(
194+
cast(Sized, seq), processes
195+
)
194196
with Pool(processes=processes) as pool:
195197
partitions = split_every(partition_size, iter(seq))
196198
packed_partitions = (pack(func, (partition,)) for partition in partitions)

0 commit comments

Comments
 (0)