Static type checking with mypy

This does introduce some not-so-nice things, like having to annotate each
`__init__` function with `-> None`. However, the benefits of having static
type checking in a complex bit of software like BAT outweigh the downsides.
This commit is contained in:
Sybren A. Stüvel
2018-03-09 11:09:47 +01:00
parent 632d01334c
commit fdbbc3a20d
18 changed files with 117 additions and 82 deletions
+11 -6
View File
@@ -19,19 +19,23 @@ class PathAction(enum.Enum):
class AssetAction:
def __init__(self):
"""All the info required to rewrite blend files and copy assets."""
def __init__(self) -> None:
self.path_action = PathAction.KEEP_PATH
self.usages = []
self.usages = [] # type: typing.List[result.BlockUsage]
"""BlockUsage objects referring to this asset.
Those BlockUsage objects could refer to data blocks in this blend file
(if the asset is a blend file) or in another blend file.
"""
self.new_path = None
self.new_path = None # type: pathlib.Path
"""Absolute path to the asset in the BAT Pack."""
self.rewrites = []
self.read_from = None # type: pathlib.Path
self.rewrites = [] # type: typing.List[result.BlockUsage]
"""BlockUsage objects in this asset that may require rewriting.
Empty list if this AssetAction is not for a blend file.
@@ -43,7 +47,7 @@ class Packer:
blendfile: pathlib.Path,
project: pathlib.Path,
target: pathlib.Path,
noop=False):
noop=False) -> None:
self.blendfile = blendfile
self.project = project
self.target = target
@@ -55,7 +59,8 @@ class Packer:
log.warning('Running in no-op mode, only showing what will be done.')
# Filled by strategise()
self._actions = collections.defaultdict(AssetAction)
self._actions = collections.defaultdict(
AssetAction) # type: typing.DefaultDict[pathlib.Path, AssetAction]
# Number of files we would copy, if not for --noop
self._file_count = 0
+4 -3
View File
@@ -11,7 +11,7 @@ log = logging.getLogger(__name__)
class FileCopyError(IOError):
"""Raised when one or more files could not be copied."""
def __init__(self, message, files_not_copied: typing.List[pathlib.Path]):
def __init__(self, message, files_not_copied: typing.List[pathlib.Path]) -> None:
super().__init__(message)
self.files_not_copied = files_not_copied
@@ -19,7 +19,7 @@ class FileCopyError(IOError):
class FileCopier(threading.Thread):
"""Copies files in directory order."""
def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
# For copying in a different process. By using a priority queue the files
@@ -31,7 +31,8 @@ class FileCopier(threading.Thread):
# maxsize=100 is just a guess as to a reasonable upper limit. When this limit
# is reached, the main thread will simply block while waiting for this thread
# to finish copying a file.
self.file_copy_queue = queue.PriorityQueue(maxsize=100)
self.file_copy_queue = queue.PriorityQueue(
maxsize=100) # type: queue.PriorityQueue[typing.Tuple[pathlib.Path, pathlib.Path]]
self.file_copy_done = threading.Event()
def queue(self, src: pathlib.Path, dst: pathlib.Path):