Skip to content

Commit 90a48bd

Browse files
committed
Add typing
1 parent bd72190 commit 90a48bd

File tree

7 files changed

+90
-22
lines changed

7 files changed

+90
-22
lines changed

getdents/__init__.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
2+
from typing import Iterator, Tuple
23

3-
from ._getdents import ( # noqa: ignore=F401
4+
from ._getdents import (
45
DT_BLK,
56
DT_CHR,
67
DT_DIR,
@@ -14,8 +15,10 @@
1415
getdents_raw,
1516
)
1617

18+
DirectoryEntry = Tuple[int, int, str]
1719

18-
def getdents(path, buff_size=32768):
20+
21+
def getdents(path: str, buff_size: int = 32768) -> Iterator[DirectoryEntry]:
1922
"""Get directory entries.
2023
2124
Wrapper around getdents_raw(), simulates ls behaviour: ignores deleted
@@ -48,3 +51,19 @@ def getdents(path, buff_size=32768):
4851
)
4952
finally:
5053
os.close(fd)
54+
55+
56+
__all__ = [
57+
'DT_BLK',
58+
'DT_CHR',
59+
'DT_DIR',
60+
'DT_FIFO',
61+
'DT_LNK',
62+
'DT_REG',
63+
'DT_SOCK',
64+
'DT_UNKNOWN',
65+
'MIN_GETDENTS_BUFF_SIZE',
66+
'O_GETDENTS',
67+
'getdents',
68+
'getdents_raw',
69+
]

getdents/_getdents.pyi

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from typing import Iterator, Tuple
2+
3+
DT_BLK: int
4+
DT_CHR: int
5+
DT_DIR: int
6+
DT_FIFO: int
7+
DT_LNK: int
8+
DT_REG: int
9+
DT_SOCK: int
10+
DT_UNKNOWN: int
11+
MIN_GETDENTS_BUFF_SIZE: int
12+
O_GETDENTS: int
13+
14+
def getdents_raw(fd: int, buff_size: int) -> Iterator[Tuple[int, int, str]]: ...

getdents/cli.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
from argparse import ArgumentParser
2-
from sys import stderr
2+
from sys import stderr, stdout
3+
from typing import List, Optional, Tuple
34

45
from . import MIN_GETDENTS_BUFF_SIZE, getdents
5-
from .formatters import FORMATTERS
6+
from .formatters import FORMATTERS, Formatter
67

78

8-
def parse_args(args, prog):
9+
def parse_args(
10+
args: Optional[List[str]],
11+
prog: Optional[str],
12+
) -> Tuple[str, int, Formatter]:
913
parser = ArgumentParser(
1014
prog=prog,
1115
description='Print directory contents.',
@@ -38,11 +42,11 @@ def parse_args(args, prog):
3842
return parsed_args.path, buff_size, FORMATTERS[parsed_args.output_format]
3943

4044

41-
def main(args=None, prog=None):
45+
def main(args: Optional[List[str]] = None, prog: Optional[str] = None) -> int:
4246
path, buff_size, fmt = parse_args(args, prog)
4347

4448
try:
45-
fmt(getdents(path, buff_size=buff_size))
49+
fmt(getdents(path, buff_size=buff_size), stdout)
4650
except MemoryError:
4751
print(
4852
'Not enough memory to allocate', buff_size, 'bytes of data',

getdents/formatters.py

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
from itertools import chain
33
from json import dumps as json_dumps
44
from sys import stdout
5+
from typing import Callable, Dict, Iterable, TextIO
56

6-
from ._getdents import (
7+
from . import (
78
DT_BLK,
89
DT_CHR,
910
DT_DIR,
@@ -12,11 +13,13 @@
1213
DT_REG,
1314
DT_SOCK,
1415
DT_UNKNOWN,
16+
DirectoryEntry,
1517
)
1618

1719

20+
Formatter = Callable[[Iterable[DirectoryEntry], TextIO], None]
1821
HEADER = ('inode', 'type', 'name')
19-
FORMATTERS = {}
22+
FORMATTERS: Dict[str, Formatter] = {}
2023
TYPE_NAMES = {
2124
DT_BLK: 'blk',
2225
DT_CHR: 'chr',
@@ -29,26 +32,35 @@
2932
}
3033

3134

32-
def formatter(name, registry=FORMATTERS):
33-
def deco(fn):
35+
def formatter(
36+
name: str,
37+
registry: Dict[str, Formatter] = FORMATTERS,
38+
) -> Callable[[Formatter], Formatter]:
39+
def deco(fn: Formatter) -> Formatter:
3440
registry[name] = fn
3541
return fn
3642
return deco
3743

3844

3945
@formatter('plain')
40-
def format_plain(directory_entries, file=stdout):
46+
def format_plain(
47+
directory_entries: Iterable[DirectoryEntry],
48+
file: TextIO = stdout,
49+
) -> None:
4150
for inode, type, name in directory_entries:
4251
print(name, file=file)
4352

4453

4554
class Echo:
46-
def write(self, value):
55+
def write(self, value: str) -> str:
4756
return value
4857

4958

50-
@formatter('csv')
51-
def format_csv(directory_entries, file=stdout, headers=False):
59+
def _format_csv(
60+
directory_entries: Iterable[DirectoryEntry],
61+
file: TextIO = stdout,
62+
headers: bool = False,
63+
) -> None:
5264
writer = csv_writer(Echo())
5365

5466
for first in directory_entries:
@@ -62,12 +74,23 @@ def format_csv(directory_entries, file=stdout, headers=False):
6274
)
6375

6476

77+
@formatter('csv')
78+
def format_csv(
79+
directory_entries: Iterable[DirectoryEntry],
80+
file: TextIO = stdout,
81+
) -> None:
82+
return _format_csv(directory_entries, file, False)
83+
84+
6585
@formatter('csv-headers')
66-
def format_csv_headers(directory_entries, file=stdout):
67-
return format_csv(directory_entries, file=file, headers=True)
86+
def format_csv_headers(
87+
directory_entries: Iterable[DirectoryEntry],
88+
file: TextIO = stdout,
89+
) -> None:
90+
return _format_csv(directory_entries, file, True)
6891

6992

70-
def json_encode(inode, type, name):
93+
def json_encode(inode: int, type: int, name: str) -> str:
7194
return json_dumps({
7295
'inode': inode,
7396
'type': TYPE_NAMES[type],
@@ -76,7 +99,10 @@ def json_encode(inode, type, name):
7699

77100

78101
@formatter('json')
79-
def format_json(directory_entries, file=stdout):
102+
def format_json(
103+
directory_entries: Iterable[DirectoryEntry],
104+
file: TextIO = stdout,
105+
) -> None:
80106
for inode, type, name in directory_entries:
81107
print(
82108
'[\n', json_encode(inode, type, name),
@@ -93,6 +119,9 @@ def format_json(directory_entries, file=stdout):
93119

94120

95121
@formatter('json-stream')
96-
def format_json_stream(directory_entries, file=stdout):
122+
def format_json_stream(
123+
directory_entries: Iterable[DirectoryEntry],
124+
file: TextIO = stdout,
125+
) -> None:
97126
for inode, type, name in directory_entries:
98127
print(json_encode(inode, type, name), file=file)

getdents/py.typed

Whitespace-only changes.

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
license='BSD-2-Clause',
2525
packages=find_packages(exclude=['tests']),
2626
include_package_data=True,
27+
package_data={'getdents': ['py.typed']},
2728
zip_safe=False,
2829
extras_require={
2930
'test': tests_require,

tests/test_cli.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import re
2+
from sys import stdout
23

34
import pretend
45

@@ -40,7 +41,7 @@ def test_main(monkeypatch):
4041
directory_entries = pretend.stub()
4142

4243
@pretend.call_recorder
43-
def format_test(directory_entries):
44+
def format_test(directory_entries, file):
4445
pass
4546

4647
@pretend.call_recorder
@@ -52,7 +53,7 @@ def getdents(path, buff_size=32768):
5253

5354
assert main(['x', '-o', 'test', '-b', '1024'], 'test') == 0
5455
assert getdents.calls == [pretend.call('x', buff_size=1024)]
55-
assert format_test.calls == [pretend.call(directory_entries)]
56+
assert format_test.calls == [pretend.call(directory_entries, stdout)]
5657

5758

5859
def test_main_memory_error(monkeypatch):

0 commit comments

Comments
 (0)