fb-tools 2.6.3__tar.gz → 2.8.0__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.
Files changed (76) hide show
  1. {fb_tools-2.6.3/lib/fb_tools.egg-info → fb_tools-2.8.0}/PKG-INFO +1 -1
  2. {fb_tools-2.6.3 → fb_tools-2.8.0}/bin/get-file-to-remove +3 -3
  3. {fb_tools-2.6.3 → fb_tools-2.8.0}/bin/myip +1 -1
  4. fb_tools-2.8.0/bin/show-spinner +78 -0
  5. {fb_tools-2.6.3 → fb_tools-2.8.0}/bin/update-ddns +1 -1
  6. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/__init__.py +2 -1
  7. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/app.py +82 -44
  8. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/cfg_app.py +1 -1
  9. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/colcts.py +1 -1
  10. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/collections.py +1 -1
  11. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/common.py +4 -2
  12. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/config.py +1 -1
  13. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/ddns/__init__.py +41 -3
  14. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/ddns/myip_app.py +1 -1
  15. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/ddns/update_app.py +1 -1
  16. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/errors.py +57 -1
  17. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/get_file_rm_app.py +1 -1
  18. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/handler/__init__.py +1 -1
  19. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/handler/lock.py +1 -1
  20. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/handling_obj.py +157 -26
  21. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/local_version.py +1 -1
  22. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/merge.py +1 -1
  23. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/multi_config/__init__.py +1 -1
  24. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/multi_config/files.py +1 -1
  25. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/multi_config/inits.py +1 -1
  26. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/multi_config/read.py +1 -1
  27. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/obj.py +24 -28
  28. fb_tools-2.8.0/lib/fb_tools/show_spinner_app.py +300 -0
  29. fb_tools-2.8.0/lib/fb_tools/socket_obj/__init__.py +668 -0
  30. fb_tools-2.8.0/lib/fb_tools/socket_obj/tcp.py +493 -0
  31. fb_tools-2.8.0/lib/fb_tools/socket_obj/unix.py +531 -0
  32. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/xlate.py +1 -1
  33. {fb_tools-2.6.3 → fb_tools-2.8.0/lib/fb_tools.egg-info}/PKG-INFO +1 -1
  34. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools.egg-info/SOURCES.txt +9 -0
  35. fb_tools-2.8.0/locale/de/LC_MESSAGES/fb_tools.mo +0 -0
  36. {fb_tools-2.6.3 → fb_tools-2.8.0}/locale/de/LC_MESSAGES/fb_tools.po +471 -144
  37. fb_tools-2.8.0/locale/en/LC_MESSAGES/fb_tools.mo +0 -0
  38. {fb_tools-2.6.3 → fb_tools-2.8.0}/locale/en/LC_MESSAGES/fb_tools.po +460 -143
  39. {fb_tools-2.6.3 → fb_tools-2.8.0}/locale/fb_tools.pot +460 -144
  40. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/general.py +4 -1
  41. fb_tools-2.8.0/test/listener_thread.py +103 -0
  42. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_15_mailaddress.py +2 -2
  43. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_20_handling_object.py +48 -1
  44. fb_tools-2.8.0/test/test_35_sockets.py +178 -0
  45. fb_tools-2.8.0/test/test_36_unixsocket.py +172 -0
  46. fb_tools-2.8.0/test/test_37_tcpsocket.py +151 -0
  47. fb_tools-2.6.3/locale/de/LC_MESSAGES/fb_tools.mo +0 -0
  48. fb_tools-2.6.3/locale/en/LC_MESSAGES/fb_tools.mo +0 -0
  49. {fb_tools-2.6.3 → fb_tools-2.8.0}/LICENSE +0 -0
  50. {fb_tools-2.6.3 → fb_tools-2.8.0}/MANIFEST.in +0 -0
  51. {fb_tools-2.6.3 → fb_tools-2.8.0}/README.md +0 -0
  52. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/argparse_actions.py +0 -0
  53. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/ddns/config.py +0 -0
  54. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/ddns/errors.py +0 -0
  55. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/mailaddress.py +0 -0
  56. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/pidfile.py +0 -0
  57. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools/spinner.py +0 -0
  58. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools.egg-info/dependency_links.txt +0 -0
  59. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools.egg-info/requires.txt +0 -0
  60. {fb_tools-2.6.3 → fb_tools-2.8.0}/lib/fb_tools.egg-info/top_level.txt +0 -0
  61. {fb_tools-2.6.3 → fb_tools-2.8.0}/setup.cfg +0 -0
  62. {fb_tools-2.6.3 → fb_tools-2.8.0}/setup.py +0 -0
  63. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/call_script.sh +0 -0
  64. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/call_sleep.sh +0 -0
  65. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/do_sleep +0 -0
  66. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_00_errors.py +0 -0
  67. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_05_common.py +0 -0
  68. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_10_base_object.py +0 -0
  69. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_13_colcts.py +0 -0
  70. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_17_multicfg.py +0 -0
  71. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_18_pidfile.py +0 -0
  72. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_25_ddns_update_status.py +0 -0
  73. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_30_base_handler.py +0 -0
  74. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_33_lock.py +0 -0
  75. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_40_app_modules.py +0 -0
  76. {fb_tools-2.6.3 → fb_tools-2.8.0}/test/test_50_spinner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fb_tools
3
- Version: 2.6.3
3
+ Version: 2.8.0
4
4
  Summary: Modules for common used objects, error classes and methods.
5
5
  Home-page: https://github.com/fbrehm/python_fb_tools
6
6
  Author: Frank Brehm
@@ -4,7 +4,7 @@
4
4
  @summary: Print a newline separated list of files generated from file globbing patterns.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import print_function
@@ -58,8 +58,8 @@ from fb_tools.xlate import XLATOR
58
58
 
59
59
  _ = XLATOR.gettext
60
60
 
61
- __author__ = 'Frank Brehm <frank.brehm@pixelpark.com>'
62
- __copyright__ = '(C) 2024 by Frank Brehm, Pixelpark GmbH, Berlin'
61
+ __author__ = 'Frank Brehm <frank@brehm-online.com>'
62
+ __copyright__ = '(C) 2024 by Frank Brehm, Berlin'
63
63
 
64
64
  appname = my_path.name
65
65
 
@@ -4,7 +4,7 @@
4
4
  @summary: Prints the public NAT IPv4 address and/or the automatic assigned IPv6 address.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import print_function
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ @summary: Print a newline separated list of files generated from file globbing patterns.
5
+
6
+ @author: Frank Brehm
7
+ @contact: frank@brehm-online.com
8
+ @copyright: © 2024 by Frank Brehm, Berlin
9
+ """
10
+ from __future__ import print_function
11
+
12
+ # Standard modules
13
+ import locale
14
+ import sys
15
+
16
+ try:
17
+ from pathlib import Path
18
+ except ImportError:
19
+ from pathlib2 import Path
20
+
21
+ __exp_py_version_major__ = 3
22
+ __min_py_version_minor__ = 6
23
+
24
+ if sys.version_info[0] != __exp_py_version_major__:
25
+ print('This script is intended to use with Python {}.'.format(
26
+ __exp_py_version_major__), file=sys.stderr)
27
+ print('You are using Python: {0}.{1}.{2}-{3}-{4}.'.format(
28
+ *sys.version_info) + '\n', file=sys.stderr)
29
+ sys.exit(1)
30
+
31
+ if sys.version_info[1] < __min_py_version_minor__:
32
+ print('A minimal Python version of {maj}.{min} is necessary to execute this script.'.format(
33
+ maj=__exp_py_version_major__, min=__min_py_version_minor__), file=sys.stderr)
34
+ print('You are using Python: {0}.{1}.{2}-{3}-{4}.'.format(
35
+ *sys.version_info) + '\n', file=sys.stderr)
36
+ sys.exit(1)
37
+
38
+ my_path = Path(__file__)
39
+ my_real_path = my_path.resolve()
40
+ bin_path = my_real_path.parent
41
+ base_dir = bin_path.parent
42
+ lib_dir = base_dir.joinpath('lib')
43
+ module_dir = lib_dir.joinpath('fb_tools')
44
+
45
+ # print("My path: {!r}".format(str(my_path)))
46
+ # print("My real path: {!r}".format(str(my_real_path)))
47
+ # print("Bin path: {!r}".format(str(bin_path)))
48
+ # print("Base dir: {!r}".format(str(base_dir)))
49
+ # print("Lib dir: {!r}".format(str(lib_dir)))
50
+ # print("Module dir: {!r}".format(str(module_dir)))
51
+
52
+ if module_dir.exists():
53
+ sys.path.insert(0, str(lib_dir))
54
+
55
+ # own modules:
56
+ from fb_tools.show_spinner_app import ShowSpinnerApplication
57
+ from fb_tools.xlate import XLATOR
58
+
59
+ _ = XLATOR.gettext
60
+
61
+ __author__ = 'Frank Brehm <frank@brehm-online.com>'
62
+ __copyright__ = '(C) 2024 by Frank Brehm, Berlin'
63
+
64
+ appname = my_path.name
65
+
66
+ locale.setlocale(locale.LC_ALL, '')
67
+
68
+ app = ShowSpinnerApplication(appname=appname, base_dir=base_dir)
69
+ app.initialized = True
70
+
71
+ if app.verbose > 2:
72
+ print(_('{c}-Object:\n{a}').format(c=app.__class__.__name__, a=app), file=sys.stderr)
73
+
74
+ app()
75
+
76
+ sys.exit(0)
77
+
78
+ # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
@@ -4,7 +4,7 @@
4
4
  @summary: Update the A and/or AAAA record at ddns.de with the current IP address.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import print_function
@@ -13,6 +13,7 @@ UTF8_ENCODING = 'utf-8'
13
13
 
14
14
  DDNS_CFG_BASENAME = 'ddns.ini'
15
15
  MAX_TIMEOUT = 3600
16
+ MAX_PORT_NUMBER = (2 ** 16) - 1
16
17
  DEFAULT_ENCODING = UTF8_ENCODING
17
18
  DEFAULT_TERMINAL_WIDTH = 99
18
19
  DEFAULT_TERMINAL_HEIGHT = 40
@@ -22,6 +23,6 @@ DEFAULT_TERMINAL_HEIGHT = 40
22
23
  from .mailaddress import MailAddress, MailAddressList, QualifiedMailAddress # noqa: F401
23
24
  from .multi_config import BaseMultiConfig # noqa: F401
24
25
 
25
- __version__ = '2.6.3'
26
+ __version__ = '2.8.0'
26
27
 
27
28
  # vim: ts=4 et list
@@ -38,7 +38,7 @@ from .xlate import __lib_dir__ as __xlate_lib_dir__
38
38
  from .xlate import __mo_file__ as __xlate_mo_file__
39
39
  from .xlate import __module_dir__ as __xlate_module_dir__
40
40
 
41
- __version__ = '2.2.2'
41
+ __version__ = '2.3.0'
42
42
  LOG = logging.getLogger(__name__)
43
43
 
44
44
  SIGNAL_NAMES = {
@@ -57,7 +57,40 @@ _ = XLATOR.gettext
57
57
 
58
58
  # =============================================================================
59
59
  class BaseApplication(HandlingObject):
60
- """Class for the base application objects."""
60
+ """
61
+ Class for the base application objects.
62
+
63
+ Properties:
64
+ * address_family (str or int - rw) (inherited from HandlingObject)
65
+ * appname (str - rw) (inherited from FbBaseObject)
66
+ * argparse_epilog (None or str - ro)
67
+ * argparse_prefix_chars (str - ro)
68
+ * assumed_answer (None or bool - rw) (inherited from HandlingObject)
69
+ * base_dir (pathlib.Path - rw) (inherited from FbBaseObject)
70
+ * description (str - ro)
71
+ * exit_value (int - rw)
72
+ * exitvalue (int - rw)
73
+ * force (bool - rw) (inherited from HandlingObject)
74
+ * force_desc_msg (None or str - ro)
75
+ * initialized (bool - rw) (inherited from FbBaseObject)
76
+ * interrupted (bool - rw) (inherited from HandlingObject)
77
+ * is_venv (bool - ro) (inherited from HandlingObject)
78
+ * prompt_timeout (int - rw) (inherited from HandlingObject)
79
+ * quiet (bool - rw) (inherited from HandlingObject)
80
+ * simulate (bool - rw) (inherited from HandlingObject)
81
+ * testing_args (array od str - ro)
82
+ * usage (str - ro)
83
+ * usage_term None or int - ro)
84
+ * verbose (int - rw) (inherited from FbBaseObject)
85
+ * version (str - ro) (inherited from FbBaseObject)
86
+
87
+ Public attributes:
88
+ * add_search_paths Array of pathlib.Path (inherited from HandlingObject)
89
+ * arg_parser argparse.ArgumentParser
90
+ * args Namespace
91
+ * env Dict
92
+ * signals_dont_interrupt Array of int (inherited from HandlingObject)
93
+ """
61
94
 
62
95
  re_prefix = re.compile(r'^[a-z0-9][a-z0-9_]*$', re.IGNORECASE)
63
96
  re_anum = re.compile(r'[^A-Z0-9_]+', re.IGNORECASE)
@@ -77,72 +110,77 @@ class BaseApplication(HandlingObject):
77
110
  self, version=__pkg_version__, usage=None, description=None, testing_args=None,
78
111
  argparse_epilog=None, argparse_prefix_chars='-', env_prefix=None,
79
112
  initialized=None, *args, **kwargs):
80
- """Initialise a BaseApplication object."""
81
- self.arg_parser = None
82
- """
83
- @ivar: argparser object to parse commandline parameters
84
- @type: argparse.ArgumentParser
85
- """
86
-
87
- self.args = None
88
- """
89
- @ivar: an object containing all commandline parameters
90
- after parsing them
91
- @type: Namespace
92
113
  """
114
+ Initialise a BaseApplication object.
93
115
 
94
- self._exit_value = 0
95
- """
96
- @ivar: return value of the application for exiting with sys.exit().
116
+ @param appname: name of the current running application
117
+ @type: str
118
+ @param argparse_epilog: an epilog displayed at the end of the argparse help screen
119
+ @type: str
120
+ @param argparse_prefix_chars: The set of characters that prefix optional arguments.
121
+ @type: str
122
+ @param assumed_answer: The assumed answer to all yes/no questions
123
+ @type: bool or None
124
+ @param base_dir: base directory used for different purposes
125
+ @type: str or pathlib.Path
126
+ @param description: a short text describing the application
127
+ @type: str
128
+ @param env_prefix: a prefix for environment variables to detect them and to assign
129
+ @type: None or str
130
+ @param force: Forced execution of something
131
+ @type: bool
132
+ @param initialized: initialisation of this object is complete after init
133
+ @type: bool
134
+ @param quiet: Quiet execution
135
+ @type: bool
136
+ @param simulate: actions with changing a state are not executed
137
+ @type: bool
138
+ @param terminal_has_colors: has the current terminal colored output
139
+ @type: bool
140
+ @param testing_args: Command line arguments to use for testing purposes.
141
+ @type: None or list of strings
142
+ @param verbose: verbosity level (0 - 9)
97
143
  @type: int
98
- """
99
-
100
- self._usage = usage
101
- """
102
- @ivar: usage text used on argparse
144
+ @type: usage: usage text used on argparse
103
145
  @type: str
104
- """
105
-
106
- self._description = description
107
- """
108
- @ivar: a short text describing the application
146
+ @param version: version string of the current object or application
109
147
  @type: str
110
148
  """
111
-
149
+ self._usage = usage
150
+ self._description = description
112
151
  self._testing_args = testing_args
152
+ self._argparse_epilog = argparse_epilog
153
+ self._argparse_prefix_chars = argparse_prefix_chars
154
+ self._env_prefix = None
155
+
156
+ self._exit_value = 0
113
157
  """
114
- @ivar: Command line arguments to use for testing purposes.
115
- @type: None or list of strings
158
+ @ivar: return value of the application for exiting with sys.exit().
159
+ @type: int
116
160
  """
117
161
 
118
- self._argparse_epilog = argparse_epilog
162
+ self.arg_parser = None
119
163
  """
120
- @ivar: an epilog displayed at the end of the argparse help screen
121
- @type: str
164
+ @ivar: argparser object to parse commandline parameters
165
+ @type: argparse.ArgumentParser
122
166
  """
123
167
 
124
- self._argparse_prefix_chars = argparse_prefix_chars
168
+ self.args = None
125
169
  """
126
- @ivar: The set of characters that prefix optional arguments.
127
- @type: str
170
+ @ivar: an object containing all commandline parameters
171
+ after parsing them
172
+ @type: Namespace
128
173
  """
129
174
 
130
175
  self.env = {}
131
176
  """
132
- @ivar: a dictionary with all application specifiv environment variables,
177
+ @ivar: a dictionary with all application specific environment variables,
133
178
  they will detected by the env_prefix property of this object,
134
179
  and their names will transformed before saving their values in
135
180
  self.env by removing the env_prefix from the variable name.
136
181
  @type: dict
137
182
  """
138
183
 
139
- self._env_prefix = None
140
- """
141
- @ivar: a prefix for environment variables to detect them and to assign
142
- their transformed names and their values in self.env
143
- @type: str
144
- """
145
-
146
184
  super(BaseApplication, self).__init__(
147
185
  version=version,
148
186
  initialized=False,
@@ -4,7 +4,7 @@
4
4
  @summary: The module for the application object with support for configuration files.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import absolute_import
@@ -6,7 +6,7 @@
6
6
  They are providing alternatives to Python's general purpose built-in frozen_set, set and dict.
7
7
 
8
8
  @author: Frank Brehm
9
- @contact: frank.brehm@pixelpark.com
9
+ @contact: frank@brehm-online.com
10
10
  @copyright: © 2024 by Frank Brehm, Berlin
11
11
  """
12
12
  from __future__ import absolute_import
@@ -6,7 +6,7 @@
6
6
  They are providing alternatives to Python's general purpose built-in frozen_set, set and dict.
7
7
 
8
8
  @author: Frank Brehm
9
- @contact: frank.brehm@pixelpark.com
9
+ @contact: frank@brehm-online.com
10
10
  @copyright: © 2024 by Frank Brehm, Berlin
11
11
  """
12
12
  from __future__ import absolute_import
@@ -4,7 +4,7 @@
4
4
  @summary: The module for common used functions.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
 
@@ -37,7 +37,7 @@ import six
37
37
  from .errors import InvalidTimeIntervalError
38
38
  from .xlate import XLATOR
39
39
 
40
- __version__ = '2.1.0'
40
+ __version__ = '2.1.1'
41
41
 
42
42
  _ = XLATOR.gettext
43
43
 
@@ -64,6 +64,8 @@ RE_FQDN = re.compile(
64
64
  r'(?=^.{4,253}$)(^((?!-)[a-z0-9-]{1,63}(?<!-)\.)+[a-z]{2,63}\.?$)',
65
65
  re.IGNORECASE)
66
66
 
67
+ RE_FIRST_LINE = re.compile(r'^([^\n]*)(\r?\n)')
68
+
67
69
  CUR_RADIX = locale.nl_langinfo(locale.RADIXCHAR)
68
70
  CUR_THOUSEP = locale.nl_langinfo(locale.THOUSEP)
69
71
  H2MB_PAT = r'^\s*\+?(\d+(?:' + re.escape(CUR_THOUSEP) + r'\d+)*(?:'
@@ -4,7 +4,7 @@
4
4
  @summary: A module for providing a configuration.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import absolute_import
@@ -4,7 +4,7 @@
4
4
  @summary: The base module for all DDNS related classes.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import absolute_import, print_function
@@ -46,10 +46,11 @@ from .. import __version__ as GLOBAL_VERSION
46
46
  from ..argparse_actions import DirectoryOptionAction
47
47
  from ..cfg_app import FbConfigApplication
48
48
  from ..common import pp
49
+ from ..common import to_bool
49
50
  from ..errors import IoTimeoutError
50
51
  from ..xlate import XLATOR, format_list
51
52
 
52
- __version__ = '2.2.3'
53
+ __version__ = '2.3.0'
53
54
  LOG = logging.getLogger(__name__)
54
55
 
55
56
  _ = XLATOR.gettext
@@ -65,6 +66,8 @@ class BaseDdnsApplication(FbConfigApplication):
65
66
  work_directory_must_exists = False
66
67
  work_directory_must_be_writeable = False
67
68
 
69
+ default_verify_server_cert = True
70
+
68
71
  # -------------------------------------------------------------------------
69
72
  def __init__(
70
73
  self, appname=None, verbose=0, version=GLOBAL_VERSION, base_dir=None,
@@ -76,6 +79,7 @@ class BaseDdnsApplication(FbConfigApplication):
76
79
  description = _('This is a base DDNS related application.')
77
80
 
78
81
  self._user_agent = '{}/{}'.format(self.library_name, GLOBAL_VERSION)
82
+ self._verify_server_cert = self.default_verify_server_cert
79
83
 
80
84
  super(BaseDdnsApplication, self).__init__(
81
85
  appname=appname, verbose=verbose, version=version, base_dir=base_dir,
@@ -99,6 +103,19 @@ class BaseDdnsApplication(FbConfigApplication):
99
103
  raise DdnsAppError(_('Invalid user agent {!r} given.').format(value))
100
104
  self._user_agent = str(value).strip()
101
105
 
106
+ # -----------------------------------------------------------
107
+ @property
108
+ def verify_server_cert(self):
109
+ """Return whether to verify the SSL certificate of the requested server."""
110
+ return self._verify_server_cert
111
+
112
+ @verify_server_cert.setter
113
+ def verify_server_cert(self, value):
114
+ if value is None:
115
+ self._verify_server_cert = self.default_verify_server_cert
116
+ return
117
+ self._verify_server_cert = to_bool(value)
118
+
102
119
  # -------------------------------------------------------------------------
103
120
  @property
104
121
  def has_dns_module(self):
@@ -119,6 +136,7 @@ class BaseDdnsApplication(FbConfigApplication):
119
136
  res = super(BaseDdnsApplication, self).as_dict(short=short)
120
137
  res['has_dns_module'] = self.has_dns_module
121
138
  res['user_agent'] = self.user_agent
139
+ res['verify_server_cert'] = self.verify_server_cert
122
140
 
123
141
  return res
124
142
 
@@ -176,6 +194,14 @@ class BaseDdnsApplication(FbConfigApplication):
176
194
  DdnsConfiguration.default_timeout),
177
195
  )
178
196
 
197
+ ddns_group.add_argument(
198
+ '-k', '--insecure', dest='insecure', action='store_true',
199
+ help=_(
200
+ 'By default, every secure connection {app} makes is verified to be secure before '
201
+ 'the request takes place. This option makes {app} skip the verification step and '
202
+ 'proceed without checking.').format(app=self.appname),
203
+ )
204
+
179
205
  super(BaseDdnsApplication, self).init_arg_parser()
180
206
 
181
207
  # -------------------------------------------------------------------------
@@ -225,6 +251,9 @@ class BaseDdnsApplication(FbConfigApplication):
225
251
  logging.getLogger('requests').setLevel(logging.WARNING)
226
252
  self.loglevel_requests_set = True
227
253
 
254
+ if self.args.insecure:
255
+ self.verify_server_cert = False
256
+
228
257
  self.initialized = True
229
258
 
230
259
  # -------------------------------------------------------------------------
@@ -251,6 +280,15 @@ class BaseDdnsApplication(FbConfigApplication):
251
280
  self, url, method='GET', data=None, headers=None, may_simulate=False,
252
281
  return_json=True):
253
282
  """Perform the underlying Web request."""
283
+ verify = None
284
+ if url.startswith('https://'):
285
+ if self.verify_server_cert:
286
+ verify = True
287
+ else:
288
+ verify = False
289
+ urllib3.disable_warnings()
290
+ LOG.debug(f'Verifying remote server certificate: {verify!r}.')
291
+
254
292
  if headers is None:
255
293
  headers = {}
256
294
 
@@ -282,7 +320,7 @@ class BaseDdnsApplication(FbConfigApplication):
282
320
 
283
321
  session = requests.Session()
284
322
  response = session.request(
285
- method, url, data=data, headers=headers, timeout=self.cfg.timeout)
323
+ method, url, data=data, headers=headers, timeout=self.cfg.timeout, verify=verify)
286
324
 
287
325
  except (
288
326
  socket.timeout, urllib3.exceptions.ConnectTimeoutError,
@@ -4,7 +4,7 @@
4
4
  @summary: The module for the classes of the myip application.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import absolute_import, print_function
@@ -4,7 +4,7 @@
4
4
  @summary: The module for the classes of the update-ddns application.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import absolute_import, print_function
@@ -14,7 +14,7 @@ import signal
14
14
  # Own modules
15
15
  from .xlate import XLATOR
16
16
 
17
- __version__ = '2.3.1'
17
+ __version__ = '2.5.1'
18
18
 
19
19
  _ = XLATOR.gettext
20
20
  ngettext = XLATOR.ngettext
@@ -150,6 +150,13 @@ class AbortAppError(FbAppError):
150
150
  pass
151
151
 
152
152
 
153
+ # =============================================================================
154
+ class ExitAppError(FbAppError):
155
+ """Special exception class exiting the application."""
156
+
157
+ pass
158
+
159
+
153
160
  # =============================================================================
154
161
  class FbCfgAppError(FbAppError):
155
162
  """Generic exception class for all configured application classes."""
@@ -572,6 +579,55 @@ class FileAccessError(CommonFileError, PermissionError):
572
579
  return msg
573
580
 
574
581
 
582
+ # =============================================================================
583
+ class GenericSocketError(FbError):
584
+ """Base error class for all special exceptions raised in a socket module."""
585
+
586
+ pass
587
+
588
+
589
+ # =============================================================================
590
+ class SocketReadTimeoutError(IoTimeoutError, GenericSocketError):
591
+ """Special error class indicating a timout error on a read operation on a socket."""
592
+
593
+ # -------------------------------------------------------------------------
594
+ def __init__(self, timeout, filename=None):
595
+ """
596
+ Initialise an SocketReadTimeoutError exception.
597
+
598
+ @param timeout: the timout in seconds leading to the error
599
+ @type timeout: float
600
+ @param filename: the filename of the socket leading to the error
601
+ @type filename: str
602
+ """
603
+ strerror = _('Timeout error on reading from socket')
604
+ fn = None
605
+ if filename is not None:
606
+ fn = str(filename)
607
+ super(SocketReadTimeoutError, self).__init__(strerror, timeout, fn)
608
+
609
+
610
+ # =============================================================================
611
+ class SocketWriteTimeoutError(IoTimeoutError, GenericSocketError):
612
+ """Special error class indicating a timout error on a write operation on a socket."""
613
+
614
+ # -------------------------------------------------------------------------
615
+ def __init__(self, timeout, filename=None):
616
+ """
617
+ Initialise an SocketWriteTimeoutError exception.
618
+
619
+ @param timeout: the timout in seconds leading to the error
620
+ @type timeout: float
621
+ @param filename: the filename of the socket leading to the error
622
+ @type filename: str
623
+ """
624
+ strerror = _('Timeout error on writing to socket')
625
+ fn = None
626
+ if filename is not None:
627
+ fn = str(filename)
628
+ super(SocketWriteTimeoutError, self).__init__(strerror, timeout, fn)
629
+
630
+
575
631
  # =============================================================================
576
632
 
577
633
  if __name__ == '__main__':
@@ -4,7 +4,7 @@
4
4
  @summary: The module for the get-file-to-remove application object.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import absolute_import
@@ -4,7 +4,7 @@
4
4
  @summary: A base handler module for underlaying actions.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
 
10
10
  """
@@ -4,7 +4,7 @@
4
4
  @summary: Module for a extended handler module, which has additional methods for locking.
5
5
 
6
6
  @author: Frank Brehm
7
- @contact: frank.brehm@pixelpark.com
7
+ @contact: frank@brehm-online.com
8
8
  @copyright: © 2024 by Frank Brehm, Berlin
9
9
  """
10
10
  from __future__ import absolute_import