summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2022-02-10 14:52:14 -0800
committerScott Gasch <[email protected]>2022-02-10 14:52:14 -0800
commit2e8dd08f5f4f9624facf4d38ea6b276cc8131f56 (patch)
tree5d9982185ddb95c76669c594d20c2802e49ce89e
parente76081ebdfa078aa8508ba1682dacea80341157e (diff)
More cleanup.
-rw-r--r--ml/quick_label.py35
-rw-r--r--type/centcount.py13
-rw-r--r--type/locations.py6
-rw-r--r--type/money.py12
-rw-r--r--type/people.py6
-rw-r--r--type/rate.py8
6 files changed, 52 insertions, 28 deletions
diff --git a/ml/quick_label.py b/ml/quick_label.py
index 7e0a6bf..da9a1d2 100644
--- a/ml/quick_label.py
+++ b/ml/quick_label.py
@@ -1,10 +1,13 @@
#!/usr/bin/env python3
+"""A helper to facilitate quick manual labeling of ML training data."""
+
import glob
import logging
import os
import warnings
-from typing import Callable, List, NamedTuple, Optional, Set
+from dataclasses import dataclass
+from typing import Callable, List, Optional, Set
import argparse_utils
import config
@@ -35,14 +38,18 @@ parser.add_argument(
)
-class InputSpec(NamedTuple):
- image_file_glob: Optional[str]
- image_file_prepopulated_list: Optional[List[str]]
- image_file_to_features_file: Callable[[str], str]
- label: str
- valid_keystrokes: List[str]
- prompt: str
- keystroke_to_label: Callable[[str], str]
+@dataclass
+class InputSpec:
+ """A wrapper around the input data we need to operate; should be
+ populated by the caller."""
+
+ image_file_glob: Optional[str] = None
+ image_file_prepopulated_list: Optional[List[str]] = None
+ image_file_to_features_file: Optional[Callable[[str], str]] = None
+ label: str = ''
+ valid_keystrokes: List[str] = []
+ prompt: str = ''
+ keystroke_to_label: Optional[Callable[[str], str]] = None
def read_skip_list() -> Set[str]:
@@ -56,7 +63,7 @@ def read_skip_list() -> Set[str]:
line = line[:-1]
line.strip()
ret.add(line)
- logger.debug(f'Read {quick_skip_file} and found {len(ret)} entries.')
+ logger.debug('Read %s and found %d entries.', quick_skip_file, len(ret))
return ret
@@ -68,7 +75,7 @@ def write_skip_list(skip_list) -> None:
filename = filename.strip()
if len(filename) > 0:
f.write(f'{filename}\n')
- logger.debug(f'Updated {quick_skip_file}')
+ logger.debug('Updated %s', quick_skip_file)
def label(in_spec: InputSpec) -> None:
@@ -85,8 +92,9 @@ def label(in_spec: InputSpec) -> None:
skip_list = read_skip_list()
for image in images:
if image in skip_list:
- logger.debug(f'Skipping {image} because of the skip list')
+ logger.debug('Skipping %s because of the skip list', image)
continue
+ assert in_spec.image_file_to_features_file
features = in_spec.image_file_to_features_file(image)
if features is None or not os.path.exists(features):
msg = f'File {image} yielded file {features} which does not exist, SKIPPING.'
@@ -114,9 +122,10 @@ def label(in_spec: InputSpec) -> None:
prompt=in_spec.prompt,
)
os.system('killall xv')
+ assert in_spec.keystroke_to_label
label_value = in_spec.keystroke_to_label(keystroke)
filtered_lines.append(f"{in_spec.label}: {label_value}\n")
with open(features, 'w') as f:
- f.writelines("%s\n" % line for line in filtered_lines)
+ f.writelines(line + '\n' for line in filtered_lines)
skip_list.add(image)
write_skip_list(skip_list)
diff --git a/type/centcount.py b/type/centcount.py
index 2cb99e0..4529695 100644
--- a/type/centcount.py
+++ b/type/centcount.py
@@ -1,7 +1,10 @@
#!/usr/bin/env python3
+"""An amount of money (USD) represented as an integral count of
+cents."""
+
import re
-from typing import Optional, Tuple, TypeVar
+from typing import Optional, Tuple
import math_utils
@@ -36,9 +39,9 @@ class CentCount(object):
a = round(a, 2)
s = f'{a:,.2f}'
if self.currency is not None:
- return '%s %s' % (s, self.currency)
+ return f'{s} {self.currency}'
else:
- return '$%s' % s
+ return f'${s}'
def __pos__(self):
return CentCount(centcount=self.centcount, currency=self.currency)
@@ -181,8 +184,8 @@ class CentCount(object):
def __ge__(self, other):
return self > other or self == other
- def __hash__(self):
- return self.__repr__
+ def __hash__(self) -> int:
+ return hash(self.__repr__)
CENTCOUNT_RE = re.compile(r"^([+|-]?)(\d+)(\.\d+)$")
CURRENCY_RE = re.compile(r"^[A-Z][A-Z][A-Z]$")
diff --git a/type/locations.py b/type/locations.py
index 24ab063..718a5f1 100644
--- a/type/locations.py
+++ b/type/locations.py
@@ -1,10 +1,14 @@
#!/usr/bin/env python3
+"""An enum to represent locations."""
+
import enum
@enum.unique
-class Location(enum.Enum):
+class Location(enum.IntEnum):
+ """An enum to represent locations."""
+
UNKNOWN = 0
HOUSE = 1
CABIN = 2
diff --git a/type/money.py b/type/money.py
index 39557aa..b84652b 100644
--- a/type/money.py
+++ b/type/money.py
@@ -1,8 +1,10 @@
#!/usr/bin/env python3
+"""A class to represent money. See also centcount.py"""
+
import re
from decimal import Decimal
-from typing import Optional, Tuple, TypeVar
+from typing import Optional, Tuple
import math_utils
@@ -39,9 +41,9 @@ class Money(object):
a = round(a, 2)
s = f'{a:,.2f}'
if self.currency is not None:
- return '%s %s' % (s, self.currency)
+ return f'{s} {self.currency}'
else:
- return '$%s' % s
+ return f'${s}'
def __pos__(self):
return Money(amount=self.amount, currency=self.currency)
@@ -178,8 +180,8 @@ class Money(object):
def __ge__(self, other):
return self > other or self == other
- def __hash__(self):
- return self.__repr__
+ def __hash__(self) -> int:
+ return hash(self.__repr__)
AMOUNT_RE = re.compile(r"^([+|-]?)(\d+)(\.\d+)$")
CURRENCY_RE = re.compile(r"^[A-Z][A-Z][A-Z]$")
diff --git a/type/people.py b/type/people.py
index 1230db2..3a6f743 100644
--- a/type/people.py
+++ b/type/people.py
@@ -1,9 +1,13 @@
#!/usr/bin/env python3
+"""An enum to represent people."""
+
import enum
-class Person(enum.Enum):
+class Person(enum.IntEnum):
+ """An enum to represent people."""
+
UNKNOWN = 0
SCOTT = 1
LYNN = 2
diff --git a/type/rate.py b/type/rate.py
index 64a4726..c365848 100644
--- a/type/rate.py
+++ b/type/rate.py
@@ -1,9 +1,13 @@
#!/usr/bin/env python3
+"""A class to represent a rate of change."""
+
from typing import Optional
class Rate(object):
+ """A class to represent a rate of change."""
+
def __init__(
self,
multiplier: Optional[float] = None,
@@ -28,9 +32,7 @@ class Rate(object):
self.multiplier = 1.0 + percent_change / 100
count += 1
if count != 1:
- raise Exception(
- 'Exactly one of percentage, percent_change or multiplier is required.'
- )
+ raise Exception('Exactly one of percentage, percent_change or multiplier is required.')
def apply_to(self, other):
return self.__mul__(other)