Skip to content

Commit 8a7d781

Browse files
committed
Add docstrings
1 parent 6afdcf4 commit 8a7d781

17 files changed

+280
-46
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
.venv
55
test-basic
66
.coverage
7+
*.pypi-token.gpg
8+
dist
9+
dirdiff.egg-info

dirdiff/cli.py

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323

2424

2525
def parse_args(args=None) -> argparse.Namespace:
26+
"""
27+
Parse command line or passed arguments return the parsed namespace object
28+
as given from the argparse module.
29+
"""
2630
parser = argparse.ArgumentParser(
2731
description="Computes the directory difference `upper = merged - lower`"
2832
)
@@ -38,6 +42,8 @@ def parse_args(args=None) -> argparse.Namespace:
3842
"--diff-type",
3943
default="overlay",
4044
choices=DIFF_CLASSES,
45+
help="Selects the kind of diff to perform. "
46+
"Mostly this affects how deletions are represented.",
4147
)
4248
parser.add_argument(
4349
"--output-type",
@@ -117,6 +123,7 @@ def parse_args(args=None) -> argparse.Namespace:
117123

118124

119125
def setup_logging(verbose: int) -> None:
126+
"""Set our logging level and format based on verbosity level"""
120127
log_level = logging.ERROR
121128
log_format = "%(message)s"
122129
if verbose > 2:
@@ -186,6 +193,7 @@ def _get_backend(
186193

187194

188195
def main(args=None) -> int:
196+
"""Main CLI entrypoint, optionally using passed arguments rather than sys.argv"""
189197
args = parse_args(args=args)
190198
setup_logging(1 + args.verbose - args.quiet)
191199

dirdiff/differ.py

+58
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@
3939

4040

4141
class DirEntryType(Enum):
42+
"""Simple enum of basic file type categories"""
43+
4244
DIRECTORY = 1
4345
REGULAR_FILE = 2
4446
OTHER = 3
4547

4648

4749
def _dir_entry_type(dir_entry: os.DirEntry) -> DirEntryType:
50+
"""Compute the high level file type from a dir entry"""
4851
if dir_entry.is_dir(follow_symlinks=False):
4952
return DirEntryType.DIRECTORY
5053
if dir_entry.is_file(follow_symlinks=False):
@@ -54,6 +57,8 @@ def _dir_entry_type(dir_entry: os.DirEntry) -> DirEntryType:
5457

5558
@dataclasses.dataclass
5659
class DifferOptions:
60+
"""Dataclass containing options to control diff behavior"""
61+
5762
output_uid: Optional[int] = None
5863
output_gid: Optional[int] = None
5964
scrub_mtime: bool = True
@@ -118,6 +123,20 @@ def _invoke(differ: "Differ", *args, **kwargs):
118123

119124

120125
class Differ:
126+
"""
127+
Class responsible for performing the complete recursive directory difference
128+
on the merged and lower direcotires. The merged_dir/lower_dir arguments must
129+
either be a path-like pointer to an existing directory or a TarFile object.
130+
131+
Parameters:
132+
merged_dir: This is the left-hand side of the directory difference. This
133+
can be a path-like object or a tar archive.
134+
lower_dir: This is the right-hand side of the directory difference. This
135+
can be a path-like object or a tar archive.
136+
output: This is a DiffOutput instance that actually writes diff results
137+
options: Additional options that govern diff output and handling of errors
138+
"""
139+
121140
def __init__(
122141
self,
123142
merged_dir: DifferPathLike,
@@ -135,6 +154,11 @@ def __init__(
135154

136155
@_new_stack
137156
def diff(self) -> None:
157+
"""
158+
Main diff entrypoint that starts the diff of the merged and lower directories/archives.
159+
160+
Any failures not ignored by the differ options will raised as a DirDiffException.
161+
"""
138162
try:
139163
merged = self._cur_stack.enter_context(_open_dir(self.merged_dir))
140164
except IOErrors as exc:
@@ -150,6 +174,12 @@ def diff(self) -> None:
150174
self._diff_dirs(".", merged, lower)
151175

152176
def _input_error(self, operand: str, path: str, verb: str) -> None:
177+
"""
178+
Handle an input error.
179+
180+
Either propagates the error or simply logs it depending on the
181+
error handler settings.
182+
"""
153183
_, exc, _ = sys.exc_info()
154184
if exc is not None:
155185
msg = f"error {verb} path={path!r} of {operand}: {exc}"
@@ -160,6 +190,12 @@ def _input_error(self, operand: str, path: str, verb: str) -> None:
160190
LOGGER.warning("ignoring %s", msg)
161191

162192
def _output_error(self, path: str, verb: str) -> None:
193+
"""
194+
Handle an output error.
195+
196+
Either propagates the error or simply logs it depending on the
197+
error handler settings.
198+
"""
163199
_, exc, _ = sys.exc_info()
164200
if exc is not None:
165201
msg = f"error {verb} path={path!r}: {exc}"
@@ -170,9 +206,11 @@ def _output_error(self, path: str, verb: str) -> None:
170206
LOGGER.warning("ignoring %s", msg)
171207

172208
def _input_error_merged(self, path: str, verb: str) -> None:
209+
"""Handle an input error reading from the merged directory"""
173210
self._input_error(OPERAND_MERGED, path, verb)
174211

175212
def _input_error_lower(self, path: str, verb: str) -> None:
213+
"""Handle an input error reading from the lower directory"""
176214
self._input_error(OPERAND_LOWER, path, verb)
177215

178216
@_new_stack
@@ -182,6 +220,9 @@ def _diff_dirs(
182220
merged: DirectoryManager,
183221
lower: DirectoryManager,
184222
) -> None:
223+
"""
224+
Helper method for recursively diffing two directories in the merged and lower
225+
"""
185226
stack = self._cur_stack
186227
LOGGER.debug("Diffing dirs %s", archive_path)
187228

@@ -267,6 +308,7 @@ def _diff_files(
267308
merged: FileManager,
268309
lower: FileManager,
269310
) -> None:
311+
"""Helper method for diffing two regular files in the merged and lower"""
270312
stack = self._cur_stack
271313
LOGGER.debug("Diffing files %s", archive_path)
272314

@@ -334,6 +376,13 @@ def _diff_other(
334376
merged: PathManager,
335377
lower: PathManager,
336378
) -> None:
379+
"""
380+
Helper method for diffing two special files in the merged and lower.
381+
382+
"Special" in this case means anything that's not either a directory or
383+
a regular file. The files may not have the same file modes so this method
384+
is responsible for checking that as well.
385+
"""
337386
stack = self._cur_stack
338387
LOGGER.debug("Diffing other %s", archive_path)
339388

@@ -364,6 +413,12 @@ def _diff_other(
364413
self._insert_other(archive_path, merged)
365414

366415
def _flush_pending(self) -> None:
416+
"""
417+
Flush any pending directory entries to the output. We do this before
418+
writing any other entries into an archive to ensure its parents have
419+
been written first. We delay writting the parents because if their are
420+
no differences in its children we can omit writing an entry for it at all.
421+
"""
367422
for archive_path, dir_stat in self._dir_pending:
368423
LOGGER.debug("Inserting directory metadata %s", archive_path)
369424
try:
@@ -378,6 +433,7 @@ def _insert_dir(
378433
archive_path: str,
379434
obj: DirectoryManager,
380435
) -> None:
436+
"""Recursively write a directory to our outout"""
381437
stack = self._cur_stack
382438
self._flush_pending()
383439
LOGGER.debug("Recursively inserting directory %s", archive_path)
@@ -410,6 +466,7 @@ def _insert_file(
410466
archive_path: str,
411467
obj: FileManager,
412468
) -> None:
469+
"""Write a file to our outout"""
413470
stack = self._cur_stack
414471
self._flush_pending()
415472
LOGGER.debug("Inserting file %s", archive_path)
@@ -436,6 +493,7 @@ def _insert_other(
436493
archive_path: str,
437494
obj: PathManager,
438495
) -> None:
496+
"""Write any other special file type to our outout"""
439497
stack = self._cur_stack
440498
self._flush_pending()
441499
LOGGER.debug("Inserting other %s", archive_path)

dirdiff/exceptions.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
class DirDiffException(Exception):
2+
"""
3+
Generic base exception for any expected failure in dirdiff. If the exception
4+
raises to the top level the CLI will simply print the exception message and
5+
exit with the passed exit_code.
6+
"""
7+
28
def __init__(self, msg: str, *, exit_code: int = 1) -> None:
39
super().__init__(msg)
410
self.exit_code = exit_code
511

612

713
class DirDiffIOException(DirDiffException):
8-
pass
14+
"""Any exception relating to an I/O failure"""
915

1016

1117
class DirDiffInputException(DirDiffIOException):
12-
pass
18+
"""An input error exception"""
1319

1420

1521
class DirDiffOutputException(DirDiffIOException):
16-
pass
22+
"""An output error exception"""

0 commit comments

Comments
 (0)