linuxfabrik-lib 4.0.2__tar.gz → 4.2.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.
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/PKG-INFO +1 -1
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/db_mysql.py +116 -1
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/db_sqlite.py +117 -11
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/disk.py +17 -10
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/endoflifedate.py +105 -71
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/linuxfabrik_lib.egg-info/PKG-INFO +1 -1
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/pyproject.toml +1 -1
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/LICENSE +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/README.md +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/__init__.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/args.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/base.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/cache.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/distro.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/dmidecode.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/feedparser.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/globals.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/grassfish.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/huawei.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/human.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/icinga.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/infomaniak.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/jitsi.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/keycloak.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/lftest.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/librenms.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/linuxfabrik_lib.egg-info/SOURCES.txt +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/linuxfabrik_lib.egg-info/dependency_links.txt +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/linuxfabrik_lib.egg-info/requires.txt +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/linuxfabrik_lib.egg-info/top_level.txt +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/net.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/nextcloud.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/nodebb.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/powershell.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/psutil.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/qts.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/redfish.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/rocket.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/setup.cfg +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/shell.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/smb.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/time.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/txt.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/uptimerobot.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/url.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/veeam.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/version.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/wildfly.py +0 -0
- {linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/winrm.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: linuxfabrik-lib
|
|
3
|
-
Version: 4.0
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: Python libraries used in various Linuxfabrik projects, including the 'Linuxfabrik Monitoring Plugins' project.
|
|
5
5
|
Author-email: "Linuxfabrik GmbH, Zurich, Switzerland" <info@linuxfabrik.ch>
|
|
6
6
|
License: This is free and unencumbered software released into the public domain.
|
|
@@ -15,7 +15,7 @@ import warnings
|
|
|
15
15
|
warnings.filterwarnings('ignore', category=UserWarning, module='pymysql')
|
|
16
16
|
|
|
17
17
|
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
|
|
18
|
-
__version__ = '
|
|
18
|
+
__version__ = '2026051803'
|
|
19
19
|
|
|
20
20
|
import re
|
|
21
21
|
import sys
|
|
@@ -416,6 +416,25 @@ def get_engines(conn):
|
|
|
416
416
|
return engines
|
|
417
417
|
|
|
418
418
|
|
|
419
|
+
def get_flavor():
|
|
420
|
+
"""
|
|
421
|
+
Return the installed MySQL/MariaDB flavor.
|
|
422
|
+
|
|
423
|
+
Thin wrapper around `get_server_info()` for callers that only care
|
|
424
|
+
about the flavor.
|
|
425
|
+
|
|
426
|
+
### Returns
|
|
427
|
+
- **str | None**: `'mariadb'`, `'mysql'`, or `None` when no binary
|
|
428
|
+
responds.
|
|
429
|
+
|
|
430
|
+
### Example
|
|
431
|
+
>>> get_flavor()
|
|
432
|
+
'mariadb'
|
|
433
|
+
"""
|
|
434
|
+
info = get_server_info()
|
|
435
|
+
return info['flavor'] if info else None
|
|
436
|
+
|
|
437
|
+
|
|
419
438
|
def get_replica_status(conn):
|
|
420
439
|
"""
|
|
421
440
|
Return the first row of `SHOW REPLICA STATUS` (or the legacy
|
|
@@ -442,6 +461,102 @@ def get_replica_status(conn):
|
|
|
442
461
|
return rows[0]
|
|
443
462
|
|
|
444
463
|
|
|
464
|
+
# Output formats handled by the regex parser:
|
|
465
|
+
#
|
|
466
|
+
# mysqld Ver 8.0.45 for Linux on x86_64 (Source distribution)
|
|
467
|
+
# mysqld Ver 10.11.15-MariaDB for Linux on x86_64 (MariaDB Server)
|
|
468
|
+
# mysql Ver 14.14 Distrib 5.7.44, for Linux (x86_64) using EditLine wrapper
|
|
469
|
+
# mariadb Ver 15.1 Distrib 10.5.x-MariaDB, for Linux on x86_64
|
|
470
|
+
# mariadb from 11.4.10-MariaDB, client 15.2 for debian-linux-gnu (x86_64) using EditLine wrapper
|
|
471
|
+
#
|
|
472
|
+
# MariaDB 11.4 dropped the `mysqld` symlink and renamed the client
|
|
473
|
+
# version banner from "Distrib X.Y.Z" to "from X.Y.Z", so the parser
|
|
474
|
+
# probes both server and client binaries and accepts both prefixes.
|
|
475
|
+
_VERSION_REGEXES = (
|
|
476
|
+
# `mysqld Ver X.Y.Z[-MariaDB] for ...` (any distro suffix like
|
|
477
|
+
# `-1~trusty` is stripped further down)
|
|
478
|
+
r'Ver (\d+\.\d+\.\d+(?:-MariaDB)?)',
|
|
479
|
+
# `mysql Ver 14.14 Distrib X.Y.Z[-MariaDB], for ...`
|
|
480
|
+
# `mariadb Ver 15.1 Distrib 10.5.x-MariaDB, for ...`
|
|
481
|
+
r'Distrib (\S+?),',
|
|
482
|
+
# `mariadb from X.Y.Z[-MariaDB], client ...` (MariaDB 11.4+)
|
|
483
|
+
r'from (\d+\.\d+\.\d+(?:-MariaDB)?),',
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _parse_version_banner(banner):
|
|
488
|
+
"""Extract `(flavor, version)` from a `mysqld`/`mariadbd`/`mariadb`/
|
|
489
|
+
`mysql` --version banner. Returns `(None, None)` if no regex matches.
|
|
490
|
+
"""
|
|
491
|
+
for regex in _VERSION_REGEXES:
|
|
492
|
+
m = re.search(regex, banner)
|
|
493
|
+
if not m:
|
|
494
|
+
continue
|
|
495
|
+
raw = m.group(1).strip()
|
|
496
|
+
flavor = 'mariadb' if '-MariaDB' in raw else 'mysql'
|
|
497
|
+
version = raw.replace('-MariaDB', '')
|
|
498
|
+
return flavor, version
|
|
499
|
+
return None, None
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def get_server_info(banner=None):
|
|
503
|
+
"""
|
|
504
|
+
Determine the installed MySQL/MariaDB flavor and version. Does not
|
|
505
|
+
require a database connection.
|
|
506
|
+
|
|
507
|
+
Returns a dict like `{'flavor': 'mariadb', 'version': '10.11.16'}`,
|
|
508
|
+
or `None` when nothing matches.
|
|
509
|
+
|
|
510
|
+
If `banner` is `None`, probe `mysqld`, `mariadbd`, `mariadb`, `mysql`
|
|
511
|
+
in order and parse the first responding --version banner. Server
|
|
512
|
+
binaries are tried first; the client fallback exists because MariaDB
|
|
513
|
+
11.4 dropped the `mysqld` symlink and renamed the client.
|
|
514
|
+
|
|
515
|
+
Pass a banner string directly (for example a unit-test fixture) to
|
|
516
|
+
skip the shell probe entirely.
|
|
517
|
+
|
|
518
|
+
Useful where the systemd-based distinction is unreliable: on Fedora
|
|
519
|
+
and RHEL `mysql.service` is aliased to `mariadb.service`, so
|
|
520
|
+
`systemctl is-enabled mysql.service` reports `alias` rather than the
|
|
521
|
+
underlying flavor.
|
|
522
|
+
|
|
523
|
+
### Parameters
|
|
524
|
+
- **banner** (`str | None`): Optional pre-collected --version banner
|
|
525
|
+
to parse instead of probing.
|
|
526
|
+
|
|
527
|
+
### Returns
|
|
528
|
+
- **dict | None**: `{'flavor': 'mariadb'|'mysql', 'version': str}`
|
|
529
|
+
or `None`.
|
|
530
|
+
|
|
531
|
+
### Example
|
|
532
|
+
>>> get_server_info()
|
|
533
|
+
{'flavor': 'mariadb', 'version': '10.11.16'}
|
|
534
|
+
"""
|
|
535
|
+
if banner is not None:
|
|
536
|
+
flavor, version = _parse_version_banner(banner)
|
|
537
|
+
if version:
|
|
538
|
+
return {'flavor': flavor, 'version': version}
|
|
539
|
+
return None
|
|
540
|
+
|
|
541
|
+
from . import shell # local import to keep db_mysql usable without shell at module load
|
|
542
|
+
for command in (
|
|
543
|
+
'mysqld --version',
|
|
544
|
+
'mariadbd --version',
|
|
545
|
+
'mariadb --version',
|
|
546
|
+
'mysql --version',
|
|
547
|
+
):
|
|
548
|
+
success, result = shell.shell_exec(command)
|
|
549
|
+
if not success:
|
|
550
|
+
continue
|
|
551
|
+
stdout, _, _ = result
|
|
552
|
+
if not stdout:
|
|
553
|
+
continue
|
|
554
|
+
flavor, version = _parse_version_banner(stdout.strip())
|
|
555
|
+
if version:
|
|
556
|
+
return {'flavor': flavor, 'version': version}
|
|
557
|
+
return None
|
|
558
|
+
|
|
559
|
+
|
|
445
560
|
def has_is_role_column(conn):
|
|
446
561
|
"""
|
|
447
562
|
Return `True` if `mysql.user.IS_ROLE` exists (MariaDB 10.0.5+ roles).
|
|
@@ -28,13 +28,14 @@ This is one typical use case of this library (taken from `disk-io`):
|
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
30
|
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
|
|
31
|
-
__version__ = '
|
|
31
|
+
__version__ = '2026060102'
|
|
32
32
|
|
|
33
33
|
import csv
|
|
34
34
|
import hashlib
|
|
35
35
|
import os
|
|
36
36
|
import re
|
|
37
37
|
import sqlite3
|
|
38
|
+
import stat
|
|
38
39
|
|
|
39
40
|
from . import disk, time, txt
|
|
40
41
|
|
|
@@ -299,6 +300,10 @@ def connect(path='', filename=''):
|
|
|
299
300
|
- Error message string on failure.
|
|
300
301
|
|
|
301
302
|
### Notes
|
|
303
|
+
- On POSIX systems the database is stored in a per-user, `0700`-protected subdirectory of the
|
|
304
|
+
temporary directory (see `get_db_dir()`), not directly in the shared, world-writable `/tmp`.
|
|
305
|
+
This isolates each user's databases and prevents symlink attacks on the predictable paths
|
|
306
|
+
(CWE-377, GHSA-r35r-fpx2-jgr4).
|
|
302
307
|
- The connection uses a `Row` factory, allowing rows to behave like dictionaries.
|
|
303
308
|
- The connection registers a `REGEXP` SQL function for regular expression support.
|
|
304
309
|
- Always check the returned success flag before using the connection.
|
|
@@ -311,16 +316,9 @@ def connect(path='', filename=''):
|
|
|
311
316
|
>>> else:
|
|
312
317
|
>>> print(conn)
|
|
313
318
|
"""
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if not path:
|
|
318
|
-
path = disk.get_tmpdir()
|
|
319
|
-
if not filename:
|
|
320
|
-
filename = 'linuxfabrik-monitoring-plugins-sqlite.db'
|
|
321
|
-
return os.path.join(path, filename)
|
|
322
|
-
|
|
323
|
-
db = get_filename(path, filename)
|
|
319
|
+
success, db = get_db_path(path=path, filename=filename)
|
|
320
|
+
if not success:
|
|
321
|
+
return False, db
|
|
324
322
|
|
|
325
323
|
try:
|
|
326
324
|
conn = sqlite3.connect(db)
|
|
@@ -640,6 +638,114 @@ def get_colnames(col_definition):
|
|
|
640
638
|
return [col.strip().split()[0] for col in col_definition.split(',') if col.strip()]
|
|
641
639
|
|
|
642
640
|
|
|
641
|
+
def get_db_dir(path):
|
|
642
|
+
"""
|
|
643
|
+
Return a per-user subdirectory of `path` that is safe for storing SQLite databases,
|
|
644
|
+
creating it if necessary.
|
|
645
|
+
|
|
646
|
+
SQLite databases are stored at predictable paths under the system temporary directory so the
|
|
647
|
+
data is found again on the next run. On a shared POSIX `/tmp`, that predictable path lets a
|
|
648
|
+
local attacker pre-create a symlink there and redirect writes to an arbitrary file. For a
|
|
649
|
+
process running as root (e.g. via sudo) this turns into an arbitrary-write primitive (CWE-377,
|
|
650
|
+
GHSA-r35r-fpx2-jgr4). To prevent this, all databases are kept inside a directory owned by the
|
|
651
|
+
current user with `0700` permissions, and the directory is rejected if anything about it looks
|
|
652
|
+
tampered with.
|
|
653
|
+
|
|
654
|
+
### Parameters
|
|
655
|
+
- **path** (`str`):
|
|
656
|
+
The base directory (typically the system temporary directory) in which to create the
|
|
657
|
+
per-user subdirectory.
|
|
658
|
+
|
|
659
|
+
### Returns
|
|
660
|
+
- **tuple** (`bool`, `str`):
|
|
661
|
+
- First element (`bool`): `True` on success, `False` on failure.
|
|
662
|
+
- Second element (`str`):
|
|
663
|
+
- The absolute path to the secure subdirectory on success.
|
|
664
|
+
- An error message describing the failure otherwise.
|
|
665
|
+
|
|
666
|
+
### Notes
|
|
667
|
+
- `os.geteuid()` does not exist on Windows, where the temporary directory is already per-user
|
|
668
|
+
rather than a shared, world-writable location. There the base `path` is returned unchanged.
|
|
669
|
+
- The directory is validated with `os.lstat()` so a symlink planted at its path is detected
|
|
670
|
+
instead of being followed.
|
|
671
|
+
|
|
672
|
+
### Example
|
|
673
|
+
>>> get_db_dir('/tmp')
|
|
674
|
+
(True, '/tmp/linuxfabrik-monitoring-plugins-uid1000')
|
|
675
|
+
"""
|
|
676
|
+
# On Windows the temp dir is already per-user; the shared-/tmp hardening below does not apply.
|
|
677
|
+
if not hasattr(os, 'geteuid'):
|
|
678
|
+
return True, path
|
|
679
|
+
|
|
680
|
+
euid = os.geteuid()
|
|
681
|
+
db_dir = os.path.join(path, f'linuxfabrik-monitoring-plugins-uid{euid}')
|
|
682
|
+
|
|
683
|
+
# Reject a pre-existing symlink outright: makedirs(exist_ok=True) would either follow it
|
|
684
|
+
# (when it resolves to a directory) or fail with a confusing "File exists" (when it dangles).
|
|
685
|
+
# Either way it must not be used. os.path.islink() does not follow the link.
|
|
686
|
+
if os.path.islink(db_dir):
|
|
687
|
+
return False, f'DB directory {db_dir} is a symlink, refusing to use it'
|
|
688
|
+
|
|
689
|
+
try:
|
|
690
|
+
# 0o700: only the owner may access the directory. An existing directory is fine and gets
|
|
691
|
+
# validated below; any other error (e.g. an unwritable temp dir) aborts the connection.
|
|
692
|
+
os.makedirs(db_dir, mode=0o700, exist_ok=True)
|
|
693
|
+
except OSError as e:
|
|
694
|
+
return False, f'Creating DB directory {db_dir} failed, Error: {e}'
|
|
695
|
+
|
|
696
|
+
# lstat() does not follow symlinks, so a symlink planted at db_dir is caught here instead of
|
|
697
|
+
# silently redirecting every database to the attacker's target.
|
|
698
|
+
try:
|
|
699
|
+
st = os.lstat(db_dir)
|
|
700
|
+
except OSError as e:
|
|
701
|
+
return False, f'Inspecting DB directory {db_dir} failed, Error: {e}'
|
|
702
|
+
|
|
703
|
+
if not stat.S_ISDIR(st.st_mode):
|
|
704
|
+
return False, f'DB directory {db_dir} is not a directory, refusing to use it'
|
|
705
|
+
if st.st_uid != euid:
|
|
706
|
+
return False, f'DB directory {db_dir} has the wrong owner, refusing to use it'
|
|
707
|
+
if st.st_mode & 0o077:
|
|
708
|
+
return False, f'DB directory {db_dir} is too permissive, refusing to use it'
|
|
709
|
+
|
|
710
|
+
return True, db_dir
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def get_db_path(path='', filename=''):
|
|
714
|
+
"""
|
|
715
|
+
Return the absolute path of the SQLite database `filename`, resolving the same secured
|
|
716
|
+
per-user directory that `connect()` uses.
|
|
717
|
+
|
|
718
|
+
Use this whenever a caller needs the on-disk location of a database it opens through
|
|
719
|
+
`connect()` (for example to seed, migrate or remove the file), so the path is built in exactly
|
|
720
|
+
one place instead of being reconstructed by every caller.
|
|
721
|
+
|
|
722
|
+
### Parameters
|
|
723
|
+
- **path** (`str`, optional):
|
|
724
|
+
Directory to resolve the database in. Defaults to the system temporary directory.
|
|
725
|
+
- **filename** (`str`, optional):
|
|
726
|
+
Name of the database file. Defaults to `'linuxfabrik-monitoring-plugins-sqlite.db'`.
|
|
727
|
+
|
|
728
|
+
### Returns
|
|
729
|
+
- **tuple** (`bool`, `str`):
|
|
730
|
+
- First element (`bool`): `True` on success, `False` on failure.
|
|
731
|
+
- Second element (`str`):
|
|
732
|
+
- The absolute path to the database file on success.
|
|
733
|
+
- An error message describing the failure otherwise.
|
|
734
|
+
|
|
735
|
+
### Example
|
|
736
|
+
>>> get_db_path(filename='example.db')
|
|
737
|
+
(True, '/tmp/linuxfabrik-monitoring-plugins-uid1000/example.db')
|
|
738
|
+
"""
|
|
739
|
+
if not path:
|
|
740
|
+
path = disk.get_tmpdir()
|
|
741
|
+
if not filename:
|
|
742
|
+
filename = 'linuxfabrik-monitoring-plugins-sqlite.db'
|
|
743
|
+
success, db_dir = get_db_dir(path)
|
|
744
|
+
if not success:
|
|
745
|
+
return False, db_dir
|
|
746
|
+
return True, os.path.join(db_dir, filename)
|
|
747
|
+
|
|
748
|
+
|
|
643
749
|
def get_tables(conn):
|
|
644
750
|
"""
|
|
645
751
|
List all user-defined tables in the SQLite database.
|
|
@@ -13,7 +13,7 @@ partitions, grepping a file, etc.
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
|
|
16
|
-
__version__ = '
|
|
16
|
+
__version__ = '2026060101'
|
|
17
17
|
|
|
18
18
|
import csv
|
|
19
19
|
import os
|
|
@@ -226,25 +226,32 @@ def get_real_disks():
|
|
|
226
226
|
|
|
227
227
|
def get_tmpdir():
|
|
228
228
|
"""
|
|
229
|
-
Return the
|
|
229
|
+
Return the absolute path of the directory used for temporary files, without a trailing '/'.
|
|
230
230
|
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
Thin wrapper around `tempfile.gettempdir()`, which picks a usable temporary directory by
|
|
232
|
+
trying to create, write and delete a test file in each candidate and returning the first one
|
|
233
|
+
that works. The candidates are tried in this order:
|
|
233
234
|
|
|
234
|
-
- The
|
|
235
|
-
-
|
|
236
|
-
|
|
237
|
-
- A platform-specific default:
|
|
238
|
-
* On Windows: C:\\TEMP, C:\\TMP, \\TEMP, \\TMP (in that order).
|
|
239
|
-
* On other systems: /tmp, /var/tmp, /usr/tmp (in that order).
|
|
235
|
+
- The directories named by the `TMPDIR`, `TEMP` and `TMP` environment variables.
|
|
236
|
+
- Platform-specific defaults: on Windows `~\\AppData\\Local\\Temp`, `%SYSTEMROOT%\\Temp`,
|
|
237
|
+
`c:\\temp`, `c:\\tmp`, `\\temp`, `\\tmp`; on other systems `/tmp`, `/var/tmp`, `/usr/tmp`.
|
|
240
238
|
- As a last resort, the current working directory.
|
|
241
239
|
|
|
240
|
+
The literal `/tmp` is only returned as a fallback if `tempfile.gettempdir()` itself raises.
|
|
241
|
+
|
|
242
242
|
### Parameters
|
|
243
243
|
- None
|
|
244
244
|
|
|
245
245
|
### Returns
|
|
246
246
|
- **str**: The absolute path to the temporary directory.
|
|
247
247
|
|
|
248
|
+
### Notes
|
|
249
|
+
- `tempfile.gettempdir()` computes the result once and caches it; changing `TMPDIR` and
|
|
250
|
+
friends afterwards has no effect for the rest of the process.
|
|
251
|
+
- The path is made absolute but not symlink-resolved (`os.path.abspath`, not
|
|
252
|
+
`os.path.realpath`), so a caller that needs a trusted location must validate the final path
|
|
253
|
+
itself.
|
|
254
|
+
|
|
248
255
|
### Example
|
|
249
256
|
>>> get_tmpdir()
|
|
250
257
|
'/tmp'
|
|
@@ -495,52 +495,59 @@ ENDOFLIFE_DATE = {
|
|
|
495
495
|
|
|
496
496
|
|
|
497
497
|
'https://endoflife.date/api/gitlab.json': [
|
|
498
|
+
{ 'cycle': '19.0',
|
|
499
|
+
'eol': '2026-08-20',
|
|
500
|
+
'latest': '19.0.1',
|
|
501
|
+
'latestReleaseDate': '2026-05-26',
|
|
502
|
+
'lts': False,
|
|
503
|
+
'releaseDate': '2026-05-21',
|
|
504
|
+
'support': '2026-06-18'},
|
|
498
505
|
{ 'cycle': '18.11',
|
|
499
506
|
'eol': '2026-07-16',
|
|
500
|
-
'latest': '18.11.
|
|
501
|
-
'latestReleaseDate': '2026-05-
|
|
507
|
+
'latest': '18.11.4',
|
|
508
|
+
'latestReleaseDate': '2026-05-26',
|
|
502
509
|
'lts': False,
|
|
503
510
|
'releaseDate': '2026-04-16',
|
|
504
511
|
'support': '2026-05-21'},
|
|
505
512
|
{ 'cycle': '18.10',
|
|
506
513
|
'eol': '2026-06-18',
|
|
507
|
-
'latest': '18.10.
|
|
508
|
-
'latestReleaseDate': '2026-05-
|
|
514
|
+
'latest': '18.10.7',
|
|
515
|
+
'latestReleaseDate': '2026-05-26',
|
|
509
516
|
'lts': False,
|
|
510
517
|
'releaseDate': '2026-03-19',
|
|
511
518
|
'support': '2026-04-16'},
|
|
512
519
|
{ 'cycle': '18.9',
|
|
513
520
|
'eol': '2026-05-21',
|
|
514
|
-
'latest': '18.9.
|
|
515
|
-
'latestReleaseDate': '2026-05-
|
|
521
|
+
'latest': '18.9.8',
|
|
522
|
+
'latestReleaseDate': '2026-05-25',
|
|
516
523
|
'lts': False,
|
|
517
524
|
'releaseDate': '2026-02-19',
|
|
518
525
|
'support': '2026-03-19'},
|
|
519
526
|
{ 'cycle': '18.8',
|
|
520
527
|
'eol': '2026-04-16',
|
|
521
|
-
'latest': '18.8.
|
|
522
|
-
'latestReleaseDate': '2026-
|
|
528
|
+
'latest': '18.8.10',
|
|
529
|
+
'latestReleaseDate': '2026-05-25',
|
|
523
530
|
'lts': False,
|
|
524
531
|
'releaseDate': '2026-01-15',
|
|
525
532
|
'support': '2026-02-19'},
|
|
526
533
|
{ 'cycle': '18.7',
|
|
527
534
|
'eol': '2026-03-19',
|
|
528
|
-
'latest': '18.7.
|
|
529
|
-
'latestReleaseDate': '2026-
|
|
535
|
+
'latest': '18.7.7',
|
|
536
|
+
'latestReleaseDate': '2026-05-25',
|
|
530
537
|
'lts': False,
|
|
531
538
|
'releaseDate': '2025-12-18',
|
|
532
539
|
'support': '2026-01-15'},
|
|
533
540
|
{ 'cycle': '18.6',
|
|
534
541
|
'eol': '2026-02-19',
|
|
535
|
-
'latest': '18.6.
|
|
536
|
-
'latestReleaseDate': '2026-
|
|
542
|
+
'latest': '18.6.8',
|
|
543
|
+
'latestReleaseDate': '2026-05-26',
|
|
537
544
|
'lts': False,
|
|
538
545
|
'releaseDate': '2025-11-20',
|
|
539
546
|
'support': '2025-12-18'},
|
|
540
547
|
{ 'cycle': '18.5',
|
|
541
548
|
'eol': '2026-01-15',
|
|
542
|
-
'latest': '18.5.
|
|
543
|
-
'latestReleaseDate': '2026-
|
|
549
|
+
'latest': '18.5.7',
|
|
550
|
+
'latestReleaseDate': '2026-05-26',
|
|
544
551
|
'lts': False,
|
|
545
552
|
'releaseDate': '2025-10-16',
|
|
546
553
|
'support': '2025-11-20'},
|
|
@@ -1126,16 +1133,22 @@ ENDOFLIFE_DATE = {
|
|
|
1126
1133
|
|
|
1127
1134
|
|
|
1128
1135
|
'https://endoflife.date/api/graylog.json': [
|
|
1136
|
+
{ 'cycle': '7.1',
|
|
1137
|
+
'eol': False,
|
|
1138
|
+
'latest': '7.1.2',
|
|
1139
|
+
'latestReleaseDate': '2026-05-20',
|
|
1140
|
+
'lts': False,
|
|
1141
|
+
'releaseDate': '2026-05-04'},
|
|
1129
1142
|
{ 'cycle': '7.0',
|
|
1130
1143
|
'eol': '2026-11-03',
|
|
1131
|
-
'latest': '7.0.
|
|
1132
|
-
'latestReleaseDate': '2026-
|
|
1144
|
+
'latest': '7.0.7',
|
|
1145
|
+
'latestReleaseDate': '2026-05-20',
|
|
1133
1146
|
'lts': False,
|
|
1134
1147
|
'releaseDate': '2025-11-03'},
|
|
1135
1148
|
{ 'cycle': '6.3',
|
|
1136
1149
|
'eol': '2026-06-30',
|
|
1137
|
-
'latest': '6.3.
|
|
1138
|
-
'latestReleaseDate': '2026-
|
|
1150
|
+
'latest': '6.3.12',
|
|
1151
|
+
'latestReleaseDate': '2026-05-20',
|
|
1139
1152
|
'lts': False,
|
|
1140
1153
|
'releaseDate': '2025-06-30'},
|
|
1141
1154
|
{ 'cycle': '6.2',
|
|
@@ -1301,8 +1314,8 @@ ENDOFLIFE_DATE = {
|
|
|
1301
1314
|
'https://endoflife.date/api/icinga.json': [
|
|
1302
1315
|
{ 'cycle': '2.16',
|
|
1303
1316
|
'eol': False,
|
|
1304
|
-
'latest': '2.16.
|
|
1305
|
-
'latestReleaseDate': '2026-
|
|
1317
|
+
'latest': '2.16.1',
|
|
1318
|
+
'latestReleaseDate': '2026-05-21',
|
|
1306
1319
|
'lts': False,
|
|
1307
1320
|
'releaseDate': '2026-04-23',
|
|
1308
1321
|
'support': True},
|
|
@@ -1432,8 +1445,8 @@ ENDOFLIFE_DATE = {
|
|
|
1432
1445
|
'https://endoflife.date/api/keycloak.json': [
|
|
1433
1446
|
{ 'cycle': '26.6',
|
|
1434
1447
|
'eol': False,
|
|
1435
|
-
'latest': '26.6.
|
|
1436
|
-
'latestReleaseDate': '2026-
|
|
1448
|
+
'latest': '26.6.2',
|
|
1449
|
+
'latestReleaseDate': '2026-05-19',
|
|
1437
1450
|
'lts': False,
|
|
1438
1451
|
'releaseDate': '2026-04-08'},
|
|
1439
1452
|
{ 'cycle': '26.5',
|
|
@@ -1614,8 +1627,8 @@ ENDOFLIFE_DATE = {
|
|
|
1614
1627
|
{ 'cycle': '11.8',
|
|
1615
1628
|
'eol': '2028-06-04',
|
|
1616
1629
|
'extendedSupport': '2033-10-22',
|
|
1617
|
-
'latest': '11.8.
|
|
1618
|
-
'latestReleaseDate': '2026-05-
|
|
1630
|
+
'latest': '11.8.8',
|
|
1631
|
+
'latestReleaseDate': '2026-05-27',
|
|
1619
1632
|
'lts': True,
|
|
1620
1633
|
'releaseDate': '2025-06-04'},
|
|
1621
1634
|
{ 'cycle': '11.7',
|
|
@@ -1645,8 +1658,8 @@ ENDOFLIFE_DATE = {
|
|
|
1645
1658
|
{ 'cycle': '11.4',
|
|
1646
1659
|
'eol': '2029-05-29',
|
|
1647
1660
|
'extendedSupport': '2033-01-16',
|
|
1648
|
-
'latest': '11.4.
|
|
1649
|
-
'latestReleaseDate': '2026-05-
|
|
1661
|
+
'latest': '11.4.12',
|
|
1662
|
+
'latestReleaseDate': '2026-05-27',
|
|
1650
1663
|
'lts': True,
|
|
1651
1664
|
'releaseDate': '2024-05-29'},
|
|
1652
1665
|
{ 'cycle': '11.3',
|
|
@@ -1684,8 +1697,8 @@ ENDOFLIFE_DATE = {
|
|
|
1684
1697
|
{ 'cycle': '10.11',
|
|
1685
1698
|
'eol': '2028-02-16',
|
|
1686
1699
|
'extendedSupport': '2028-02-16',
|
|
1687
|
-
'latest': '10.11.
|
|
1688
|
-
'latestReleaseDate': '2026-05-
|
|
1700
|
+
'latest': '10.11.18',
|
|
1701
|
+
'latestReleaseDate': '2026-05-27',
|
|
1689
1702
|
'lts': True,
|
|
1690
1703
|
'releaseDate': '2023-02-16'},
|
|
1691
1704
|
{ 'cycle': '10.10',
|
|
@@ -1723,8 +1736,8 @@ ENDOFLIFE_DATE = {
|
|
|
1723
1736
|
{ 'cycle': '10.6',
|
|
1724
1737
|
'eol': '2026-07-06',
|
|
1725
1738
|
'extendedSupport': '2029-08-23',
|
|
1726
|
-
'latest': '10.6.
|
|
1727
|
-
'latestReleaseDate': '2026-05-
|
|
1739
|
+
'latest': '10.6.27',
|
|
1740
|
+
'latestReleaseDate': '2026-05-27',
|
|
1728
1741
|
'lts': True,
|
|
1729
1742
|
'releaseDate': '2021-07-06'},
|
|
1730
1743
|
{ 'cycle': '10.5',
|
|
@@ -1813,20 +1826,20 @@ ENDOFLIFE_DATE = {
|
|
|
1813
1826
|
'https://endoflife.date/api/mastodon.json': [
|
|
1814
1827
|
{ 'cycle': '4.5',
|
|
1815
1828
|
'eol': False,
|
|
1816
|
-
'latest': '4.5.
|
|
1817
|
-
'latestReleaseDate': '2026-
|
|
1829
|
+
'latest': '4.5.10',
|
|
1830
|
+
'latestReleaseDate': '2026-05-20',
|
|
1818
1831
|
'lts': False,
|
|
1819
1832
|
'releaseDate': '2025-11-06'},
|
|
1820
1833
|
{ 'cycle': '4.4',
|
|
1821
1834
|
'eol': False,
|
|
1822
|
-
'latest': '4.4.
|
|
1823
|
-
'latestReleaseDate': '2026-
|
|
1835
|
+
'latest': '4.4.17',
|
|
1836
|
+
'latestReleaseDate': '2026-05-20',
|
|
1824
1837
|
'lts': False,
|
|
1825
1838
|
'releaseDate': '2025-07-08'},
|
|
1826
1839
|
{ 'cycle': '4.3',
|
|
1827
1840
|
'eol': '2026-05-06',
|
|
1828
|
-
'latest': '4.3.
|
|
1829
|
-
'latestReleaseDate': '2026-
|
|
1841
|
+
'latest': '4.3.23',
|
|
1842
|
+
'latestReleaseDate': '2026-05-20',
|
|
1830
1843
|
'lts': False,
|
|
1831
1844
|
'releaseDate': '2024-10-08'},
|
|
1832
1845
|
{ 'cycle': '4.2',
|
|
@@ -1901,8 +1914,8 @@ ENDOFLIFE_DATE = {
|
|
|
1901
1914
|
'https://endoflife.date/api/matomo.json': [
|
|
1902
1915
|
{ 'cycle': '5',
|
|
1903
1916
|
'eol': False,
|
|
1904
|
-
'latest': '5.10.
|
|
1905
|
-
'latestReleaseDate': '2026-05-
|
|
1917
|
+
'latest': '5.10.1',
|
|
1918
|
+
'latestReleaseDate': '2026-05-29',
|
|
1906
1919
|
'lts': False,
|
|
1907
1920
|
'releaseDate': '2023-12-18',
|
|
1908
1921
|
'support': True},
|
|
@@ -2267,14 +2280,14 @@ ENDOFLIFE_DATE = {
|
|
|
2267
2280
|
'https://endoflife.date/api/nextcloud.json': [
|
|
2268
2281
|
{ 'cycle': '33',
|
|
2269
2282
|
'eol': '2027-02-28',
|
|
2270
|
-
'latest': '33.0.
|
|
2271
|
-
'latestReleaseDate': '2026-
|
|
2283
|
+
'latest': '33.0.4',
|
|
2284
|
+
'latestReleaseDate': '2026-05-28',
|
|
2272
2285
|
'lts': False,
|
|
2273
2286
|
'releaseDate': '2026-02-18'},
|
|
2274
2287
|
{ 'cycle': '32',
|
|
2275
2288
|
'eol': '2026-09-30',
|
|
2276
|
-
'latest': '32.0.
|
|
2277
|
-
'latestReleaseDate': '2026-
|
|
2289
|
+
'latest': '32.0.10',
|
|
2290
|
+
'latestReleaseDate': '2026-05-28',
|
|
2278
2291
|
'lts': False,
|
|
2279
2292
|
'releaseDate': '2025-09-27'},
|
|
2280
2293
|
{ 'cycle': '31',
|
|
@@ -2604,29 +2617,29 @@ ENDOFLIFE_DATE = {
|
|
|
2604
2617
|
'https://endoflife.date/api/postfix.json': [
|
|
2605
2618
|
{ 'cycle': '3.11',
|
|
2606
2619
|
'eol': False,
|
|
2607
|
-
'latest': '3.11.
|
|
2608
|
-
'latestReleaseDate': '2026-05-
|
|
2620
|
+
'latest': '3.11.3',
|
|
2621
|
+
'latestReleaseDate': '2026-05-18',
|
|
2609
2622
|
'link': 'https://www.postfix.org/announcements/postfix-3.11.0.html',
|
|
2610
2623
|
'lts': False,
|
|
2611
2624
|
'releaseDate': '2026-03-06'},
|
|
2612
2625
|
{ 'cycle': '3.10',
|
|
2613
2626
|
'eol': False,
|
|
2614
|
-
'latest': '3.10.
|
|
2615
|
-
'latestReleaseDate': '2026-05-
|
|
2627
|
+
'latest': '3.10.10',
|
|
2628
|
+
'latestReleaseDate': '2026-05-18',
|
|
2616
2629
|
'link': 'https://www.postfix.org/announcements/postfix-3.10.0.html',
|
|
2617
2630
|
'lts': False,
|
|
2618
2631
|
'releaseDate': '2025-02-16'},
|
|
2619
2632
|
{ 'cycle': '3.9',
|
|
2620
2633
|
'eol': False,
|
|
2621
|
-
'latest': '3.9.
|
|
2622
|
-
'latestReleaseDate': '2026-05-
|
|
2634
|
+
'latest': '3.9.11',
|
|
2635
|
+
'latestReleaseDate': '2026-05-18',
|
|
2623
2636
|
'link': 'https://www.postfix.org/announcements/postfix-3.9.2.html',
|
|
2624
2637
|
'lts': False,
|
|
2625
2638
|
'releaseDate': '2024-03-06'},
|
|
2626
2639
|
{ 'cycle': '3.8',
|
|
2627
2640
|
'eol': False,
|
|
2628
|
-
'latest': '3.8.
|
|
2629
|
-
'latestReleaseDate': '2026-05-
|
|
2641
|
+
'latest': '3.8.17',
|
|
2642
|
+
'latestReleaseDate': '2026-05-18',
|
|
2630
2643
|
'link': 'https://www.postfix.org/announcements/postfix-3.9.2.html',
|
|
2631
2644
|
'lts': False,
|
|
2632
2645
|
'releaseDate': '2023-04-17'},
|
|
@@ -3101,13 +3114,20 @@ ENDOFLIFE_DATE = {
|
|
|
3101
3114
|
|
|
3102
3115
|
|
|
3103
3116
|
'https://endoflife.date/api/redis.json': [
|
|
3117
|
+
{ 'cycle': '8.8',
|
|
3118
|
+
'eol': False,
|
|
3119
|
+
'latest': '8.8.0',
|
|
3120
|
+
'latestReleaseDate': '2026-05-25',
|
|
3121
|
+
'lts': False,
|
|
3122
|
+
'releaseDate': '2026-05-25',
|
|
3123
|
+
'support': True},
|
|
3104
3124
|
{ 'cycle': '8.6',
|
|
3105
3125
|
'eol': False,
|
|
3106
3126
|
'latest': '8.6.3',
|
|
3107
3127
|
'latestReleaseDate': '2026-05-05',
|
|
3108
3128
|
'lts': False,
|
|
3109
3129
|
'releaseDate': '2026-02-11',
|
|
3110
|
-
'support':
|
|
3130
|
+
'support': '2026-05-25'},
|
|
3111
3131
|
{ 'cycle': '8.4',
|
|
3112
3132
|
'eol': False,
|
|
3113
3133
|
'latest': '8.4.3',
|
|
@@ -3116,7 +3136,7 @@ ENDOFLIFE_DATE = {
|
|
|
3116
3136
|
'releaseDate': '2025-11-18',
|
|
3117
3137
|
'support': '2026-02-11'},
|
|
3118
3138
|
{ 'cycle': '8.2',
|
|
3119
|
-
'eol':
|
|
3139
|
+
'eol': '2026-05-25',
|
|
3120
3140
|
'latest': '8.2.6',
|
|
3121
3141
|
'latestReleaseDate': '2026-05-05',
|
|
3122
3142
|
'lts': False,
|
|
@@ -3178,16 +3198,16 @@ ENDOFLIFE_DATE = {
|
|
|
3178
3198
|
{ 'cycle': '10',
|
|
3179
3199
|
'eol': '2035-05-31',
|
|
3180
3200
|
'extendedSupport': '2038-05-31',
|
|
3181
|
-
'latest': '10.
|
|
3182
|
-
'latestReleaseDate': '
|
|
3201
|
+
'latest': '10.2',
|
|
3202
|
+
'latestReleaseDate': '2026-05-20',
|
|
3183
3203
|
'lts': '2035-05-31',
|
|
3184
3204
|
'releaseDate': '2025-05-20',
|
|
3185
3205
|
'support': '2030-05-31'},
|
|
3186
3206
|
{ 'cycle': '9',
|
|
3187
3207
|
'eol': '2032-05-31',
|
|
3188
3208
|
'extendedSupport': '2035-05-31',
|
|
3189
|
-
'latest': '9.
|
|
3190
|
-
'latestReleaseDate': '
|
|
3209
|
+
'latest': '9.8',
|
|
3210
|
+
'latestReleaseDate': '2026-05-20',
|
|
3191
3211
|
'lts': '2032-05-31',
|
|
3192
3212
|
'releaseDate': '2022-05-18',
|
|
3193
3213
|
'support': '2027-05-31'},
|
|
@@ -3237,43 +3257,43 @@ ENDOFLIFE_DATE = {
|
|
|
3237
3257
|
'https://endoflife.date/api/rocketchat.json': [
|
|
3238
3258
|
{ 'cycle': '8.4',
|
|
3239
3259
|
'eol': '2026-10-31',
|
|
3240
|
-
'latest': '8.4.
|
|
3241
|
-
'latestReleaseDate': '2026-05-
|
|
3260
|
+
'latest': '8.4.2',
|
|
3261
|
+
'latestReleaseDate': '2026-05-22',
|
|
3242
3262
|
'lts': False,
|
|
3243
3263
|
'releaseDate': '2026-04-30',
|
|
3244
3264
|
'support': '2026-04-30'},
|
|
3245
3265
|
{ 'cycle': '8.3',
|
|
3246
3266
|
'eol': '2026-10-31',
|
|
3247
|
-
'latest': '8.3.
|
|
3248
|
-
'latestReleaseDate': '2026-05-
|
|
3267
|
+
'latest': '8.3.4',
|
|
3268
|
+
'latestReleaseDate': '2026-05-22',
|
|
3249
3269
|
'lts': False,
|
|
3250
3270
|
'releaseDate': '2026-04-07',
|
|
3251
3271
|
'support': '2026-04-07'},
|
|
3252
3272
|
{ 'cycle': '8.2',
|
|
3253
3273
|
'eol': '2026-09-30',
|
|
3254
|
-
'latest': '8.2.
|
|
3255
|
-
'latestReleaseDate': '2026-05-
|
|
3274
|
+
'latest': '8.2.4',
|
|
3275
|
+
'latestReleaseDate': '2026-05-22',
|
|
3256
3276
|
'lts': False,
|
|
3257
3277
|
'releaseDate': '2026-03-02',
|
|
3258
3278
|
'support': '2026-03-02'},
|
|
3259
3279
|
{ 'cycle': '8.1',
|
|
3260
3280
|
'eol': '2026-08-31',
|
|
3261
|
-
'latest': '8.1.
|
|
3262
|
-
'latestReleaseDate': '2026-05-
|
|
3281
|
+
'latest': '8.1.5',
|
|
3282
|
+
'latestReleaseDate': '2026-05-22',
|
|
3263
3283
|
'lts': False,
|
|
3264
3284
|
'releaseDate': '2026-02-10',
|
|
3265
3285
|
'support': '2026-02-10'},
|
|
3266
3286
|
{ 'cycle': '8.0',
|
|
3267
3287
|
'eol': '2026-06-30',
|
|
3268
|
-
'latest': '8.0.
|
|
3269
|
-
'latestReleaseDate': '2026-05-
|
|
3288
|
+
'latest': '8.0.6',
|
|
3289
|
+
'latestReleaseDate': '2026-05-22',
|
|
3270
3290
|
'lts': False,
|
|
3271
3291
|
'releaseDate': '2026-01-12',
|
|
3272
3292
|
'support': '2026-01-12'},
|
|
3273
3293
|
{ 'cycle': '7.13',
|
|
3274
3294
|
'eol': '2026-05-31',
|
|
3275
|
-
'latest': '7.13.
|
|
3276
|
-
'latestReleaseDate': '2026-05-
|
|
3295
|
+
'latest': '7.13.8',
|
|
3296
|
+
'latestReleaseDate': '2026-05-22',
|
|
3277
3297
|
'lts': False,
|
|
3278
3298
|
'releaseDate': '2025-12-05',
|
|
3279
3299
|
'support': '2025-12-05'},
|
|
@@ -3293,8 +3313,8 @@ ENDOFLIFE_DATE = {
|
|
|
3293
3313
|
'support': '2025-10-17'},
|
|
3294
3314
|
{ 'cycle': '7.10',
|
|
3295
3315
|
'eol': '2026-06-30',
|
|
3296
|
-
'latest': '7.10.
|
|
3297
|
-
'latestReleaseDate': '2026-05-
|
|
3316
|
+
'latest': '7.10.12',
|
|
3317
|
+
'latestReleaseDate': '2026-05-25',
|
|
3298
3318
|
'lts': True,
|
|
3299
3319
|
'releaseDate': '2025-09-04',
|
|
3300
3320
|
'support': '2025-09-04'},
|
|
@@ -3824,6 +3844,13 @@ ENDOFLIFE_DATE = {
|
|
|
3824
3844
|
|
|
3825
3845
|
|
|
3826
3846
|
'https://endoflife.date/api/valkey.json': [
|
|
3847
|
+
{ 'cycle': '9.1',
|
|
3848
|
+
'eol': False,
|
|
3849
|
+
'latest': '9.1.0',
|
|
3850
|
+
'latestReleaseDate': '2026-05-19',
|
|
3851
|
+
'lts': False,
|
|
3852
|
+
'releaseDate': '2026-05-19',
|
|
3853
|
+
'support': True},
|
|
3827
3854
|
{ 'cycle': '9.0',
|
|
3828
3855
|
'eol': '2028-10-21',
|
|
3829
3856
|
'latest': '9.0.4',
|
|
@@ -3856,8 +3883,15 @@ ENDOFLIFE_DATE = {
|
|
|
3856
3883
|
|
|
3857
3884
|
|
|
3858
3885
|
'https://endoflife.date/api/wordpress.json': [
|
|
3859
|
-
{ 'cycle': '
|
|
3886
|
+
{ 'cycle': '7.0',
|
|
3860
3887
|
'eol': False,
|
|
3888
|
+
'latest': '7.0.0',
|
|
3889
|
+
'latestReleaseDate': '2026-05-20',
|
|
3890
|
+
'lts': False,
|
|
3891
|
+
'releaseDate': '2026-05-20',
|
|
3892
|
+
'supportedPHPVersions': '7.4 - 8.5'},
|
|
3893
|
+
{ 'cycle': '6.9',
|
|
3894
|
+
'eol': '2026-05-20',
|
|
3861
3895
|
'latest': '6.9.4',
|
|
3862
3896
|
'latestReleaseDate': '2026-03-11',
|
|
3863
3897
|
'lts': False,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: linuxfabrik-lib
|
|
3
|
-
Version: 4.0
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: Python libraries used in various Linuxfabrik projects, including the 'Linuxfabrik Monitoring Plugins' project.
|
|
5
5
|
Author-email: "Linuxfabrik GmbH, Zurich, Switzerland" <info@linuxfabrik.ch>
|
|
6
6
|
License: This is free and unencumbered software released into the public domain.
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "linuxfabrik-lib"
|
|
9
|
-
version = "4.0
|
|
9
|
+
version = "4.2.0"
|
|
10
10
|
description = "Python libraries used in various Linuxfabrik projects, including the 'Linuxfabrik Monitoring Plugins' project."
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = [
|
|
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
|
{linuxfabrik_lib-4.0.2 → linuxfabrik_lib-4.2.0}/linuxfabrik_lib.egg-info/dependency_links.txt
RENAMED
|
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
|