Start using warnings from stdlib.
authorScott <[email protected]>
Tue, 11 Jan 2022 21:33:24 +0000 (13:33 -0800)
committerScott <[email protected]>
Tue, 11 Jan 2022 21:33:24 +0000 (13:33 -0800)
19 files changed:
argparse_utils.py
arper.py
base_presence.py
camera_utils.py
decorator_utils.py
executors.py
file_utils.py
google_assistant.py
lockfile.py
logging_utils.py
ml/model_trainer.py
ml/quick_label.py
persistent.py
remote_worker.py
smart_home/lights.py
smart_home/outlets.py
smart_home/registry.py
string_utils.py
unittest_utils.py

index e8c2f5699bea4bceb67d22127a923099d0d143e5..1c61b2460650c11872cbaaabf4e7f5a689be746c 100644 (file)
@@ -114,7 +114,7 @@ def valid_ip(ip: str) -> str:
     if s is not None:
         return s
     msg = f"{ip} is an invalid IP address"
-    logger.warning(msg)
+    logger.error(msg)
     raise argparse.ArgumentTypeError(msg)
 
 
@@ -140,7 +140,7 @@ def valid_mac(mac: str) -> str:
     if s is not None:
         return s
     msg = f"{mac} is an invalid MAC address"
-    logger.warning(msg)
+    logger.error(msg)
     raise argparse.ArgumentTypeError(msg)
 
 
@@ -166,7 +166,7 @@ def valid_percentage(num: str) -> float:
     if 0.0 <= n <= 100.0:
         return n
     msg = f"{num} is an invalid percentage; expected 0 <= n <= 100.0"
-    logger.warning(msg)
+    logger.error(msg)
     raise argparse.ArgumentTypeError(msg)
 
 
@@ -188,7 +188,7 @@ def valid_filename(filename: str) -> str:
     if os.path.exists(s):
         return s
     msg = f"{filename} was not found and is therefore invalid."
-    logger.warning(msg)
+    logger.error(msg)
     raise argparse.ArgumentTypeError(msg)
 
 
@@ -210,7 +210,7 @@ def valid_date(txt: str) -> datetime.date:
     if date is not None:
         return date
     msg = f'Cannot parse argument as a date: {txt}'
-    logger.warning(msg)
+    logger.error(msg)
     raise argparse.ArgumentTypeError(msg)
 
 
@@ -232,7 +232,7 @@ def valid_datetime(txt: str) -> datetime.datetime:
     if dt is not None:
         return dt
     msg = f'Cannot parse argument as datetime: {txt}'
-    logger.warning(msg)
+    logger.error(msg)
     raise argparse.ArgumentTypeError(msg)
 
 
index c187023c98798044ac27e2b888f70ded7275ac93..c0cc9f035af4367ce0c84a0e623a2ea6ae320699 100644 (file)
--- a/arper.py
+++ b/arper.py
@@ -6,6 +6,7 @@ import datetime
 import logging
 import os
 from typing import Any, Optional
+import warnings
 
 from overrides import overrides
 
@@ -126,9 +127,9 @@ class Arper(persistent.Persistent):
             if len(cached_state) > config.config['arper_min_entries_to_be_valid']:
                 return cls(cached_state)
             else:
-                logger.warning(
-                    f'{cache_file} sucks, only {len(cached_state)} entries.  Deleting it.'
-                )
+                msg = f'{cache_file} is invalid: only {len(cached_state)} entries.  Deleting it.'
+                warnings.warn(msg)
+                logger.warning(msg)
                 os.remove(cache_file)
         logger.debug('No usable saved state found')
         return None
index eff613b5edcfaea975ad5e7d37afe021fc14a03b..b38b436be2820a3fd36637569d76eaae86d2aee7 100755 (executable)
@@ -5,6 +5,7 @@ from collections import defaultdict
 import logging
 import re
 from typing import Dict, List, Set
+import warnings
 
 # Note: this module is fairly early loaded.  Be aware of dependencies.
 import argparse_utils
@@ -113,7 +114,9 @@ class PresenceDetection(object):
             self.parse_raw_macs_file(raw, Location.CABIN)
         except Exception as e:
             logger.exception(e)
-            logger.warning("Can't see the cabin right now; presence detection impared.")
+            msg = "Can't see the cabin right now; presence detection impared."
+            logger.warning(msg)
+            warnings.warn(msg)
             self.dark_locations.add(Location.CABIN)
 
     def update_from_cabin(self) -> None:
@@ -131,7 +134,9 @@ class PresenceDetection(object):
             self.parse_raw_macs_file(raw, Location.HOUSE)
         except Exception as e:
             logger.exception(e)
-            logger.warning("Can't see the house right now; presence detection impared.")
+            msg = "Can't see the house right now; presence detection impared."
+            logger.warning(msg)
+            warnings.warn(msg)
             self.dark_locations.add(Location.HOUSE)
 
     def read_persisted_macs_file(
@@ -193,9 +198,9 @@ class PresenceDetection(object):
     def where_is_person_now(self, name: Person) -> Location:
         self.maybe_update()
         if len(self.dark_locations) > 0:
-            logger.warning(
-                f"Can't see {self.dark_locations} right now; answer confidence impacted"
-            )
+            msg = f"Can't see {self.dark_locations} right now; answer confidence impacted"
+            logger.warning(msg)
+            warnings.warn(msg)
         logger.debug(f'Looking for {name}...')
 
         if name is Person.UNKNOWN:
index acf760d55ca8b61d69871260ac55e18844f46acb..e69eddb7b3cec5faf915dd6bc23243b261d26858 100644 (file)
@@ -6,6 +6,7 @@ import logging
 import platform
 import subprocess
 from typing import NamedTuple, Optional
+import warnings
 
 import cv2  # type: ignore
 import numpy as np
@@ -81,7 +82,9 @@ def fetch_camera_image_from_video_server(
                 return raw
     except Exception as e:
         logger.exception(e)
-    logger.warning(f"Got a bad image or HTTP error from {url}")
+    msg = f"Got a bad image or HTTP error from {url}; returning None."
+    logger.warning(msg)
+    warnings.warn(msg)
     return None
 
 
@@ -106,6 +109,7 @@ def fetch_camera_image_from_rtsp_stream(
 ) -> Optional[bytes]:
     """Fetch the raw webcam image straight from the webcam's RTSP stream."""
     hostname = blue_iris_camera_name_to_hostname(camera_name)
+    stream = f"rtsp://camera:IaLaIok@{hostname}:554/live"
     try:
         cmd = [
             "/usr/bin/timeout",
@@ -114,7 +118,7 @@ def fetch_camera_image_from_rtsp_stream(
             "/usr/local/bin/ffmpeg",
             "-y",
             "-i",
-            f"rtsp://camera:IaLaIok@{hostname}:554/live",
+            f"{stream}",
             "-f",
             "singlejpeg",
             "-vframes",
@@ -130,7 +134,9 @@ def fetch_camera_image_from_rtsp_stream(
             return out
     except Exception as e:
         logger.exception(e)
-    logger.warning("Failed to retrieve image from RTSP stream")
+    msg = "Failed to retrieve image via RTSP {stream}, returning None."
+    warnings.warn(msg)
+    logger.warning(msg)
     return None
 
 
@@ -157,9 +163,9 @@ def _fetch_camera_image(
             jpg=jpg,
             hsv=hsv,
         )
-    logger.warning(
-        "Failed to retieve image from both video server and direct RTSP stream"
-    )
+    msg = "Failed to retieve image from both video server and direct RTSP stream"
+    logger.warning(msg)
+    warnings.warn(msg)
     return RawJpgHsv(None, None, None)
 
 
index d5349cc31aed2e74352822c3175ace022ab20e74..07ad881f63a613de38d82d9a54babce92127b1b5 100644 (file)
@@ -479,7 +479,7 @@ def deprecated(func):
     def wrapper_deprecated(*args, **kwargs):
         msg = f"Call to deprecated function {func.__qualname__}"
         logger.warning(msg)
-        warnings.warn(msg, category=DeprecationWarning)
+        warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
         print(msg, file=sys.stderr)
         return func(*args, **kwargs)
     return wrapper_deprecated
@@ -507,8 +507,8 @@ def thunkify(func):
                 exc[0] = True
                 exc[1] = sys.exc_info()  # (type, value, traceback)
                 msg = f"Thunkify has thrown an exception (will be raised on thunk()):\n{traceback.format_exc()}"
-                print(msg)
                 logger.warning(msg)
+                warnings.warn(msg)
             finally:
                 wait_event.set()
 
index cdbb811a6acd2cb9af12fefe49c61b65adba5ad0..dabddf31b65e6687087820f7f2115a1197e93281 100644 (file)
@@ -15,6 +15,7 @@ import subprocess
 import threading
 import time
 from typing import Any, Callable, Dict, List, Optional, Set
+import warnings
 
 import cloudpickle  # type: ignore
 from overrides import overrides
@@ -490,7 +491,9 @@ class WeightedRandomRemoteWorkerSelectionPolicy(RemoteWorkerSelectionPolicy):
                     worker.count -= 1
                     logger.debug(f'Selected worker {worker}')
                     return worker
-        logger.warning("Couldn't find a worker; go fish.")
+        msg = 'Unexpectedly could not find a worker, retrying...'
+        logger.warning(msg)
+        warnings.warn(msg)
         return None
 
 
@@ -525,7 +528,9 @@ class RoundRobinRemoteWorkerSelectionPolicy(RemoteWorkerSelectionPolicy):
             if x >= len(self.workers):
                 x = 0
             if x == self.index:
-                logger.warning("Couldn't find a worker; go fish.")
+                msg = 'Unexpectedly could not find a worker, retrying...'
+                logger.warning(msg)
+                warnings.warn(msg)
                 return None
 
 
@@ -768,11 +773,11 @@ class RemoteExecutor(BaseExecutor):
                     # There's a race condition where someone else
                     # already finished the work and removed the source
                     # code file before we could copy it.  No biggie.
-                    logger.warning(
-                        f'{bundle}: Failed to send instructions to the worker machine... ' +
+                    msg = f'{bundle}: Failed to send instructions to the worker machine... ' +
                         'We\'re a backup and this may be caused by the original (or some ' +
                         'other backup) already finishing this work.  Ignoring this.'
-                    )
+                    logger.warning(msg)
+                    warnings.warn(msg)
                     return None
 
         # Kick off the work.  Note that if this fails we let
@@ -844,9 +849,9 @@ class RemoteExecutor(BaseExecutor):
             logger.exception(e)
             logger.error(f'{bundle}: Something unexpected just happened...')
             if p is not None:
-                logger.warning(
-                    f"{bundle}: Failed to wrap up \"done\" bundle, re-waiting on active ssh."
-                )
+                msg = f"{bundle}: Failed to wrap up \"done\" bundle, re-waiting on active ssh."
+                logger.warning(msg)
+                warnings.warn(msg)
                 return self.wait_for_process(p, bundle, depth + 1)
             else:
                 self.status.record_release_worker(
@@ -1059,9 +1064,9 @@ class RemoteExecutor(BaseExecutor):
                 logger.error(f'{bundle}: At least it\'s only a backup; better luck with the others.')
             return None
         else:
-            logger.warning(
-                f'>>> Emergency rescheduling {bundle} because of unexected errors (wtf?!) <<<'
-            )
+            msg = f'>>> Emergency rescheduling {bundle} because of unexected errors (wtf?!) <<<'
+            logger.warning(msg)
+            warnings.warn(msg)
             return self.launch(bundle, avoid_last_machine)
 
     @overrides
index 67e6f561f394e1a99c4ace7bb2f6ddbe733ea011..176b0dab055f1447ad8ac5a0d67ce073be7deb7c 100644 (file)
@@ -20,6 +20,7 @@ logger = logging.getLogger(__name__)
 
 
 # os.remove(file) you fuckwit.
+# os.path.basename too.
 
 
 def create_path_if_not_exist(path, on_error=None):
index 572b4ccdf25644992f77f66eae800ea9e306ce50..041648ca4f15e9db4ce1b1df2862d948ec450325 100644 (file)
@@ -3,6 +3,7 @@
 import logging
 from typing import NamedTuple
 import sys
+import warnings
 
 import requests
 import speech_recognition as sr  # type: ignore
@@ -93,7 +94,9 @@ def ask_google(cmd: str, *, recognize_speech=True) -> GoogleResponse:
                     logger.debug(f"Transcription: '{audio_transcription}'")
                 except sr.UnknownValueError as e:
                     logger.exception(e)
-                    logger.warning('Unable to parse Google assistant\'s response.')
+                    msg = 'Unable to parse Google assistant\'s response.'
+                    logger.warning(msg)
+                    warnings.warn(msg)
                     audio_transcription = None
         return GoogleResponse(
             success=success,
index d275f407ff237c38ceaec83c94a1abf92174b04a..7f10cc1f5894155c65ca352183afc0ea6d81fa37 100644 (file)
@@ -8,6 +8,7 @@ import os
 import signal
 import sys
 from typing import Optional
+import warnings
 
 import config
 import datetime_utils
@@ -87,7 +88,9 @@ class LockFile(object):
             return True
         except OSError:
             pass
-        logger.warning(f'Could not acquire {self.lockfile}.')
+        msg = f'Could not acquire {self.lockfile}.'
+        logger.warning(msg)
+        warnings.warn(msg)
         return False
 
     def acquire_with_retries(
@@ -124,6 +127,7 @@ class LockFile(object):
             return self
         msg = f"Couldn't acquire {self.lockfile}; giving up."
         logger.warning(msg)
+        warnings.warn(msg)
         raise LockFileException(msg)
 
     def __exit__(self, type, value, traceback):
@@ -132,7 +136,9 @@ class LockFile(object):
             duration = ts - self.locktime
             if duration >= config.config['lockfile_held_duration_warning_threshold_sec']:
                 str_duration = datetime_utils.describe_duration_briefly(duration)
-                logger.warning(f'Held {self.lockfile} for {str_duration}')
+                msg = f'Held {self.lockfile} for {str_duration}'
+                logger.warning(msg)
+                warnings.warn(msg, stacklevel=2)
         self.release()
 
     def __del__(self):
@@ -170,16 +176,18 @@ class LockFile(object):
                     try:
                         os.kill(contents.pid, 0)
                     except OSError:
-                        logger.warning(f'Lockfile {self.lockfile}\'s pid ({contents.pid}) is stale; ' +
-                                       'force acquiring')
+                        msg = f'Lockfile {self.lockfile}\'s pid ({contents.pid}) is stale; force acquiring'
+                        logger.warning(msg)
+                        warnings.warn(msg)
                         self.release()
 
                     # Has the lock expiration expired?
                     if contents.expiration_timestamp is not None:
                         now = datetime.datetime.now().timestamp()
                         if now > contents.expiration_datetime:
-                            logger.warning(f'Lockfile {self.lockfile} expiration time has passed; ' +
-                                           'force acquiring')
+                            msg = f'Lockfile {self.lockfile} expiration time has passed; force acquiring'
+                            logger.warning(msg)
+                            warnings.warn(msg)
                             self.release()
         except Exception:
             pass
index de69046c30a82914b04e288982fcf93455fcb965..20a57f7c953ff9474f58a7057d5c20ef757aae2e 100644 (file)
@@ -13,6 +13,7 @@ import os
 import random
 import sys
 from typing import Callable, Iterable, Mapping, Optional
+import warnings
 
 from overrides import overrides
 import pytz
@@ -523,9 +524,9 @@ def initialize_logging(logger=None) -> logging.Logger:
         f'Initialized global logging; default logging level is {level_name}.'
     )
     if config.config['logging_clear_preexisting_handlers'] and preexisting_handlers_count > 0:
-        logger.warning(
-            'Logging cleared {preexisting_handlers_count} global handlers (--logging_clear_preexisting_handlers)'
-        )
+        msg = 'Logging cleared {preexisting_handlers_count} global handlers (--logging_clear_preexisting_handlers)'
+        logger.warning(msg)
+        warnings.warn(msg)
     logger.debug(f'Logging format specification is "{fmt}"')
     if config.config['logging_debug_threads']:
         logger.debug('...Logging format spec captures tid/pid (--logging_debug_threads)')
index acd721868a2a9e04de0da364b8d37dcc268b4fee..79ce7062b5b4a05616cddcf7b3d35d59cfbef007 100644 (file)
@@ -12,6 +12,7 @@ import random
 import sys
 from types import SimpleNamespace
 from typing import Any, List, NamedTuple, Optional, Set, Tuple
+import warnings
 
 import numpy as np
 from sklearn.model_selection import train_test_split  # type:ignore
@@ -247,13 +248,13 @@ class TrainingBlueprint(ABC):
 
                 if self.spec.delete_bad_inputs:
                     msg = f"WARNING: {filename}: missing features or label; expected {self.spec.feature_count} but saw {len(x)}.  DELETING."
-                    print(msg, file=sys.stderr)
                     logger.warning(msg)
+                    warnings.warn(msg)
                     os.remove(filename)
                 else:
                     msg = f"WARNING: {filename}: missing features or label; expected {self.spec.feature_count} but saw {len(x)}.  Skipping."
-                    print(msg, file=sys.stderr)
                     logger.warning(msg)
+                    warnings.warn(msg)
         return (X, y)
 
     def make_progress_graph(self) -> None:
index 1ed42966db65da792a81a802b8b5a606b55e4dcc..120ff5fe92e644d22385741d2044d8c14d006dea 100644 (file)
@@ -4,6 +4,7 @@ import glob
 import logging
 import os
 from typing import Callable, List, NamedTuple, Optional, Set
+import warnings
 
 import argparse_utils
 import config
@@ -90,9 +91,9 @@ def label(in_spec: InputSpec) -> None:
             continue
         features = in_spec.image_file_to_features_file(image)
         if features is None or not os.path.exists(features):
-            logger.warning(
-                f'File {image} yielded file {features} which does not exist, SKIPPING.'
-            )
+            msg = f'File {image} yielded file {features} which does not exist, SKIPPING.'
+            logger.warning(msg)
+            warnings.warn(msg)
             continue
 
         # Render features and image.
index f6ca0a0faa4bde09299db88d100fd1e9b8640f0a..2751572553ac7c20c7663974c13e17b13f0ab037 100644 (file)
@@ -7,6 +7,7 @@ import enum
 import functools
 import logging
 from typing import Any
+import warnings
 
 import file_utils
 
@@ -143,7 +144,9 @@ class persistent_autoloaded_singleton(object):
             logger.debug(f'Attempting to load {cls.__name__} from persisted state.')
             self.instance = cls.load()
             if not self.instance:
-                logger.warning('Loading from cache failed.')
+                msg = 'Loading from cache failed.'
+                logger.warning(msg)
+                warnings.warn(msg)
                 logger.debug(f'Attempting to instantiate {cls.__name__} directly.')
                 self.instance = cls(*args, **kwargs)
             else:
index 0086c40b0379ce680383c3b4e723bdc92b3bec0a..42aeb854ce633b47e1f1be85b40bce8bf8d436f6 100755 (executable)
@@ -51,9 +51,6 @@ cfg.add_argument(
 
 @background_thread
 def watch_for_cancel(terminate_event: threading.Event) -> None:
-    if platform.node() == 'VIDEO-COMPUTER':
-        logger.warning('Background thread not allowed on retarded computers, sorry.')
-        return
     logger.debug('Starting up background thread...')
     p = psutil.Process(os.getpid())
     while True:
index e23569a69f60d35056faa1a795be536a3d103933..44b3634cd5fb9f5c84620762701f120db8bd3977 100644 (file)
@@ -11,6 +11,7 @@ import re
 import subprocess
 import sys
 from typing import Any, Dict, List, Optional, Tuple
+import warnings
 
 from overrides import overrides
 import tinytuya as tt
@@ -46,14 +47,18 @@ def tplink_light_command(command: str) -> bool:
     result = os.system(command)
     signal = result & 0xFF
     if signal != 0:
-        logger.warning(f'{command} died with signal {signal}')
-        logging_utils.hlog("%s died with signal %d" % (command, signal))
+        msg = f'{command} died with signal {signal}'
+        logger.warning(msg)
+        warnings.warn(msg)
+        logging_utils.hlog(msg)
         return False
     else:
         exit_value = result >> 8
         if exit_value != 0:
-            logger.warning(f'{command} failed, exited {exit_value}')
-            logging_utils.hlog("%s failed, exit %d" % (command, exit_value))
+            msg = f'{command} failed, exited {exit_value}'
+            logger.warning(msg)
+            warnings.warn(msg)
+            logging_utils.hlog(msg)
             return False
     logger.debug(f'{command} succeeded.')
     return True
index 8fd09487a48b5c49478bb5d84b91d481dc36adfc..6cc8d57ec065beabc5652c1015fa75df3307cd97 100644 (file)
@@ -13,6 +13,7 @@ import re
 import subprocess
 import sys
 from typing import Any, Dict, List, Optional
+import warnings
 
 from meross_iot.http_api import MerossHttpClient
 from meross_iot.manager import MerossManager
@@ -48,14 +49,18 @@ def tplink_outlet_command(command: str) -> bool:
     result = os.system(command)
     signal = result & 0xFF
     if signal != 0:
-        logger.warning(f'{command} died with signal {signal}')
-        logging_utils.hlog("%s died with signal %d" % (command, signal))
+        msg = f'{command} died with signal {signal}'
+        logger.warning(msg)
+        warnings.warn(msg)
+        logging_utils.hlog(msg)
         return False
     else:
         exit_value = result >> 8
         if exit_value != 0:
-            logger.warning(f'{command} failed, exited {exit_value}')
-            logging_utils.hlog("%s failed, exit %d" % (command, exit_value))
+            msg = f'{command} failed, exited {exit_value}'
+            logger.warning(msg)
+            warnings.warn(msg)
+            logging_utils.hlog(msg)
             return False
     logger.debug(f'{command} succeeded.')
     return True
index 23584e119173e00f8d86dd38858126a990222f39..20fb3f43807bf0dbbd45fa7f5c36ed8f4d1bc917 100644 (file)
@@ -3,6 +3,7 @@
 import logging
 import re
 from typing import List, Optional, Set
+import warnings
 
 import argparse_utils
 import config
@@ -63,7 +64,9 @@ class SmartHomeRegistry(object):
             try:
                 (mac, name, keywords) = line.split(",")
             except ValueError:
-                logger.warning(f'SH-CONFIG> {line} is malformed?!')
+                msg = f'SH-CONFIG> {line} is malformed?!'
+                logger.warning(msg)
+                warnings.warn(msg)
                 continue
             mac = mac.strip()
             name = name.strip()
@@ -183,11 +186,11 @@ class SmartHomeRegistry(object):
                     logger.debug('    ...an unknown device (should this be here?)')
                     return device.Device(name, mac, kws)
             except Exception as e:
-                logger.warning(
-                    f'Got exception {e} while trying to communicate with device {name}/{mac}.'
-                )
+                logger.exception(e)
                 return device.Device(name, mac, kws)
-        logger.warning(f'{mac} is not a known smart home device, returning None')
+        msg = f'{mac} is not a known smart home device, returning None'
+        logger.warning(msg)
+        warnings.warn(msg)
         return None
 
     def query(self, query: str) -> List[device.Device]:
index 45607f3448d85f1d61a9e614502cf6c87bfd6fdc..b93dc93aaa78e9b1b901499169c3b902f3445a59 100644 (file)
@@ -14,6 +14,7 @@ import string
 from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple
 import unicodedata
 from uuid import uuid4
+import warnings
 
 import list_utils
 
@@ -1097,7 +1098,9 @@ def to_date(in_str: str) -> Optional[datetime.date]:
         d.parse(in_str)
         return d.get_date()
     except dp.ParseException:
-        logger.warning(f'Unable to parse date {in_str}.')
+        msg = f'Unable to parse date {in_str}.'
+        logger.warning(msg)
+        warnings.warn(msg)
     return None
 
 
@@ -1111,7 +1114,9 @@ def valid_date(in_str: str) -> bool:
         _ = d.parse(in_str)
         return True
     except dp.ParseException:
-        logger.warning(f'Unable to parse date {in_str}.')
+        msg = f'Unable to parse date {in_str}.'
+        logger.warning(msg)
+        warnings.warn(msg)
     return False
 
 
@@ -1126,7 +1131,9 @@ def to_datetime(in_str: str) -> Optional[datetime.datetime]:
         if type(dt) == datetime.datetime:
             return dt
     except ValueError:
-        logger.warning(f'Unable to parse datetime {in_str}.')
+        msg = f'Unable to parse datetime {in_str}.'
+        logger.warning(msg)
+        warnings.warn(msg)
     return None
 
 
@@ -1137,7 +1144,9 @@ def valid_datetime(in_str: str) -> bool:
     _ = to_datetime(in_str)
     if _ is not None:
         return True
-    logger.warning(f'Unable to parse datetime {in_str}.')
+    msg = f'Unable to parse datetime {in_str}.'
+    logger.warning(msg)
+    warnings.warn(msg)
     return False
 
 
@@ -1466,8 +1475,9 @@ def chunk(txt: str, chunk_size):
 
     """
     if len(txt) % chunk_size != 0:
-        logger.warning(
-            f'String to chunk\'s length ({len(txt)} is not an even multiple of chunk_size ({chunk_size})')
+        msg = f'String to chunk\'s length ({len(txt)} is not an even multiple of chunk_size ({chunk_size})'
+        logger.warning(msg)
+        warnings.warn(msg)
     for x in range(0, len(txt), chunk_size):
         yield txt[x:x+chunk_size]
 
index bb1a9b432f49d7886b99f39418339e9f62e0cee1..270e20d1e268112f543ac70d4e096745b1861d1c 100644 (file)
@@ -18,6 +18,7 @@ import time
 import tempfile
 from typing import Callable
 import unittest
+import warnings
 
 import bootstrap
 import config
@@ -78,7 +79,9 @@ def check_method_for_perf_regressions(func: Callable) -> Callable:
             perfdb = load_known_test_performance_characteristics()
         except Exception as e:
             logger.exception(e)
-            logger.warning(f'Unable to load perfdb from {_db}')
+            msg = f'Unable to load perfdb from {_db}'
+            logger.warning(msg)
+            warnings.warn(msg)
             perfdb = {}
 
         # This is a unique identifier for a test: filepath!function