diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 9b037d4..5d2db44 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -19,47 +19,18 @@ from . import test, remote_hardware from . import portnums_pb2, channel_pb2, mesh_pb2, radioconfig_pb2 from . import tunnel from .util import support_info, our_exit +from .globals import Globals """We only import the tunnel code if we are on a platform that can run it""" have_tunnel = platform.system() == 'Linux' channelIndex = 0 -class Settings: - """Settings class is a Singleton.""" - __instance = None - @staticmethod - def getInstance(): - """Get an instance of the Settings class.""" - if Settings.__instance is None: - Settings() - return Settings.__instance - def __init__(self): - """Constructor for the Settings CLass""" - if Settings.__instance is not None: - raise Exception("This class is a singleton") - else: - Settings.__instance = self - self.args = None - self.parser = None - def set_args(self, args): - """Set the args""" - self.args = args - def set_parser(self, parser): - """Set the parser""" - self.parser = parser - def get_args(self): - """Get args""" - return self.args - def get_parser(self): - """Get parser""" - return self.parser - def onReceive(packet, interface): """Callback invoked when a packet arrives""" - settings = Settings.getInstance() - args = settings.get_args() + our_globals = Globals.getInstance() + args = our_globals.get_args() try: d = packet.get('decoded') @@ -223,8 +194,8 @@ def onConnected(interface): """Callback invoked when we connect to a radio""" closeNow = False # Should we drop the connection after we finish? try: - settings = Settings.getInstance() - args = settings.get_args() + our_globals = Globals.getInstance() + args = our_globals.get_args() print("Connected to radio") @@ -591,9 +562,9 @@ def subscribe(): def common(): """Shared code for all of our command line wrappers""" - settings = Settings.getInstance() - args = settings.get_args() - parser = settings.get_parser() + our_globals = Globals.getInstance() + args = our_globals.get_args() + parser = our_globals.get_parser() logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO) if len(sys.argv) == 1: @@ -670,9 +641,9 @@ def common(): def initParser(): """ Initialize the command line argument parsing.""" - settings = Settings.getInstance() - parser = settings.get_parser() - args = settings.get_args() + our_globals = Globals.getInstance() + parser = our_globals.get_parser() + args = our_globals.get_args() parser.add_argument( "--configure", @@ -837,28 +808,28 @@ def initParser(): "--support", action='store_true', help="Show support info (useful when troubleshooting an issue)") args = parser.parse_args() - settings.set_args(args) - settings.set_parser(parser) + our_globals.set_args(args) + our_globals.set_parser(parser) def main(): """Perform command line meshtastic operations""" - settings = Settings.getInstance() + our_globals = Globals.getInstance() parser = argparse.ArgumentParser() - settings.set_parser(parser) + our_globals.set_parser(parser) initParser() common() def tunnelMain(): """Run a meshtastic IP tunnel""" - settings = Settings.getInstance() + our_globals = Globals.getInstance() parser = argparse.ArgumentParser() - settings.set_parser(parser) + our_globals.set_parser(parser) initParser() - args = settings.get_args() + args = our_globals.get_args() args.tunnel = True - settings.set_args(args) + our_globals.set_args(args) common() diff --git a/meshtastic/globals.py b/meshtastic/globals.py new file mode 100644 index 0000000..c255e81 --- /dev/null +++ b/meshtastic/globals.py @@ -0,0 +1,44 @@ +"""Globals singleton class. + + Instead of using a global, stuff your variables in this "trash can". + This is not much better than using python's globals, but it allows + us to better test meshtastic. Plus, there are some weird python + global issues/gotcha that we can hopefully avoid by using this + class in stead. +""" + +class Globals: + """Globals class is a Singleton.""" + __instance = None + + @staticmethod + def getInstance(): + """Get an instance of the Globals class.""" + if Globals.__instance is None: + Globals() + return Globals.__instance + + def __init__(self): + """Constructor for the Globals CLass""" + if Globals.__instance is not None: + raise Exception("This class is a singleton") + else: + Globals.__instance = self + self.args = None + self.parser = None + + def set_args(self, args): + """Set the args""" + self.args = args + + def set_parser(self, parser): + """Set the parser""" + self.parser = parser + + def get_args(self): + """Get args""" + return self.args + + def get_parser(self): + """Get parser""" + return self.parser diff --git a/meshtastic/test/test_globals.py b/meshtastic/test/test_globals.py new file mode 100644 index 0000000..aba911c --- /dev/null +++ b/meshtastic/test/test_globals.py @@ -0,0 +1,25 @@ +"""Meshtastic unit tests for globals.py +""" + +import pytest + +from ..globals import Globals + + +@pytest.mark.unit +def test_globals_get_instaance(): + """Test that we can instantiate a Globals instance""" + ourglobals = Globals() + ourglobals2 = Globals.getInstance() + assert ourglobals == ourglobals2 + + +@pytest.mark.unit +def test_globals_there_can_be_only_one(): + """Test that we can cannot create two Globals instances""" + # ensure we have at least one instance created + Globals.getInstance() + with pytest.raises(Exception) as pytest_wrapped_e: + # try to create another instance + Globals() + assert pytest_wrapped_e.type == Exception diff --git a/meshtastic/test/test_main.py b/meshtastic/test/test_main.py index 186e8de..bc9a3a5 100644 --- a/meshtastic/test/test_main.py +++ b/meshtastic/test/test_main.py @@ -6,30 +6,18 @@ import re import pytest -from meshtastic.__main__ import initParser, Settings +from meshtastic.__main__ import initParser, Globals -"""The command line arguments""" -#args = None - -"""The parser for arguments""" -#parser = None - -#@pytest.fixture -#def patched_env(monkeypatch): -# monkeypatch.args = None -# #monkeypatch.sys.argv = [''] -# monkeypatch.parser = None - @pytest.mark.unit def test_main_no_args(capsys): """Test no arguments""" sys.argv = [''] args = sys.argv - settings = Settings.getInstance() + our_globals = Globals.getInstance() parser = argparse.ArgumentParser() - settings.set_parser(parser) - settings.set_args(args) + our_globals.set_parser(parser) + our_globals.set_args(args) initParser() out, err = capsys.readouterr() assert out == '' @@ -43,9 +31,9 @@ def test_main_version(capsys): args = sys.argv parser = None parser = argparse.ArgumentParser() - settings = Settings.getInstance() - settings.set_parser(parser) - settings.set_args(args) + our_globals = Globals.getInstance() + our_globals.set_parser(parser) + our_globals.set_args(args) with pytest.raises(SystemExit) as pytest_wrapped_e: initParser() assert pytest_wrapped_e.type == SystemExit