aprsd 4.1.0__py3-none-any.whl → 4.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
aprsd/cli_helper.py CHANGED
@@ -13,35 +13,35 @@ from aprsd.utils import trace
13
13
 
14
14
  CONF = cfg.CONF
15
15
  home = str(Path.home())
16
- DEFAULT_CONFIG_DIR = f"{home}/.config/aprsd/"
17
- DEFAULT_SAVE_FILE = f"{home}/.config/aprsd/aprsd.p"
18
- DEFAULT_CONFIG_FILE = f"{home}/.config/aprsd/aprsd.conf"
16
+ DEFAULT_CONFIG_DIR = f'{home}/.config/aprsd/'
17
+ DEFAULT_SAVE_FILE = f'{home}/.config/aprsd/aprsd.p'
18
+ DEFAULT_CONFIG_FILE = f'{home}/.config/aprsd/aprsd.conf'
19
19
 
20
20
 
21
- F = t.TypeVar("F", bound=t.Callable[..., t.Any])
21
+ F = t.TypeVar('F', bound=t.Callable[..., t.Any])
22
22
 
23
23
  common_options = [
24
24
  click.option(
25
- "--loglevel",
26
- default="INFO",
25
+ '--loglevel',
26
+ default='INFO',
27
27
  show_default=True,
28
28
  type=click.Choice(
29
- ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"],
29
+ ['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
30
30
  case_sensitive=False,
31
31
  ),
32
32
  show_choices=True,
33
- help="The log level to use for aprsd.log",
33
+ help='The log level to use for aprsd.log',
34
34
  ),
35
35
  click.option(
36
- "-c",
37
- "--config",
38
- "config_file",
36
+ '-c',
37
+ '--config',
38
+ 'config_file',
39
39
  show_default=True,
40
40
  default=DEFAULT_CONFIG_FILE,
41
- help="The aprsd config file to use for options.",
41
+ help='The aprsd config file to use for options.',
42
42
  ),
43
43
  click.option(
44
- "--quiet",
44
+ '--quiet',
45
45
  is_flag=True,
46
46
  default=False,
47
47
  help="Don't log to stdout",
@@ -59,7 +59,7 @@ class AliasedGroup(click.Group):
59
59
  """
60
60
 
61
61
  def decorator(f):
62
- aliases = kwargs.pop("aliases", [])
62
+ aliases = kwargs.pop('aliases', [])
63
63
  cmd = click.decorators.command(*args, **kwargs)(f)
64
64
  self.add_command(cmd)
65
65
  for alias in aliases:
@@ -77,7 +77,7 @@ class AliasedGroup(click.Group):
77
77
  """
78
78
 
79
79
  def decorator(f):
80
- aliases = kwargs.pop("aliases", [])
80
+ aliases = kwargs.pop('aliases', [])
81
81
  cmd = click.decorators.group(*args, **kwargs)(f)
82
82
  self.add_command(cmd)
83
83
  for alias in aliases:
@@ -101,36 +101,37 @@ def process_standard_options(f: F) -> F:
101
101
  ctx = args[0]
102
102
  ctx.ensure_object(dict)
103
103
  config_file_found = True
104
- if kwargs["config_file"]:
105
- default_config_files = [kwargs["config_file"]]
104
+ if kwargs['config_file']:
105
+ default_config_files = [kwargs['config_file']]
106
106
  else:
107
107
  default_config_files = None
108
+
108
109
  try:
109
110
  CONF(
110
111
  [],
111
- project="aprsd",
112
+ project='aprsd',
112
113
  version=aprsd.__version__,
113
114
  default_config_files=default_config_files,
114
115
  )
115
116
  except cfg.ConfigFilesNotFoundError:
116
117
  config_file_found = False
117
- ctx.obj["loglevel"] = kwargs["loglevel"]
118
+ ctx.obj['loglevel'] = kwargs['loglevel']
118
119
  # ctx.obj["config_file"] = kwargs["config_file"]
119
- ctx.obj["quiet"] = kwargs["quiet"]
120
+ ctx.obj['quiet'] = kwargs['quiet']
120
121
  log.setup_logging(
121
- ctx.obj["loglevel"],
122
- ctx.obj["quiet"],
122
+ ctx.obj['loglevel'],
123
+ ctx.obj['quiet'],
123
124
  )
124
125
  if CONF.trace_enabled:
125
- trace.setup_tracing(["method", "api"])
126
+ trace.setup_tracing(['method', 'api'])
126
127
 
127
128
  if not config_file_found:
128
- LOG = logging.getLogger("APRSD") # noqa: N806
129
+ LOG = logging.getLogger('APRSD') # noqa: N806
129
130
  LOG.error("No config file found!! run 'aprsd sample-config'")
130
131
 
131
- del kwargs["loglevel"]
132
- del kwargs["config_file"]
133
- del kwargs["quiet"]
132
+ del kwargs['loglevel']
133
+ del kwargs['config_file']
134
+ del kwargs['quiet']
134
135
  return f(*args, **kwargs)
135
136
 
136
137
  return update_wrapper(t.cast(F, new_func), f)
@@ -142,17 +143,17 @@ def process_standard_options_no_config(f: F) -> F:
142
143
  def new_func(*args, **kwargs):
143
144
  ctx = args[0]
144
145
  ctx.ensure_object(dict)
145
- ctx.obj["loglevel"] = kwargs["loglevel"]
146
- ctx.obj["config_file"] = kwargs["config_file"]
147
- ctx.obj["quiet"] = kwargs["quiet"]
146
+ ctx.obj['loglevel'] = kwargs['loglevel']
147
+ ctx.obj['config_file'] = kwargs['config_file']
148
+ ctx.obj['quiet'] = kwargs['quiet']
148
149
  log.setup_logging(
149
- ctx.obj["loglevel"],
150
- ctx.obj["quiet"],
150
+ ctx.obj['loglevel'],
151
+ ctx.obj['quiet'],
151
152
  )
152
153
 
153
- del kwargs["loglevel"]
154
- del kwargs["config_file"]
155
- del kwargs["quiet"]
154
+ del kwargs['loglevel']
155
+ del kwargs['config_file']
156
+ del kwargs['quiet']
156
157
  return f(*args, **kwargs)
157
158
 
158
159
  return update_wrapper(t.cast(F, new_func), f)
aprsd/client/base.py CHANGED
@@ -9,7 +9,7 @@ from aprsd.packets import core
9
9
  from aprsd.utils import keepalive_collector
10
10
 
11
11
  CONF = cfg.CONF
12
- LOG = logging.getLogger("APRSD")
12
+ LOG = logging.getLogger('APRSD')
13
13
 
14
14
 
15
15
  class APRSClient:
@@ -20,8 +20,8 @@ class APRSClient:
20
20
 
21
21
  connected = False
22
22
  login_status = {
23
- "success": False,
24
- "message": None,
23
+ 'success': False,
24
+ 'message': None,
25
25
  }
26
26
  filter = None
27
27
  lock = threading.Lock()
@@ -59,17 +59,20 @@ class APRSClient:
59
59
 
60
60
  @property
61
61
  def login_success(self):
62
- return self.login_status.get("success", False)
62
+ return self.login_status.get('success', False)
63
63
 
64
64
  @property
65
65
  def login_failure(self):
66
- return self.login_status["message"]
66
+ return self.login_status['message']
67
67
 
68
68
  def set_filter(self, filter):
69
69
  self.filter = filter
70
70
  if self._client:
71
71
  self._client.set_filter(filter)
72
72
 
73
+ def get_filter(self):
74
+ return self.filter
75
+
73
76
  @property
74
77
  def client(self):
75
78
  if not self._client:
@@ -80,16 +83,16 @@ class APRSClient:
80
83
  try:
81
84
  self._client = self.setup_connection()
82
85
  if self.filter:
83
- LOG.info("Creating APRS client filter")
86
+ LOG.info('Creating APRS client filter')
84
87
  self._client.set_filter(self.filter)
85
88
  except Exception as e:
86
- LOG.error(f"Failed to create APRS client: {e}")
89
+ LOG.error(f'Failed to create APRS client: {e}')
87
90
  self._client = None
88
91
  raise
89
92
 
90
93
  def stop(self):
91
94
  if self._client:
92
- LOG.info("Stopping client connection.")
95
+ LOG.info('Stopping client connection.')
93
96
  self._client.stop()
94
97
 
95
98
  def send(self, packet: core.Packet) -> None:
@@ -103,16 +106,16 @@ class APRSClient:
103
106
  @wrapt.synchronized(lock)
104
107
  def reset(self) -> None:
105
108
  """Call this to force a rebuild/reconnect."""
106
- LOG.info("Resetting client connection.")
109
+ LOG.info('Resetting client connection.')
107
110
  if self._client:
108
111
  self._client.close()
109
112
  del self._client
110
113
  self._create_client()
111
114
  else:
112
- LOG.warning("Client not initialized, nothing to reset.")
115
+ LOG.warning('Client not initialized, nothing to reset.')
113
116
 
114
117
  # Recreate the client
115
- LOG.info(f"Creating new client {self.client}")
118
+ LOG.info(f'Creating new client {self.client}')
116
119
 
117
120
  @abc.abstractmethod
118
121
  def setup_connection(self):
@@ -3,58 +3,60 @@ import sys
3
3
  import time
4
4
 
5
5
  import aprslib
6
- from aprslib.exceptions import LoginError
7
6
  import click
7
+ from aprslib.exceptions import LoginError
8
8
  from oslo_config import cfg
9
9
 
10
10
  import aprsd
11
- from aprsd import cli_helper, packets
12
- from aprsd import conf # noqa : F401
11
+ import aprsd.packets # noqa : F401
12
+ from aprsd import (
13
+ cli_helper,
14
+ conf, # noqa : F401
15
+ packets,
16
+ )
13
17
  from aprsd.client import client_factory
14
18
  from aprsd.main import cli
15
- import aprsd.packets # noqa : F401
16
19
  from aprsd.packets import collector
17
20
  from aprsd.packets import log as packet_log
18
21
  from aprsd.threads import tx
19
22
 
20
-
21
23
  CONF = cfg.CONF
22
- LOG = logging.getLogger("APRSD")
24
+ LOG = logging.getLogger('APRSD')
23
25
 
24
26
 
25
27
  @cli.command()
26
28
  @cli_helper.add_options(cli_helper.common_options)
27
29
  @click.option(
28
- "--aprs-login",
29
- envvar="APRS_LOGIN",
30
+ '--aprs-login',
31
+ envvar='APRS_LOGIN',
30
32
  show_envvar=True,
31
- help="What callsign to send the message from. Defaults to config entry.",
33
+ help='What callsign to send the message from. Defaults to config entry.',
32
34
  )
33
35
  @click.option(
34
- "--aprs-password",
35
- envvar="APRS_PASSWORD",
36
+ '--aprs-password',
37
+ envvar='APRS_PASSWORD',
36
38
  show_envvar=True,
37
- help="the APRS-IS password for APRS_LOGIN. Defaults to config entry.",
39
+ help='the APRS-IS password for APRS_LOGIN. Defaults to config entry.',
38
40
  )
39
41
  @click.option(
40
- "--no-ack",
41
- "-n",
42
+ '--no-ack',
43
+ '-n',
42
44
  is_flag=True,
43
45
  show_default=True,
44
46
  default=False,
45
47
  help="Don't wait for an ack, just sent it to APRS-IS and bail.",
46
48
  )
47
49
  @click.option(
48
- "--wait-response",
49
- "-w",
50
+ '--wait-response',
51
+ '-w',
50
52
  is_flag=True,
51
53
  show_default=True,
52
54
  default=False,
53
- help="Wait for a response to the message?",
55
+ help='Wait for a response to the message?',
54
56
  )
55
- @click.option("--raw", default=None, help="Send a raw message. Implies --no-ack")
56
- @click.argument("tocallsign", required=True)
57
- @click.argument("command", nargs=-1, required=True)
57
+ @click.option('--raw', default=None, help='Send a raw message. Implies --no-ack')
58
+ @click.argument('tocallsign', required=True)
59
+ @click.argument('command', nargs=-1, required=True)
58
60
  @click.pass_context
59
61
  @cli_helper.process_standard_options
60
62
  def send_message(
@@ -69,11 +71,11 @@ def send_message(
69
71
  ):
70
72
  """Send a message to a callsign via APRS_IS."""
71
73
  global got_ack, got_response
72
- quiet = ctx.obj["quiet"]
74
+ quiet = ctx.obj['quiet']
73
75
 
74
76
  if not aprs_login:
75
77
  if CONF.aprs_network.login == conf.client.DEFAULT_LOGIN:
76
- click.echo("Must set --aprs_login or APRS_LOGIN")
78
+ click.echo('Must set --aprs_login or APRS_LOGIN')
77
79
  ctx.exit(-1)
78
80
  return
79
81
  else:
@@ -81,15 +83,15 @@ def send_message(
81
83
 
82
84
  if not aprs_password:
83
85
  if not CONF.aprs_network.password:
84
- click.echo("Must set --aprs-password or APRS_PASSWORD")
86
+ click.echo('Must set --aprs-password or APRS_PASSWORD')
85
87
  ctx.exit(-1)
86
88
  return
87
89
  else:
88
90
  aprs_password = CONF.aprs_network.password
89
91
 
90
- LOG.info(f"APRSD LISTEN Started version: {aprsd.__version__}")
92
+ LOG.info(f'APRSD LISTEN Started version: {aprsd.__version__}')
91
93
  if type(command) is tuple:
92
- command = " ".join(command)
94
+ command = ' '.join(command)
93
95
  if not quiet:
94
96
  if raw:
95
97
  LOG.info(f"L'{aprs_login}' R'{raw}'")
@@ -129,7 +131,7 @@ def send_message(
129
131
  sys.exit(0)
130
132
 
131
133
  try:
132
- client_factory.create().client
134
+ client_factory.create().client # noqa: B018
133
135
  except LoginError:
134
136
  sys.exit(-1)
135
137
 
@@ -140,7 +142,7 @@ def send_message(
140
142
  # message
141
143
  if raw:
142
144
  tx.send(
143
- packets.Packet(from_call="", to_call="", raw=raw),
145
+ packets.Packet(from_call='', to_call='', raw=raw),
144
146
  direct=True,
145
147
  )
146
148
  sys.exit(0)
@@ -164,7 +166,7 @@ def send_message(
164
166
  aprs_client = client_factory.create().client
165
167
  aprs_client.consumer(rx_packet, raw=False)
166
168
  except aprslib.exceptions.ConnectionDrop:
167
- LOG.error("Connection dropped, reconnecting")
169
+ LOG.error('Connection dropped, reconnecting')
168
170
  time.sleep(5)
169
171
  # Force the deletion of the client object connected to aprs
170
172
  # This will cause a reconnect, next time client.get_client()
aprsd/cmds/server.py CHANGED
@@ -12,59 +12,24 @@ from aprsd.client import client_factory
12
12
  from aprsd.main import cli
13
13
  from aprsd.packets import collector as packet_collector
14
14
  from aprsd.packets import seen_list
15
- from aprsd.threads import aprsd as aprsd_threads
16
- from aprsd.threads import keepalive, registry, rx, tx
15
+ from aprsd.threads import keepalive, registry, rx, service, tx
17
16
  from aprsd.threads import stats as stats_thread
18
- from aprsd.utils import singleton
19
17
 
20
18
  CONF = cfg.CONF
21
- LOG = logging.getLogger("APRSD")
22
-
23
-
24
- @singleton
25
- class ServerThreads:
26
- """Registry for threads that the server command runs.
27
-
28
- This enables extensions to register a thread to run during
29
- the server command.
30
-
31
- """
32
-
33
- def __init__(self):
34
- self.threads: list[aprsd_threads.APRSDThread] = []
35
-
36
- def register(self, thread: aprsd_threads.APRSDThread):
37
- if not isinstance(thread, aprsd_threads.APRSDThread):
38
- raise TypeError(f"Thread {thread} is not an APRSDThread")
39
- self.threads.append(thread)
40
-
41
- def unregister(self, thread: aprsd_threads.APRSDThread):
42
- if not isinstance(thread, aprsd_threads.APRSDThread):
43
- raise TypeError(f"Thread {thread} is not an APRSDThread")
44
- self.threads.remove(thread)
45
-
46
- def start(self):
47
- """Start all threads in the list."""
48
- for thread in self.threads:
49
- thread.start()
50
-
51
- def join(self):
52
- """Join all the threads in the list"""
53
- for thread in self.threads:
54
- thread.join()
19
+ LOG = logging.getLogger('APRSD')
55
20
 
56
21
 
57
22
  # main() ###
58
23
  @cli.command()
59
24
  @cli_helper.add_options(cli_helper.common_options)
60
25
  @click.option(
61
- "-f",
62
- "--flush",
63
- "flush",
26
+ '-f',
27
+ '--flush',
28
+ 'flush',
64
29
  is_flag=True,
65
30
  show_default=True,
66
31
  default=False,
67
- help="Flush out all old aged messages on disk.",
32
+ help='Flush out all old aged messages on disk.',
68
33
  )
69
34
  @click.pass_context
70
35
  @cli_helper.process_standard_options
@@ -73,37 +38,37 @@ def server(ctx, flush):
73
38
  signal.signal(signal.SIGINT, aprsd_main.signal_handler)
74
39
  signal.signal(signal.SIGTERM, aprsd_main.signal_handler)
75
40
 
76
- server_threads = ServerThreads()
41
+ service_threads = service.ServiceThreads()
77
42
 
78
43
  level, msg = utils._check_version()
79
44
  if level:
80
45
  LOG.warning(msg)
81
46
  else:
82
47
  LOG.info(msg)
83
- LOG.info(f"APRSD Started version: {aprsd.__version__}")
48
+ LOG.info(f'APRSD Started version: {aprsd.__version__}')
84
49
 
85
50
  # Initialize the client factory and create
86
51
  # The correct client object ready for use
87
52
  if not client_factory.is_client_enabled():
88
- LOG.error("No Clients are enabled in config.")
53
+ LOG.error('No Clients are enabled in config.')
89
54
  sys.exit(-1)
90
55
 
91
56
  # Make sure we have 1 client transport enabled
92
57
  if not client_factory.is_client_enabled():
93
- LOG.error("No Clients are enabled in config.")
58
+ LOG.error('No Clients are enabled in config.')
94
59
  sys.exit(-1)
95
60
 
96
61
  if not client_factory.is_client_configured():
97
- LOG.error("APRS client is not properly configured in config file.")
62
+ LOG.error('APRS client is not properly configured in config file.')
98
63
  sys.exit(-1)
99
64
 
100
65
  # Creates the client object
101
- LOG.info("Creating client connection")
66
+ LOG.info('Creating client connection')
102
67
  aprs_client = client_factory.create()
103
68
  LOG.info(aprs_client)
104
69
  if not aprs_client.login_success:
105
70
  # We failed to login, will just quit!
106
- msg = f"Login Failure: {aprs_client.login_failure}"
71
+ msg = f'Login Failure: {aprs_client.login_failure}'
107
72
  LOG.error(msg)
108
73
  print(msg)
109
74
  sys.exit(-1)
@@ -114,7 +79,7 @@ def server(ctx, flush):
114
79
  # We register plugins first here so we can register each
115
80
  # plugins config options, so we can dump them all in the
116
81
  # log file output.
117
- LOG.info("Loading Plugin Manager and registering plugins")
82
+ LOG.info('Loading Plugin Manager and registering plugins')
118
83
  plugin_manager = plugin.PluginManager()
119
84
  plugin_manager.setup_plugins(load_help_plugin=CONF.load_help_plugin)
120
85
 
@@ -122,10 +87,10 @@ def server(ctx, flush):
122
87
  CONF.log_opt_values(LOG, logging.DEBUG)
123
88
  message_plugins = plugin_manager.get_message_plugins()
124
89
  watchlist_plugins = plugin_manager.get_watchlist_plugins()
125
- LOG.info("Message Plugins enabled and running:")
90
+ LOG.info('Message Plugins enabled and running:')
126
91
  for p in message_plugins:
127
92
  LOG.info(p)
128
- LOG.info("Watchlist Plugins enabled and running:")
93
+ LOG.info('Watchlist Plugins enabled and running:')
129
94
  for p in watchlist_plugins:
130
95
  LOG.info(p)
131
96
 
@@ -135,37 +100,37 @@ def server(ctx, flush):
135
100
 
136
101
  # Now load the msgTrack from disk if any
137
102
  if flush:
138
- LOG.debug("Flushing All packet tracking objects.")
103
+ LOG.debug('Flushing All packet tracking objects.')
139
104
  packet_collector.PacketCollector().flush()
140
105
  else:
141
106
  # Try and load saved MsgTrack list
142
- LOG.debug("Loading saved packet tracking data.")
107
+ LOG.debug('Loading saved packet tracking data.')
143
108
  packet_collector.PacketCollector().load()
144
109
 
145
110
  # Now start all the main processing threads.
146
111
 
147
- server_threads.register(keepalive.KeepAliveThread())
148
- server_threads.register(stats_thread.APRSDStatsStoreThread())
149
- server_threads.register(
112
+ service_threads.register(keepalive.KeepAliveThread())
113
+ service_threads.register(stats_thread.APRSDStatsStoreThread())
114
+ service_threads.register(
150
115
  rx.APRSDRXThread(
151
116
  packet_queue=threads.packet_queue,
152
117
  ),
153
118
  )
154
- server_threads.register(
119
+ service_threads.register(
155
120
  rx.APRSDPluginProcessPacketThread(
156
121
  packet_queue=threads.packet_queue,
157
122
  ),
158
123
  )
159
124
 
160
125
  if CONF.enable_beacon:
161
- LOG.info("Beacon Enabled. Starting Beacon thread.")
162
- server_threads.register(tx.BeaconSendThread())
126
+ LOG.info('Beacon Enabled. Starting Beacon thread.')
127
+ service_threads.register(tx.BeaconSendThread())
163
128
 
164
129
  if CONF.aprs_registry.enabled:
165
- LOG.info("Registry Enabled. Starting Registry thread.")
166
- server_threads.register(registry.APRSRegistryThread())
130
+ LOG.info('Registry Enabled. Starting Registry thread.')
131
+ service_threads.register(registry.APRSRegistryThread())
167
132
 
168
- server_threads.start()
169
- server_threads.join()
133
+ service_threads.start()
134
+ service_threads.join()
170
135
 
171
136
  return 0
aprsd/conf/log.py CHANGED
@@ -54,6 +54,11 @@ logging_opts = [
54
54
  default=True,
55
55
  help='Enable ANSI color codes in logging',
56
56
  ),
57
+ cfg.BoolOpt(
58
+ 'enable_console_stdout',
59
+ default=True,
60
+ help='Enable logging to the console/stdout.',
61
+ ),
57
62
  ]
58
63
 
59
64
 
aprsd/log/log.py CHANGED
@@ -84,15 +84,18 @@ def setup_logging(loglevel=None, quiet=False):
84
84
  logging.getLogger(name).handlers = []
85
85
  logging.getLogger(name).propagate = name not in disable_list
86
86
 
87
- handlers = [
88
- {
89
- 'sink': sys.stdout,
90
- 'serialize': False,
91
- 'format': CONF.logging.logformat,
92
- 'colorize': CONF.logging.enable_color,
93
- 'level': log_level,
94
- },
95
- ]
87
+ handlers = []
88
+ if CONF.logging.enable_console_stdout:
89
+ handlers.append(
90
+ {
91
+ 'sink': sys.stdout,
92
+ 'serialize': False,
93
+ 'format': CONF.logging.logformat,
94
+ 'colorize': CONF.logging.enable_color,
95
+ 'level': log_level,
96
+ },
97
+ )
98
+
96
99
  if CONF.logging.logfile:
97
100
  handlers.append(
98
101
  {