def main() -> None: # ------------------------------------------------------------------------- # Arguments # ------------------------------------------------------------------------- parser = argparse.ArgumentParser( description="test_mimic_balance -- to test Starfeeder", formatter_class=argparse.ArgumentDefaultsHelpFormatter # formatter_class=lambda prog: argparse.ArgumentDefaultsHelpFormatter( # prog, max_help_position=30, width=120) # http://stackoverflow.com/questions/5462873/control-formatting-of-the-argparse-help-argument-list # noqa ) parser.add_argument('--verbose', '-v', action='store_true', help="Be verbose") add_serial_port_args(parser) args = parser.parse_args() # ------------------------------------------------------------------------- # Logging # ------------------------------------------------------------------------- loglevel = logging.DEBUG if args.verbose else logging.INFO logging.basicConfig(format=LOG_FORMAT, datefmt=LOG_DATEFMT, level=loglevel) rootlogger = logging.getLogger() rootlogger.setLevel(loglevel) configure_logger_for_colour(rootlogger) # configure root logger # ------------------------------------------------------------------------- # Go # ------------------------------------------------------------------------- log.info("test_mimic_balance") log.info("args: {}".format(args)) mimic = BalanceMimic(args) mimic.run()
def main() -> None: # ------------------------------------------------------------------------- # Arguments # ------------------------------------------------------------------------- parser = argparse.ArgumentParser( description="test_mimic_rfid_reader -- to test Starfeeder", formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('--verbose', '-v', action='store_true', help="Be verbose") parser.add_argument( '--mean_time_between_rfids_s', type=float, default=1.0, help="Mean time between RFID generation (s) when reading") add_serial_port_args(parser) args = parser.parse_args() # ------------------------------------------------------------------------- # Logging # ------------------------------------------------------------------------- loglevel = logging.DEBUG if args.verbose else logging.INFO logging.basicConfig(format=LOG_FORMAT, datefmt=LOG_DATEFMT, level=loglevel) rootlogger = logging.getLogger() rootlogger.setLevel(loglevel) configure_logger_for_colour(rootlogger) # configure root logger # ------------------------------------------------------------------------- # Go # ------------------------------------------------------------------------- log.info("test_mimic_rfid_reader") log.info("args: {}".format(args)) mimic = RfidMimic(args) mimic.run()
def main() -> None: logging.basicConfig() logging.getLogger("whisker").setLevel(logging.DEBUG) configure_logger_for_colour(logging.getLogger()) # configure root logger # print_report_on_all_logs() parser = argparse.ArgumentParser("Test Whisker raw socket client") parser.add_argument('--server', default='localhost', help="Server (default: localhost)") parser.add_argument('--port', default=DEFAULT_PORT, type=int, help="Port (default: {})".format(DEFAULT_PORT)) parser.add_argument( '--display_num', default=DEFAULT_DISPLAY_NUM, type=int, help="Display number to use (default: {})".format(DEFAULT_DISPLAY_NUM)) parser.add_argument( '--audio_num', default=DEFAULT_AUDIO_NUM, type=int, help="Audio device number to use (default: {})".format( DEFAULT_AUDIO_NUM)) parser.add_argument( '--input', default=DEFAULT_INPUT_LINE, type=int, help="Input line number to use (default: {})".format( DEFAULT_INPUT_LINE)) parser.add_argument( '--output', default=DEFAULT_OUTPUT_LINE, type=int, help="Output line number to use (default: {})".format( DEFAULT_OUTPUT_LINE)) parser.add_argument( '--media_dir', default=DEFAULT_MEDIA_DIR, type=str, help="Media directory to use (default: {})".format( DEFAULT_MEDIA_DIR)) parser.add_argument( '--bitmap', default=DEFAULT_BITMAP, type=str, help="Bitmap to use (default: {})".format(DEFAULT_BITMAP)) parser.add_argument( '--video', default=DEFAULT_VIDEO, type=str, help="Video to use (default: {})".format(DEFAULT_VIDEO)) parser.add_argument( '--wav', default=DEFAULT_WAV, type=str, help="WAV file to use (default: {})".format(DEFAULT_WAV)) args = parser.parse_args() print("Module run explicitly. Running a Whisker test.") w = MyWhiskerTask( display_num=args.display_num, audio_num=args.audio_num, input_line=args.input, output_line=args.output, media_dir=args.media_dir, bitmap=args.bitmap, video=args.video, wav=args.wav, ) w.connect(args.server, args.port) reactor.run()
def main() -> None: logging.basicConfig() logging.getLogger("whisker").setLevel(logging.DEBUG) configure_logger_for_colour(logging.getLogger()) # configure root logger parser = argparse.ArgumentParser("Test Whisker raw socket client") parser.add_argument('--server', default='localhost', help="Server (default: localhost)") parser.add_argument('--port', default=DEFAULT_PORT, type=int, help="Port (default: {})".format(DEFAULT_PORT)) args = parser.parse_args() test_whisker(server=args.server, port=args.port)
def main() -> None: logging.basicConfig() logging.getLogger("whisker").setLevel(logging.DEBUG) configure_logger_for_colour(logging.getLogger()) # configure root logger parser = argparse.ArgumentParser("Test Whisker raw socket client") parser.add_argument('--server', default='localhost', help="Server (default: localhost)") parser.add_argument('--port', default=DEFAULT_PORT, type=int, help="Port (default: {})".format(DEFAULT_PORT)) args = parser.parse_args() test_whisker(server=args.server, port=args.port)
def main() -> None: logging.basicConfig() logging.getLogger("whisker").setLevel(logging.DEBUG) configure_logger_for_colour(logging.getLogger()) # configure root logger # print_report_on_all_logs() parser = argparse.ArgumentParser("Test Whisker raw socket client") parser.add_argument('--server', default='localhost', help="Server (default: localhost)") parser.add_argument('--port', default=DEFAULT_PORT, type=int, help="Port (default: {})".format(DEFAULT_PORT)) parser.add_argument( '--display_num', default=DEFAULT_DISPLAY_NUM, type=int, help="Display number to use (default: {})".format(DEFAULT_DISPLAY_NUM)) parser.add_argument('--audio_num', default=DEFAULT_AUDIO_NUM, type=int, help="Audio device number to use (default: {})".format( DEFAULT_AUDIO_NUM)) parser.add_argument('--input', default=DEFAULT_INPUT_LINE, type=int, help="Input line number to use (default: {})".format( DEFAULT_INPUT_LINE)) parser.add_argument('--output', default=DEFAULT_OUTPUT_LINE, type=int, help="Output line number to use (default: {})".format( DEFAULT_OUTPUT_LINE)) parser.add_argument( '--media_dir', default=DEFAULT_MEDIA_DIR, type=str, help="Media directory to use (default: {})".format(DEFAULT_MEDIA_DIR)) parser.add_argument( '--bitmap', default=DEFAULT_BITMAP, type=str, help="Bitmap to use (default: {})".format(DEFAULT_BITMAP)) parser.add_argument( '--video', default=DEFAULT_VIDEO, type=str, help="Video to use (default: {})".format(DEFAULT_VIDEO)) parser.add_argument( '--wav', default=DEFAULT_WAV, type=str, help="WAV file to use (default: {})".format(DEFAULT_WAV)) args = parser.parse_args() print("Module run explicitly. Running a Whisker test.") w = MyWhiskerTask( display_num=args.display_num, audio_num=args.audio_num, input_line=args.input, output_line=args.output, media_dir=args.media_dir, bitmap=args.bitmap, video=args.video, wav=args.wav, ) w.connect(args.server, args.port) reactor.run()
import logging from attrdict import AttrDict from datetime import datetime from twisted.internet import reactor from whisker.logging import configure_logger_for_colour from whisker.constants import DEFAULT_PORT from whisker.convenience import (load_config_or_die, connect_to_db_using_attrdict, insert_and_set_id, ask_user, save_data) from whisker.twistedclient import WhiskerTask log = logging.getLogger(__name__) configure_logger_for_colour(log) log.setLevel(logging.DEBUG) # debug-level logging for this file... logging.getLogger("whisker").setLevel(logging.DEBUG) # ... and for Whisker # ============================================================================= # Constants # ============================================================================= TASKNAME_SHORT = "countpings" # no spaces; we'll use it in a filename TASKNAME_LONG = "Ping Counting Task" # Our tables. They will be autocreated. (NOTE: do not store separate copies of # table objects, as they can get out of sync as new columns area created.) SESSION_TABLE = 'session' TRIAL_TABLE = 'trial'
# Imports, and configure logging # ============================================================================= import logging from attrdict import AttrDict from datetime import datetime from twisted.internet import reactor from whisker.logging import configure_logger_for_colour from whisker.constants import DEFAULT_PORT from whisker.convenience import (load_config_or_die, connect_to_db_using_attrdict, insert_and_set_id, ask_user, save_data) from whisker.twistedclient import WhiskerTask log = logging.getLogger(__name__) configure_logger_for_colour(log) log.setLevel(logging.DEBUG) # debug-level logging for this file... logging.getLogger("whisker").setLevel(logging.DEBUG) # ... and for Whisker # ============================================================================= # Constants # ============================================================================= TASKNAME_SHORT = "countpings" # no spaces; we'll use it in a filename TASKNAME_LONG = "Ping Counting Task" # Our tables. They will be autocreated. (NOTE: do not store separate copies of # table objects, as they can get out of sync as new columns area created.) SESSION_TABLE = 'session' TRIAL_TABLE = 'trial'
def main() -> int: # ------------------------------------------------------------------------- # Arguments # ------------------------------------------------------------------------- parser = argparse.ArgumentParser( description="Starfeeder v{}. Whisker bird monitor, reading from RFID " "tag readers and weighing balances.".format(VERSION)) # ... allow_abbrev=False requires Python 3.5 parser.add_argument("--logfile", default=None, help="Filename to append log to") parser.add_argument('--verbose', '-v', action='count', default=0, help="Be verbose (use twice for extra verbosity)") parser.add_argument('--guilog', action="store_true", help="Show Python log in a GUI window") parser.add_argument('--upgrade-database', action="store_true", help="Upgrade database (determined from SQLAlchemy" " URL, read from {} environment variable) to current" " version".format(DB_URL_ENV_VAR)) parser.add_argument('--gui', '-g', action="store_true", help="GUI mode only") parser.add_argument( "--dburl", default=None, help="Database URL (if not specified, task will look in {} " "environment variable).".format(DB_URL_ENV_VAR)) parser.add_argument('--dbecho', action="store_true", help="Echo SQL to log.") parser.add_argument('--debug-qt-signals', action="store_true", help="Debug QT signals.") # We could allow extra Qt arguments: # args, unparsed_args = parser.parse_known_args() # Or not: args = parser.parse_args() unparsed_args = [] qt_args = sys.argv[:1] + unparsed_args # ------------------------------------------------------------------------- # Modify settings if we're in a PyInstaller bundle # ------------------------------------------------------------------------- in_bundle = getattr(sys, 'frozen', False) if in_bundle: args.gui = True if not args.gui: args.guilog = False # ------------------------------------------------------------------------- # Create QApplication before we create any windows (or Qt will crash) # ------------------------------------------------------------------------- qt_app = QApplication(qt_args) # Attempt to fix rare bugs by constraining the Python garbage collector # to the GUI thread only # noinspection PyUnusedLocal my_garbage_collector = GarbageCollector(qt_app, interval_ms=100) # ... with interval of 10000, get # pymysql.err.OperationalError (1040, 'Too many connections') # ... 500 seems OK # ... not sure why there was a problem, though, as all sessions are created # using "with session_thread_scope", and when that finishes, it calls # session.close(), and that's meant to release all resources: # http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#closing # ... since I'm not sure, let's use 100 to be conservative # ------------------------------------------------------------------------- # Logging # ------------------------------------------------------------------------- loglevel = logging.DEBUG if args.verbose >= 1 else logging.INFO logging.basicConfig(format=LOG_FORMAT, datefmt=LOG_DATEFMT, level=loglevel) rootlogger = logging.getLogger() rootlogger.setLevel(loglevel) configure_logger_for_colour(rootlogger) # configure root logger logging.getLogger('whisker').setLevel( logging.DEBUG if args.verbose >= 2 else logging.INFO) if args.logfile: copy_root_log_to_file(args.logfile) if args.guilog: log_window = LogWindow(level=loglevel, window_title=WINDOW_TITLE + " Python log", logger=rootlogger) log_window.show() # If any exceptions happen up to this point, we're a bit stuffed. # But from now on, we can trap anything and see it in the GUI log, if # enabled, even if we have no console. # noinspection PyBroadException try: # --------------------------------------------------------------------- # Info # --------------------------------------------------------------------- log.info("Starfeeder v{}: RFID/balance controller for Whisker, " "by Rudolf Cardinal ([email protected])".format(VERSION)) log.debug("args: {}".format(args)) log.debug("qt_args: {}".format(qt_args)) log.debug("PyQt5 version: {}".format(PYQT_VERSION_STR)) log.debug("Qt version: {}".format(QT_VERSION_STR)) log.debug("Whisker client version: {}".format(whisker.version.VERSION)) if in_bundle: log.debug("Running inside a PyInstaller bundle") if args.gui: log.debug("Running in GUI-only mode") # if args.debug_qt_signals: # enable_signal_debugging_simply() # --------------------------------------------------------------------- # Database # --------------------------------------------------------------------- # Get URL, or complain if args.dburl: set_database_url(args.dburl) if args.dbecho: set_database_echo(args.dbecho) try: database_url = get_database_url() except ValueError: if args.gui: win = NoDatabaseSpecifiedWindow() if args.guilog: # noinspection PyUnboundLocalVariable win.exit_kill_log.connect(log_window.exit) return run_gui(qt_app, win) raise ValueError(DATABASE_ENV_VAR_NOT_SPECIFIED) engine = create_engine(database_url) log.debug("Using database URL: {}".format(engine)) # obscures password # Has the user requested a command-line database upgrade? if args.upgrade_database: sys.exit( upgrade_database(ALEMBIC_CONFIG_FILENAME, ALEMBIC_BASE_DIR)) # Is the database at the correct version? (current_revision, head_revision) = get_current_and_head_revision( database_url, ALEMBIC_CONFIG_FILENAME, ALEMBIC_BASE_DIR) if current_revision != head_revision: if args.gui: win = WrongDatabaseVersionWindow(current_revision, head_revision) if args.guilog: # noinspection PyUnboundLocalVariable win.exit_kill_log.connect(log_window.exit) return run_gui(qt_app, win) raise ValueError( WRONG_DATABASE_VERSION_STUB.format( head_revision=head_revision, current_revision=current_revision)) # --------------------------------------------------------------------- # Run app # --------------------------------------------------------------------- win = BaseWindow() if args.guilog: # noinspection PyUnboundLocalVariable win.exit_kill_log.connect(log_window.exit) return run_gui(qt_app, win) except: if args.guilog: log.critical(traceback.format_exc()) log_window.set_may_close(True) return qt_app.exec_() else: raise