fb-tools 3.2.1__tar.gz → 3.3.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.
- {fb_tools-3.2.1 → fb_tools-3.3.0}/PKG-INFO +1 -1
- fb_tools-3.3.0/data/share/locale/de/LC_MESSAGES/fb_tools.mo +0 -0
- fb_tools-3.3.0/data/share/locale/en/LC_MESSAGES/fb_tools.mo +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/__init__.py +3 -1
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/application/get_file_rm.py +26 -15
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/handling_obj.py +225 -10
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/multi_config/inits.py +57 -37
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/socket_obj/__init__.py +7 -3
- fb_tools-3.2.1/data/share/locale/de/LC_MESSAGES/fb_tools.mo +0 -0
- fb_tools-3.2.1/data/share/locale/en/LC_MESSAGES/fb_tools.mo +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/LICENSE +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/README.md +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/pyproject.toml +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/any_config.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/app.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/application/__init__.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/application/cfg_converter.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/application/show_spinner.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/argparse_actions.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_app.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_options/__init__.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_options/dump.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_options/hjson.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_options/inifile.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_options/json.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_options/toml.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/cfg_options/yaml.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/colcts.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/collections.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/common.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/config.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/errors.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/handler/__init__.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/handler/lock.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/mailaddress.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/merge.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/multi_config/__init__.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/multi_config/files.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/obj.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/pidfile.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/socket_obj/tcp.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/socket_obj/unix.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/spinner.py +0 -0
- {fb_tools-3.2.1 → fb_tools-3.3.0}/src/fb_tools/xlate.py +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -27,11 +27,13 @@ MIN_INDENT = 2
|
|
|
27
27
|
# Maximal indention of configuration files
|
|
28
28
|
MAX_INDENT = 12
|
|
29
29
|
|
|
30
|
+
PROJECT_NAME = "fb-tools"
|
|
31
|
+
|
|
30
32
|
# Own modules
|
|
31
33
|
|
|
32
34
|
from .mailaddress import MailAddress, MailAddressList, QualifiedMailAddress # noqa: F401
|
|
33
35
|
from .multi_config import BaseMultiConfig # noqa: F401
|
|
34
36
|
|
|
35
|
-
__version__ = "3.
|
|
37
|
+
__version__ = "3.3.0"
|
|
36
38
|
|
|
37
39
|
# vim: ts=4 et list
|
|
@@ -29,7 +29,7 @@ from ..common import get_monday, pp
|
|
|
29
29
|
from ..errors import FbAppError
|
|
30
30
|
from ..xlate import XLATOR
|
|
31
31
|
|
|
32
|
-
__version__ = "2.2.
|
|
32
|
+
__version__ = "2.2.2"
|
|
33
33
|
LOG = logging.getLogger(__name__)
|
|
34
34
|
|
|
35
35
|
_ = XLATOR.gettext
|
|
@@ -171,8 +171,10 @@ class GetFileRmApplication(BaseApplication):
|
|
|
171
171
|
if v >= self.min_keep_days:
|
|
172
172
|
self._keep_days = v
|
|
173
173
|
else:
|
|
174
|
-
msg = _("Wrong value {v
|
|
175
|
-
v=value,
|
|
174
|
+
msg = _("Wrong value {v} for {n}, must be >= {m}").format(
|
|
175
|
+
v=self.colored(repr(value), "red"),
|
|
176
|
+
n="keep_days",
|
|
177
|
+
m=self.colored(str(self.min_keep_days), "yellow"),
|
|
176
178
|
)
|
|
177
179
|
raise ValueError(msg)
|
|
178
180
|
|
|
@@ -188,8 +190,10 @@ class GetFileRmApplication(BaseApplication):
|
|
|
188
190
|
if v >= self.min_keep_weeks:
|
|
189
191
|
self._keep_weeks = v
|
|
190
192
|
else:
|
|
191
|
-
msg = _("Wrong value {v
|
|
192
|
-
v=value,
|
|
193
|
+
msg = _("Wrong value {v} for {n}, must be >= {m}").format(
|
|
194
|
+
v=self.colored(repr(value), "red"),
|
|
195
|
+
n="keep_weeks",
|
|
196
|
+
m=self.colored(str(self.min_keep_weeks), "yellow"),
|
|
193
197
|
)
|
|
194
198
|
raise ValueError(msg)
|
|
195
199
|
|
|
@@ -205,8 +209,10 @@ class GetFileRmApplication(BaseApplication):
|
|
|
205
209
|
if v >= self.min_keep_months:
|
|
206
210
|
self._keep_months = v
|
|
207
211
|
else:
|
|
208
|
-
msg = _("Wrong value {v
|
|
209
|
-
v=value,
|
|
212
|
+
msg = _("Wrong value {v} for {n}, must be >= {m}").format(
|
|
213
|
+
v=self.colored(repr(value), "red"),
|
|
214
|
+
n="keep_months",
|
|
215
|
+
m=self.colored(str(self.min_keep_months), "yellow"),
|
|
210
216
|
)
|
|
211
217
|
raise ValueError(msg)
|
|
212
218
|
|
|
@@ -222,8 +228,10 @@ class GetFileRmApplication(BaseApplication):
|
|
|
222
228
|
if v >= self.min_keep_years:
|
|
223
229
|
self._keep_years = v
|
|
224
230
|
else:
|
|
225
|
-
msg = _("Wrong value {v
|
|
226
|
-
v=value,
|
|
231
|
+
msg = _("Wrong value {v} for {n}, must be >= {m}").format(
|
|
232
|
+
v=self.colored(repr(value), "red"),
|
|
233
|
+
n="keep_years",
|
|
234
|
+
m=self.colored(str(self.min_keep_years), "yellow"),
|
|
227
235
|
)
|
|
228
236
|
raise ValueError(msg)
|
|
229
237
|
|
|
@@ -239,8 +247,10 @@ class GetFileRmApplication(BaseApplication):
|
|
|
239
247
|
if v >= self.min_keep_last:
|
|
240
248
|
self._keep_last = v
|
|
241
249
|
else:
|
|
242
|
-
msg = _("Wrong value {v
|
|
243
|
-
v=value,
|
|
250
|
+
msg = _("Wrong value {v} for {n}, must be >= {m}").format(
|
|
251
|
+
v=self.colored(repr(value), "red"),
|
|
252
|
+
n="keep_last",
|
|
253
|
+
m=self.colored(str(self.min_keep_last), "yellow"),
|
|
244
254
|
)
|
|
245
255
|
raise ValueError(msg)
|
|
246
256
|
|
|
@@ -368,7 +378,7 @@ class GetFileRmApplication(BaseApplication):
|
|
|
368
378
|
if not check_date_pattern(pat):
|
|
369
379
|
raise WrongDatePattern(self.date_pattern)
|
|
370
380
|
if self.verbose > 1:
|
|
371
|
-
LOG.debug(_("Resolving date pattern {
|
|
381
|
+
LOG.debug(_("Resolving date pattern {}.").format(self.colored(pat, "cyan")))
|
|
372
382
|
|
|
373
383
|
self._pattern = (
|
|
374
384
|
pat.replace("%Y", r"(?P<year>\d{4})")
|
|
@@ -395,7 +405,7 @@ class GetFileRmApplication(BaseApplication):
|
|
|
395
405
|
for fname in self.args.files:
|
|
396
406
|
|
|
397
407
|
if self.verbose > 2:
|
|
398
|
-
LOG.debug(_("Checking given file {
|
|
408
|
+
LOG.debug(_("Checking given file {} ...").format(self.colored(fname, "cyan")))
|
|
399
409
|
|
|
400
410
|
given_paths = []
|
|
401
411
|
single_fpath = Path(fname)
|
|
@@ -429,8 +439,9 @@ class GetFileRmApplication(BaseApplication):
|
|
|
429
439
|
match = self.re_date.search(str(fpath))
|
|
430
440
|
if not match:
|
|
431
441
|
LOG.warning(
|
|
432
|
-
_("File {fi
|
|
433
|
-
fi=str(fpath),
|
|
442
|
+
_("File {fi} does not match pattern {pa}.").format(
|
|
443
|
+
fi=self.colored(str(fpath), "yellow"),
|
|
444
|
+
pa=self.colord(repr(self.date_pattern), "yellow"),
|
|
434
445
|
)
|
|
435
446
|
)
|
|
436
447
|
continue
|
|
@@ -24,17 +24,13 @@ import shutil
|
|
|
24
24
|
import signal
|
|
25
25
|
import socket
|
|
26
26
|
import sys
|
|
27
|
+
from pathlib import Path
|
|
27
28
|
from shlex import quote
|
|
28
29
|
from subprocess import PIPE, Popen
|
|
29
30
|
|
|
30
31
|
# from codecs import BOM_BE, BOM_LE, BOM_UTF32_BE, BOM_UTF32_LE, BOM_UTF8
|
|
31
32
|
# from collections import OrderedDict
|
|
32
33
|
|
|
33
|
-
try:
|
|
34
|
-
import pathlib
|
|
35
|
-
except ImportError:
|
|
36
|
-
import pathlib2 as pathlib
|
|
37
|
-
|
|
38
34
|
if sys.version_info[0] >= 3:
|
|
39
35
|
from subprocess import SubprocessError, TimeoutExpired
|
|
40
36
|
else:
|
|
@@ -57,6 +53,7 @@ import six
|
|
|
57
53
|
|
|
58
54
|
# Own modules
|
|
59
55
|
from . import DEFAULT_TERMINAL_HEIGHT, DEFAULT_TERMINAL_WIDTH
|
|
56
|
+
from . import PROJECT_NAME
|
|
60
57
|
from .common import caller_search_path, encode_or_bust, pp, to_bool, to_str
|
|
61
58
|
from .common import indent, is_sequence
|
|
62
59
|
from .errors import AbortAppError
|
|
@@ -69,7 +66,7 @@ from .errors import WriteTimeoutError
|
|
|
69
66
|
from .obj import FbBaseObject
|
|
70
67
|
from .xlate import XLATOR, format_list
|
|
71
68
|
|
|
72
|
-
__version__ = "2.
|
|
69
|
+
__version__ = "2.6.0"
|
|
73
70
|
LOG = logging.getLogger(__name__)
|
|
74
71
|
|
|
75
72
|
_ = XLATOR.gettext
|
|
@@ -182,19 +179,23 @@ class HandlingObject(FbBaseObject):
|
|
|
182
179
|
* appname (str - rw) (inherited from FbBaseObject)
|
|
183
180
|
* assumed_answer (None or bool - rw)
|
|
184
181
|
* base_dir (pathlib.Path - rw) (inherited from FbBaseObject)
|
|
182
|
+
* cache_dir (pathlib.Path - rw)
|
|
183
|
+
* data_dir (pathlib.Path - rw)
|
|
185
184
|
* force (bool - rw)
|
|
186
185
|
* initialized (bool - rw) (inherited from FbBaseObject)
|
|
187
186
|
* interrupted (bool - rw)
|
|
188
187
|
* is_venv (bool - ro)
|
|
188
|
+
* project_name (str) - rw)
|
|
189
189
|
* prompt_timeout (int - rw)
|
|
190
190
|
* quiet (bool - rw)
|
|
191
191
|
* simulate (bool - rw)
|
|
192
|
+
* state_dir (pathlib.Path - rw)
|
|
192
193
|
* terminal_has_colors (bool - rw)
|
|
193
194
|
* verbose (int - rw) (inherited from FbBaseObject)
|
|
194
195
|
* version (str - ro) (inherited from FbBaseObject)
|
|
195
196
|
|
|
196
197
|
Public attributes:
|
|
197
|
-
* add_search_paths Array of
|
|
198
|
+
* add_search_paths Array of Path
|
|
198
199
|
* signals_dont_interrupt Array of int
|
|
199
200
|
"""
|
|
200
201
|
|
|
@@ -221,6 +222,12 @@ class HandlingObject(FbBaseObject):
|
|
|
221
222
|
"6",
|
|
222
223
|
)
|
|
223
224
|
|
|
225
|
+
# Project name, used for the subdirectory name of different default directories
|
|
226
|
+
# e.g. log directory, data directory, cache dir, runtime dir a.s.o.
|
|
227
|
+
default_project_name = PROJECT_NAME
|
|
228
|
+
|
|
229
|
+
re_project_name = re.compile(r"^[a-z0-9]([a-z0-9+\-_\.]*[a-z0-9])?$", re.IGNORECASE)
|
|
230
|
+
|
|
224
231
|
# -------------------------------------------------------------------------
|
|
225
232
|
def __init__(
|
|
226
233
|
self,
|
|
@@ -230,6 +237,11 @@ class HandlingObject(FbBaseObject):
|
|
|
230
237
|
simulate=None,
|
|
231
238
|
force=None,
|
|
232
239
|
assumed_answer=None,
|
|
240
|
+
project_name=None,
|
|
241
|
+
data_dir=None,
|
|
242
|
+
cache_dir=None,
|
|
243
|
+
state_dir=None,
|
|
244
|
+
runtime_dir=None,
|
|
233
245
|
*args,
|
|
234
246
|
**kwargs,
|
|
235
247
|
):
|
|
@@ -248,11 +260,22 @@ class HandlingObject(FbBaseObject):
|
|
|
248
260
|
@type: bool
|
|
249
261
|
@param assumed_answer: The assumed answer to all yes/no questions.
|
|
250
262
|
@type: bool or None
|
|
263
|
+
@param project_name: Project name used for subdirectories in default directories
|
|
264
|
+
@type: str
|
|
265
|
+
@param data_dir: directory to which user-specific data files should be stored.
|
|
266
|
+
@type: Path or None
|
|
267
|
+
@param cache_dir: directory to which user-specific non-essential data files
|
|
268
|
+
should be stored.
|
|
269
|
+
@type: Path or None
|
|
270
|
+
@param state_dir: directory to which user-specific state files should be stored.
|
|
271
|
+
@type: Path or None
|
|
272
|
+
@param runtime_dir: directory to which non-essential runtime files should be stored.
|
|
273
|
+
@type: Path or None
|
|
251
274
|
|
|
252
275
|
@param appname: name of the current running application
|
|
253
276
|
@type: str
|
|
254
277
|
@param base_dir: base directory used for different purposes
|
|
255
|
-
@type: str or
|
|
278
|
+
@type: str or Path
|
|
256
279
|
@param initialized: initialisation of this object is complete after init
|
|
257
280
|
@type: bool
|
|
258
281
|
@param verbose: verbosity level (0 - 9)
|
|
@@ -266,10 +289,19 @@ class HandlingObject(FbBaseObject):
|
|
|
266
289
|
self._assumed_answer = None
|
|
267
290
|
self._address_family = self.default_address_family
|
|
268
291
|
|
|
292
|
+
self._project_name = self.default_project_name
|
|
293
|
+
if project_name:
|
|
294
|
+
self.project_name = project_name
|
|
295
|
+
|
|
296
|
+
self._data_dir = self.get_default_data_dir() / self.project_name
|
|
297
|
+
self._cache_dir = self.get_default_cache_dir() / self.project_name
|
|
298
|
+
self._state_dir = self.get_default_state_dir() / self.project_name
|
|
299
|
+
self._runtime_dir = self.get_default_runtime_dir() / self.project_name
|
|
300
|
+
|
|
269
301
|
self.add_search_paths = []
|
|
270
302
|
"""
|
|
271
303
|
@ivar: Additional search paths of executing external commands
|
|
272
|
-
@type: Array of
|
|
304
|
+
@type: Array of Path
|
|
273
305
|
"""
|
|
274
306
|
|
|
275
307
|
self._prompt_timeout = self.default_prompt_timeout
|
|
@@ -292,6 +324,14 @@ class HandlingObject(FbBaseObject):
|
|
|
292
324
|
version=version,
|
|
293
325
|
**kwargs,
|
|
294
326
|
)
|
|
327
|
+
if data_dir:
|
|
328
|
+
self._data_dir = data_dir
|
|
329
|
+
if cache_dir:
|
|
330
|
+
self.cache_dir = cache_dir
|
|
331
|
+
if state_dir:
|
|
332
|
+
self.state_dir = state_dir
|
|
333
|
+
if runtime_dir:
|
|
334
|
+
self.runtime_dir = runtime_dir
|
|
295
335
|
|
|
296
336
|
if simulate is not None:
|
|
297
337
|
self.simulate = simulate
|
|
@@ -427,6 +467,102 @@ class HandlingObject(FbBaseObject):
|
|
|
427
467
|
family = socket.AF_INET6
|
|
428
468
|
self._address_family = family
|
|
429
469
|
|
|
470
|
+
# -----------------------------------------------------------
|
|
471
|
+
@property
|
|
472
|
+
def project_name(self):
|
|
473
|
+
"""Return the project name used for subdirectories in default directories."""
|
|
474
|
+
return self._project_name
|
|
475
|
+
|
|
476
|
+
@project_name.setter
|
|
477
|
+
def project_name(self, value):
|
|
478
|
+
if value is None:
|
|
479
|
+
self._project_name = self.default_project_name
|
|
480
|
+
return
|
|
481
|
+
|
|
482
|
+
val = str(value)
|
|
483
|
+
if val == "":
|
|
484
|
+
raise ValueError(_("A project name must not be empty."))
|
|
485
|
+
|
|
486
|
+
if not self.re_project_name.match(val):
|
|
487
|
+
msg = _("Invalid project name {} given.").format(self.colored(val, "red"))
|
|
488
|
+
raise ValueError(msg)
|
|
489
|
+
|
|
490
|
+
# -----------------------------------------------------------
|
|
491
|
+
@property
|
|
492
|
+
def data_dir(self):
|
|
493
|
+
"""Return the directory to which user-specific data files should be stored."""
|
|
494
|
+
return self._data_dir
|
|
495
|
+
|
|
496
|
+
@data_dir.setter
|
|
497
|
+
def data_dir(self, value):
|
|
498
|
+
if value is None:
|
|
499
|
+
self._data_dir = self.get_default_data_dir() / self.project_name
|
|
500
|
+
return
|
|
501
|
+
|
|
502
|
+
path = Path(value)
|
|
503
|
+
if path.is_absolute():
|
|
504
|
+
self._data_dir = path
|
|
505
|
+
return
|
|
506
|
+
|
|
507
|
+
self._data_dir = path.resolve()
|
|
508
|
+
|
|
509
|
+
# -----------------------------------------------------------
|
|
510
|
+
@property
|
|
511
|
+
def cache_dir(self):
|
|
512
|
+
"""Return the dir to which user-specific non-essential data files should be stored."""
|
|
513
|
+
return self._cache_dir
|
|
514
|
+
|
|
515
|
+
@cache_dir.setter
|
|
516
|
+
def cache_dir(self, value):
|
|
517
|
+
if value is None:
|
|
518
|
+
self._cache_dir = self.get_default_cache_dir() / self.project_name
|
|
519
|
+
return
|
|
520
|
+
|
|
521
|
+
path = Path(value)
|
|
522
|
+
if path.is_absolute():
|
|
523
|
+
self._cache_dir = path
|
|
524
|
+
return
|
|
525
|
+
|
|
526
|
+
self._cache_dir = path.resolve()
|
|
527
|
+
|
|
528
|
+
# -----------------------------------------------------------
|
|
529
|
+
@property
|
|
530
|
+
def state_dir(self):
|
|
531
|
+
"""Return the directory to which user-specific state files should be stored."""
|
|
532
|
+
return self._state_dir
|
|
533
|
+
|
|
534
|
+
@state_dir.setter
|
|
535
|
+
def state_dir(self, value):
|
|
536
|
+
if value is None:
|
|
537
|
+
self._state_dir = self.get_default_state_dir() / self.project_name
|
|
538
|
+
return
|
|
539
|
+
|
|
540
|
+
path = Path(value)
|
|
541
|
+
if path.is_absolute():
|
|
542
|
+
self._state_dir = path
|
|
543
|
+
return
|
|
544
|
+
|
|
545
|
+
self._state_dir = path.resolve()
|
|
546
|
+
|
|
547
|
+
# -----------------------------------------------------------
|
|
548
|
+
@property
|
|
549
|
+
def runtime_dir(self):
|
|
550
|
+
"""Return the directory to which user-specific runtime files should be stored."""
|
|
551
|
+
return self._runtime_dir
|
|
552
|
+
|
|
553
|
+
@runtime_dir.setter
|
|
554
|
+
def runtime_dir(self, value):
|
|
555
|
+
if value is None:
|
|
556
|
+
self._runtime_dir = self.get_default_runtime_dir() / self.project_name
|
|
557
|
+
return
|
|
558
|
+
|
|
559
|
+
path = Path(value)
|
|
560
|
+
if path.is_absolute():
|
|
561
|
+
self._runtime_dir = path
|
|
562
|
+
return
|
|
563
|
+
|
|
564
|
+
self._runtime_dir = path.resolve()
|
|
565
|
+
|
|
430
566
|
# -------------------------------------------------------------------------
|
|
431
567
|
@classmethod
|
|
432
568
|
def init_yes_no_lists(cls):
|
|
@@ -450,6 +586,80 @@ class HandlingObject(FbBaseObject):
|
|
|
450
586
|
)
|
|
451
587
|
cls.re_yes_no = re.compile(cls.pattern_yes_no, re.IGNORECASE)
|
|
452
588
|
|
|
589
|
+
# -------------------------------------------------------------------------
|
|
590
|
+
@classmethod
|
|
591
|
+
def get_default_data_dir(cls):
|
|
592
|
+
"""Return the default base path to the data directory."""
|
|
593
|
+
xdg_dir = os.environ.get("XDG_DATA_HOME", None)
|
|
594
|
+
xdg_dirs = os.environ.get("XDG_DATA_DIRS", None)
|
|
595
|
+
|
|
596
|
+
if xdg_dirs:
|
|
597
|
+
xdg_dirs = [Path(x) for x in xdg_dirs.split(os.pathsep)]
|
|
598
|
+
else:
|
|
599
|
+
xdg_dirs = []
|
|
600
|
+
|
|
601
|
+
# If $XDG_DATA_HOME was given, then use it, no matter whether it exists
|
|
602
|
+
if xdg_dir:
|
|
603
|
+
# LOG.debug(f"Using data_dir {xdg_dir!r}.")
|
|
604
|
+
return Path(xdg_dir)
|
|
605
|
+
|
|
606
|
+
# Search for the first existing dir in XDG_DATA_DIRS. If not existing,
|
|
607
|
+
# use the first one, no matter whether it exists
|
|
608
|
+
if xdg_dirs:
|
|
609
|
+
for ddir in xdg_dirs:
|
|
610
|
+
# LOG.debug(f"Checking data_dir {str(ddir)!r}.")
|
|
611
|
+
if ddir.exists and ddir.is_dir() and os.access(str(ddir), os.W_OK):
|
|
612
|
+
# LOG.debug(f"Using data_dir {str(ddir)!r}.")
|
|
613
|
+
return ddir
|
|
614
|
+
if not os.geteuid():
|
|
615
|
+
return xdg_dirs[0]
|
|
616
|
+
|
|
617
|
+
# Init as root user
|
|
618
|
+
if not os.geteuid():
|
|
619
|
+
return Path("/var/lib")
|
|
620
|
+
|
|
621
|
+
# Init as non root user
|
|
622
|
+
return Path("~/.local/share").expanduser()
|
|
623
|
+
|
|
624
|
+
# -------------------------------------------------------------------------
|
|
625
|
+
@classmethod
|
|
626
|
+
def get_default_cache_dir(cls):
|
|
627
|
+
"""Get the default base path to the cache directory."""
|
|
628
|
+
xdg_dir = os.environ.get("XDG_CACHE_HOME", None)
|
|
629
|
+
|
|
630
|
+
if xdg_dir:
|
|
631
|
+
return Path(xdg_dir)
|
|
632
|
+
|
|
633
|
+
if not os.geteuid():
|
|
634
|
+
return Path("/var/cache")
|
|
635
|
+
|
|
636
|
+
return Path("~/.cache").expanduser()
|
|
637
|
+
|
|
638
|
+
# -------------------------------------------------------------------------
|
|
639
|
+
@classmethod
|
|
640
|
+
def get_default_state_dir(cls):
|
|
641
|
+
"""Get the default base path to the state directory."""
|
|
642
|
+
xdg_dir = os.environ.get("XDG_STATE_HOME", None)
|
|
643
|
+
|
|
644
|
+
if xdg_dir:
|
|
645
|
+
return Path(xdg_dir)
|
|
646
|
+
|
|
647
|
+
if not os.geteuid():
|
|
648
|
+
return Path("/var/lib")
|
|
649
|
+
|
|
650
|
+
return Path("~/.local/state").expanduser()
|
|
651
|
+
|
|
652
|
+
# -------------------------------------------------------------------------
|
|
653
|
+
@classmethod
|
|
654
|
+
def get_default_runtime_dir(cls):
|
|
655
|
+
"""Get the default base path to the runtime directory."""
|
|
656
|
+
xdg_dir = os.environ.get("XDG_RUNTIME_DIR", None)
|
|
657
|
+
|
|
658
|
+
if xdg_dir:
|
|
659
|
+
return Path(xdg_dir)
|
|
660
|
+
|
|
661
|
+
return Path("/run")
|
|
662
|
+
|
|
453
663
|
# -------------------------------------------------------------------------
|
|
454
664
|
def as_dict(self, short=True):
|
|
455
665
|
"""
|
|
@@ -464,15 +674,20 @@ class HandlingObject(FbBaseObject):
|
|
|
464
674
|
res = super(HandlingObject, self).as_dict(short=short)
|
|
465
675
|
res["address_family"] = self.address_family
|
|
466
676
|
res["assumed_answer"] = self.assumed_answer
|
|
677
|
+
res["cache_dir"] = self.cache_dir
|
|
678
|
+
res["data_dir"] = self.data_dir
|
|
467
679
|
res["fileio_timeout"] = self.fileio_timeout
|
|
468
680
|
res["force"] = self.force
|
|
469
681
|
res["interrupted"] = self.interrupted
|
|
470
682
|
res["is_venv"] = self.is_venv
|
|
471
683
|
res["no_list"] = self.no_list
|
|
472
684
|
res["pattern_yes_no"] = self.pattern_yes_no
|
|
685
|
+
res["project_name"] = self.project_name
|
|
473
686
|
res["prompt_timeout"] = self.prompt_timeout
|
|
474
687
|
res["quiet"] = self.quiet
|
|
688
|
+
res["runtime_dir"] = self.runtime_dir
|
|
475
689
|
res["simulate"] = self.simulate
|
|
690
|
+
res["state_dir"] = self.state_dir
|
|
476
691
|
res["terminal_has_colors"] = self.terminal_has_colors
|
|
477
692
|
res["yes_list"] = self.yes_list
|
|
478
693
|
|
|
@@ -637,7 +852,7 @@ class HandlingObject(FbBaseObject):
|
|
|
637
852
|
@rtype: str or None
|
|
638
853
|
|
|
639
854
|
"""
|
|
640
|
-
cmd =
|
|
855
|
+
cmd = Path(cmd)
|
|
641
856
|
|
|
642
857
|
if self.verbose > 2:
|
|
643
858
|
LOG.debug(_("Searching for command {!r} ...").format(str(cmd)))
|
|
@@ -25,7 +25,7 @@ import six
|
|
|
25
25
|
from ..common import is_sequence, to_str
|
|
26
26
|
from ..xlate import XLATOR
|
|
27
27
|
|
|
28
|
-
__version__ = "0.
|
|
28
|
+
__version__ = "0.4.0"
|
|
29
29
|
|
|
30
30
|
LOG = logging.getLogger(__name__)
|
|
31
31
|
|
|
@@ -43,54 +43,74 @@ class MultiCfgInitMixin:
|
|
|
43
43
|
|
|
44
44
|
# -------------------------------------------------------------------------
|
|
45
45
|
def _init_config_dirs(self, additional_cfgdirs=None):
|
|
46
|
-
|
|
46
|
+
"""Create the list of possible configuration directories."""
|
|
47
47
|
self.config_dirs = []
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
# Insert in this list possible paths in decreasing priority
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
if
|
|
53
|
-
|
|
51
|
+
# Exceptionally given additional config directory or directories
|
|
52
|
+
if additional_cfgdirs:
|
|
53
|
+
if is_sequence(additional_cfgdirs):
|
|
54
|
+
for item in additional_cfgdirs:
|
|
55
|
+
path = Path(item)
|
|
56
|
+
if path not in self.config_dirs:
|
|
57
|
+
self.config_dirs.append(path)
|
|
58
|
+
else:
|
|
59
|
+
path = Path(additional_cfgdirs)
|
|
60
|
+
self.config_dirs.append(Path(additional_cfgdirs))
|
|
54
61
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if path in self.config_dirs:
|
|
59
|
-
self.config_dirs.remove(path)
|
|
62
|
+
# Current working directory
|
|
63
|
+
path = Path.cwd()
|
|
64
|
+
if path not in self.config_dirs:
|
|
60
65
|
self.config_dirs.append(path)
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
# The base directory itselv (whatever it is)
|
|
68
|
+
path = self.base_dir
|
|
69
|
+
if path not in self.config_dirs:
|
|
70
|
+
self.config_dirs.append(path)
|
|
66
71
|
|
|
72
|
+
# ${base_dir}/etc
|
|
67
73
|
path = self.base_dir / "etc"
|
|
68
|
-
if path in self.config_dirs:
|
|
69
|
-
self.config_dirs.
|
|
70
|
-
self.config_dirs.append(path)
|
|
74
|
+
if path not in self.config_dirs:
|
|
75
|
+
self.config_dirs.append(path)
|
|
71
76
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
# ${current_working_directory}/etc
|
|
78
|
+
path = Path.cwd() / "etc"
|
|
79
|
+
if path not in self.config_dirs:
|
|
80
|
+
self.config_dirs.append(path)
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
if
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
# ${virtual_env_directory}/etc
|
|
83
|
+
if self.is_venv():
|
|
84
|
+
path = Path(sys.prefix) / "etc"
|
|
85
|
+
if path not in self.config_dirs:
|
|
86
|
+
self.config_dirs.append(path)
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
# ${XDG_CONFIG_HOME}/${config_dir}
|
|
89
|
+
xdg_dir = os.environ.get("XDG_CONFIG_HOME", None)
|
|
90
|
+
if xdg_dir:
|
|
91
|
+
path = Path(xdg_dir) / self.config_dir
|
|
92
|
+
else:
|
|
93
|
+
path = Path("~/.config").expanduser() / self.config_dir
|
|
94
|
+
if path not in self.config_dirs:
|
|
95
|
+
self.config_dirs.append(path)
|
|
96
|
+
|
|
97
|
+
# All directories in $XDG_CONFIG_DIRS, appended by ${config_dir}
|
|
98
|
+
xdg_dirs = os.environ.get("XDG_CONFIG_DIRS", None)
|
|
99
|
+
if xdg_dirs:
|
|
100
|
+
xdg_dirs = [Path(x) for x in xdg_dirs.split(os.pathsep)]
|
|
101
|
+
for path in xdg_dirs:
|
|
102
|
+
path = path / self.config_dir
|
|
103
|
+
if path not in self.config_dirs:
|
|
88
104
|
self.config_dirs.append(path)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
|
|
106
|
+
# last, but not least /etc/${config_dir}
|
|
107
|
+
path = Path("/etc") / self.config_dir
|
|
108
|
+
if path not in self.config_dirs:
|
|
109
|
+
self.config_dirs.append(path)
|
|
110
|
+
|
|
111
|
+
# And now revert the list, so the lowest prioritized dirs come first,
|
|
112
|
+
# and the highest prioritized dir comes at last
|
|
113
|
+
self.config_dirs.reverse()
|
|
94
114
|
|
|
95
115
|
# -------------------------------------------------------------------------
|
|
96
116
|
def _init_stems(self, append_appname_to_stems, additional_stems=None):
|
|
@@ -34,7 +34,7 @@ from ..errors import GenericSocketError
|
|
|
34
34
|
from ..handling_obj import HandlingObject
|
|
35
35
|
from ..xlate import XLATOR
|
|
36
36
|
|
|
37
|
-
__version__ = "0.8.
|
|
37
|
+
__version__ = "0.8.1"
|
|
38
38
|
|
|
39
39
|
LOG = logging.getLogger(__name__)
|
|
40
40
|
|
|
@@ -689,14 +689,18 @@ class GenericSocket(HandlingObject):
|
|
|
689
689
|
def __enter__(self):
|
|
690
690
|
"""Execute this action, when this socket will be opened by the with-block."""
|
|
691
691
|
LOG.debug(
|
|
692
|
-
_("Opened the {cls} {name
|
|
692
|
+
_("Opened the {cls} {name} ...").format(
|
|
693
|
+
cls=self.__class__.__name__, name=self.colored(self.name, "cyan")
|
|
694
|
+
)
|
|
693
695
|
)
|
|
694
696
|
|
|
695
697
|
# -------------------------------------------------------------------------
|
|
696
698
|
def __exit__(self, exc_type, exc_val, exc_traceback):
|
|
697
699
|
"""Exit action at the end of the with-block - closing socket."""
|
|
698
700
|
LOG.debug(
|
|
699
|
-
_("Closing the {cls} {name
|
|
701
|
+
_("Closing the {cls} {name} ...").format(
|
|
702
|
+
cls=self.__class__.__name__, name=self.colored(self.name, "cyan")
|
|
703
|
+
)
|
|
700
704
|
)
|
|
701
705
|
|
|
702
706
|
self.close()
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|