prim-ctrl 0.8.3__tar.gz → 0.8.5__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prim-ctrl
3
- Version: 0.8.3
3
+ Version: 0.8.5
4
4
  Summary: Primitive Ctrl - Remote control of your phone's Primitive FTPd Android SFTP server and optionally Tailscale VPN.
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -44,13 +44,19 @@ class LevelFormatter(logging.Formatter):
44
44
  return self.formatters.get(record.levelno, self.default_formatter).format(record)
45
45
 
46
46
  class Logger(logging.Logger):
47
+ timestamp: bool = False
48
+
49
+ @staticmethod
50
+ def setConfiguration(timestamp: bool):
51
+ Logger.timestamp = timestamp
52
+
47
53
  def __init__(self, name, level = logging.NOTSET):
48
54
  super().__init__(name, level)
49
- self.exitcode = 0
55
+ self.addHandler(logging.StreamHandler(sys.stderr))
56
+ self.configure()
50
57
 
51
- def prepare(self, timestamp: bool, silent: bool):
52
- handler = logging.StreamHandler(sys.stderr)
53
- handler.setFormatter(
58
+ def configure(self):
59
+ formatter = (
54
60
  LevelFormatter(
55
61
  {
56
62
  logging.WARNING: '%(asctime)s %(message)s',
@@ -58,7 +64,7 @@ class Logger(logging.Logger):
58
64
  logging.DEBUG: '%(asctime)s %(levelname)s %(message)s',
59
65
  },
60
66
  '%(asctime)s %(name)s: %(levelname)s: %(message)s')
61
- if timestamp else
67
+ if Logger.timestamp else
62
68
  LevelFormatter(
63
69
  {
64
70
  logging.WARNING: '%(message)s',
@@ -67,9 +73,16 @@ class Logger(logging.Logger):
67
73
  },
68
74
  '%(name)s: %(levelname)s: %(message)s')
69
75
  )
70
- self.addHandler(handler)
71
- if self.level == logging.NOTSET:
72
- self.setLevel(logging.WARNING if silent else logging.INFO)
76
+ for handler in self.handlers:
77
+ handler.setFormatter(formatter)
78
+
79
+ class MainLogger(Logger):
80
+ def __init__(self, name, level = logging.NOTSET):
81
+ super().__init__(name, level)
82
+ self.exitcode = 0
83
+
84
+ def setConfiguration(self, level: int):
85
+ self.setLevel(level)
73
86
 
74
87
  def exception_or_error(self, e: Exception):
75
88
  if self.level == logging.NOTSET or self.level == logging.DEBUG:
@@ -109,7 +122,7 @@ class LazyStr:
109
122
  self.result = str(self.func)
110
123
  return self.result
111
124
 
112
- logger = Logger(Path(sys.argv[0]).name)
125
+ logger = MainLogger(Path(sys.argv[0]).name)
113
126
 
114
127
  ########
115
128
 
@@ -727,8 +740,10 @@ class Funnel(Pingable):
727
740
  self.external_port = external_port
728
741
  self.external_url = f'https://{machine_name}.{tailscale.tailnet}:{external_port}{local_path}'
729
742
  self.local_tailscale = local_tailscale
743
+ self.external_public_dns_resolver_address = None
730
744
  self.external_public_dns_resolver = None
731
- self.external_tailscale_dns_resolvers = None
745
+ self.external_tailscale_dns_resolver_addresses = None
746
+ self.external_tailscale_dns_resolver = None
732
747
 
733
748
  async def wait_for(self, available: bool, timeout: float):
734
749
  self._sleepcounter = 0
@@ -737,25 +752,33 @@ class Funnel(Pingable):
737
752
  async def ping(self, availability_hint: bool | None = None):
738
753
  logger.debug("Resolving DNS for %s (%s:%s)", LazyStr(self.get_class_name), self.external_name, self.external_port)
739
754
  # first try at Tailscale's DNSs, if they don't know, we should not resolve at a public DNS and cache nxdomain for 5 minutes
740
- if self.external_tailscale_dns_resolvers is None:
755
+ if self.external_tailscale_dns_resolver_addresses is None:
741
756
  resolvers = [await self.local_tailscale.external_tailscale_dns_resolver()]
742
757
  resolvers.extend(await self._external_tailscale_dns_resolvers())
743
- self.external_tailscale_dns_resolvers = [ExternalDnsResolver(resolver) for resolver in resolvers]
758
+ self.external_tailscale_dns_resolver_addresses = resolvers
759
+ resolver = self.external_tailscale_dns_resolver
760
+ if resolver is None:
761
+ resolver = ExternalDnsResolver(self.external_tailscale_dns_resolver_addresses[0])
744
762
  try:
745
- _answer = await self.external_tailscale_dns_resolvers[0].resolve(self.external_name, self.external_port)
763
+ _answer = await resolver.resolve(self.external_name, self.external_port)
746
764
  except Exception as e:
747
- logger.debug("Resolving at Tailscale's external DNS %s has failed: %s", self.external_tailscale_dns_resolvers[0].where, LazyStr(exception_repr, e))
765
+ logger.debug("Resolving at Tailscale's external DNS %s has failed: %s", self.external_tailscale_dns_resolver_addresses[0], LazyStr(exception_repr, e))
748
766
  # move current resolver to the end of the list
749
- self.external_tailscale_dns_resolvers.append(self.external_tailscale_dns_resolvers.pop(0))
767
+ self.external_tailscale_dns_resolver_addresses.append(self.external_tailscale_dns_resolver_addresses.pop(0))
750
768
  return False
769
+ self.external_tailscale_dns_resolver = resolver
751
770
  # then try at a public DNS
752
- if self.external_public_dns_resolver is None:
753
- self.external_public_dns_resolver = ExternalDnsResolver(await self.local_tailscale.external_public_dns_resolver())
771
+ if self.external_public_dns_resolver_address is None:
772
+ self.external_public_dns_resolver_address = await self.local_tailscale.external_public_dns_resolver()
773
+ resolver = self.external_public_dns_resolver
774
+ if resolver is None:
775
+ resolver = ExternalDnsResolver(self.external_public_dns_resolver_address)
754
776
  try:
755
- _answer = await self.external_public_dns_resolver.resolve(self.external_name, self.external_port)
777
+ _answer = await resolver.resolve(self.external_name, self.external_port)
756
778
  except Exception as e:
757
779
  logger.debug("Resolving at public external DNS has failed: %s", LazyStr(exception_repr, e))
758
780
  return False
781
+ self.external_public_dns_resolver = resolver
759
782
  return True
760
783
 
761
784
  async def _sleep_while_wait(self, available: bool):
@@ -1158,9 +1181,11 @@ class Control:
1158
1181
 
1159
1182
  @staticmethod
1160
1183
  def prepare(args: argparse.Namespace):
1161
- if args.debug:
1162
- logger.setLevel(logging.DEBUG)
1163
- logger.prepare(args.timestamp or args.debug, args.silent)
1184
+ Logger.setConfiguration(args.timestamp or args.debug)
1185
+ logging.setLoggerClass(Logger)
1186
+ logger.setConfiguration(
1187
+ logging.DEBUG if args.debug else logging.WARNING if args.silent else logging.INFO) #NOSONAR(S3358)
1188
+ logger.configure()
1164
1189
 
1165
1190
  if args.accept_cellular and args.intent != 'start':
1166
1191
  raise ValueError("The --accept-cellular options can be enabled only for the start intent")
@@ -3,7 +3,7 @@ packages = [{include = "prim_ctrl"}]
3
3
 
4
4
  [project]
5
5
  name = "prim-ctrl"
6
- version = "0.8.3"
6
+ version = "0.8.5"
7
7
  description = "Primitive Ctrl - Remote control of your phone's Primitive FTPd Android SFTP server and optionally Tailscale VPN."
8
8
  license = "Apache-2.0"
9
9
  authors = [
File without changes
File without changes