From d73486627279bef654beed103e2e55d0abe84bf9 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Tue, 7 May 2024 16:41:31 +0200 Subject: [PATCH 1/7] Remove try-except imports needed for Python <3.9 --- python/nav/buildconf.py | 11 ++++------- python/nav/eventengine/__init__.py | 5 +---- python/nav/eventengine/export.py | 5 +---- python/nav/statemon/db.py | 10 +++------- python/nav/util.py | 6 +----- python/nav/web/sortedstats/views.py | 6 +----- tests/integration/pping_test.py | 8 ++------ tests/integration/smsd_test.py | 8 ++------ tests/integration/web/crawler_test.py | 7 ++----- tests/unittests/general/config_test.py | 6 +----- 10 files changed, 18 insertions(+), 54 deletions(-) diff --git a/python/nav/buildconf.py b/python/nav/buildconf.py index c39aed4088..c3a1b114bc 100644 --- a/python/nav/buildconf.py +++ b/python/nav/buildconf.py @@ -1,13 +1,10 @@ """NAV build configuration variables.""" + # pylint: disable=invalid-name +from importlib import metadata import os import sysconfig -try: - from importlib import metadata as _impmeta -except ImportError: - import importlib_metadata as _impmeta - datadir = os.path.join(sysconfig.get_config_var('datarootdir'), 'nav') localstatedir = os.path.join(datadir, 'var') @@ -17,8 +14,8 @@ try: - VERSION = _impmeta.version("nav") -except _impmeta.PackageNotFoundError: + VERSION = metadata.version("nav") +except metadata.PackageNotFoundError: # If we're not installed, try to get the current version from Git tags import setuptools_scm diff --git a/python/nav/eventengine/__init__.py b/python/nav/eventengine/__init__.py index 801837cb27..c2698011bf 100644 --- a/python/nav/eventengine/__init__.py +++ b/python/nav/eventengine/__init__.py @@ -15,10 +15,7 @@ # """NAV eventengine""" -try: - from subprocess32 import STDOUT, check_output, TimeoutExpired, CalledProcessError -except ImportError: - from subprocess import STDOUT, check_output, TimeoutExpired, CalledProcessError +from subprocess import STDOUT, check_output, TimeoutExpired, CalledProcessError def get_eventengine_output(timeout=10): diff --git a/python/nav/eventengine/export.py b/python/nav/eventengine/export.py index 0379d67a81..f74391faea 100644 --- a/python/nav/eventengine/export.py +++ b/python/nav/eventengine/export.py @@ -17,13 +17,10 @@ """Alert stream export functionality""" import logging import json +import subprocess from django.core.serializers.json import DjangoJSONEncoder -try: - import subprocess32 as subprocess -except ImportError: - import subprocess from nav.web.api.v1.alert_serializers import AlertQueueSerializer diff --git a/python/nav/statemon/db.py b/python/nav/statemon/db.py index 32869eb9c7..0515145187 100644 --- a/python/nav/statemon/db.py +++ b/python/nav/statemon/db.py @@ -23,16 +23,12 @@ """ from __future__ import absolute_import -import threading - -try: - import queue -except ImportError: - import Queue as queue -import time import atexit from collections import defaultdict import logging +import queue +import time +import threading import psycopg2 from psycopg2.errorcodes import IN_FAILED_SQL_TRANSACTION diff --git a/python/nav/util.py b/python/nav/util.py index edb8d9c93f..71fe0e3caa 100644 --- a/python/nav/util.py +++ b/python/nav/util.py @@ -24,17 +24,13 @@ import uuid import hashlib from functools import wraps +from importlib.resources import as_file, files as resource_files from itertools import chain, tee, groupby, islice from operator import itemgetter from secrets import token_hex import IPy -try: - from importlib.resources import as_file, files as resource_files -except ImportError: # Python 3.7! - from importlib_resources import as_file, files as resource_files - def gradient(start, stop, steps): """Create and return a sequence of steps representing an integer diff --git a/python/nav/web/sortedstats/views.py b/python/nav/web/sortedstats/views.py index 02832e492c..7edbfa4fb9 100644 --- a/python/nav/web/sortedstats/views.py +++ b/python/nav/web/sortedstats/views.py @@ -17,11 +17,7 @@ import logging from datetime import datetime - -try: - from zoneinfo import ZoneInfo -except ImportError: - from backports.zoneinfo import ZoneInfo +from zoneinfo import ZoneInfo from django.shortcuts import render from django.core.cache import caches diff --git a/tests/integration/pping_test.py b/tests/integration/pping_test.py index 8068b6c008..20e52aef9b 100644 --- a/tests/integration/pping_test.py +++ b/tests/integration/pping_test.py @@ -1,15 +1,11 @@ """ various pping integration tests """ + import os -from pathlib import Path import getpass from shutil import which - -try: - from subprocess32 import STDOUT, check_output, TimeoutExpired, CalledProcessError -except ImportError: - from subprocess import STDOUT, check_output, TimeoutExpired, CalledProcessError +from subprocess import STDOUT, check_output, CalledProcessError import pytest diff --git a/tests/integration/smsd_test.py b/tests/integration/smsd_test.py index cc09a9f8fb..710dc09dd4 100644 --- a/tests/integration/smsd_test.py +++ b/tests/integration/smsd_test.py @@ -1,16 +1,12 @@ """ smsd integration tests """ + import os import os.path - -try: - from subprocess32 import STDOUT, check_output, TimeoutExpired, CalledProcessError -except ImportError: - from subprocess import STDOUT, check_output, TimeoutExpired, CalledProcessError +from subprocess import STDOUT, check_output, TimeoutExpired, CalledProcessError import pytest -from mock import Mock, patch from nav.config import find_config_file, find_config_dir diff --git a/tests/integration/web/crawler_test.py b/tests/integration/web/crawler_test.py index 5ed896c276..9b23d6dde4 100644 --- a/tests/integration/web/crawler_test.py +++ b/tests/integration/web/crawler_test.py @@ -13,17 +13,14 @@ URLs that report a Content-Type of text/html. """ + from __future__ import print_function from collections import namedtuple +from http.client import BadStatusLine from lxml.html import fromstring import os -try: - from http.client import BadStatusLine -except ImportError: - from httplib import BadStatusLine - import pytest from tidylib import tidy_document diff --git a/tests/unittests/general/config_test.py b/tests/unittests/general/config_test.py index 33e9a4c1f8..66c301184b 100644 --- a/tests/unittests/general/config_test.py +++ b/tests/unittests/general/config_test.py @@ -14,16 +14,12 @@ # from __future__ import unicode_literals +from io import StringIO from os import makedirs, remove, rmdir, listdir from os.path import join import pytest -try: - from io import StringIO -except ImportError: - from StringIO import StringIO - from nav import config From 51815c8c3830c4e316b53e0b1584bf5075f6c224 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Tue, 7 May 2024 16:43:02 +0200 Subject: [PATCH 2/7] Remove superfluous comment since upgrading from Python 3.5 --- python/nav/logs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/nav/logs.py b/python/nav/logs.py index 95d0ecec50..6e831b495b 100644 --- a/python/nav/logs.py +++ b/python/nav/logs.py @@ -125,7 +125,6 @@ def _get_logging_conf(): """ filename = os.environ.get(LOGGING_CONF_VAR, LOGGING_CONF_FILE_DEFAULT) config = configparser.ConfigParser() - # Warning about `bytes` on py 3.5, fixed in py 3.7. Do not change read = config.read(filename) if filename not in read and LOGGING_CONF_VAR in os.environ: _logger.error( From a7ab6359630305c63dcfcc22d871dae6103c7947 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Tue, 7 May 2024 16:44:17 +0200 Subject: [PATCH 3/7] Add elements to tests possible since dropping Python 2 --- tests/integration/auditlog_test.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/tests/integration/auditlog_test.py b/tests/integration/auditlog_test.py index c0159fe2ea..99770b99f6 100644 --- a/tests/integration/auditlog_test.py +++ b/tests/integration/auditlog_test.py @@ -19,19 +19,16 @@ def test_str(self): l.delete() def test_add_log_entry_bad_template(self): - LogEntry.add_log_entry( - self.justification, u'bad template test', u'this is a {bad} template' - ) - l = LogEntry.objects.filter(verb='bad template test').get() - self.assertEqual(l.summary, u'Error creating summary - see error log') - l.delete() - - # # When on python3: - # with self.assertLogs(level='ERROR') as log: - # # run body - # self.assertEqual(len(log.output), 1) - # self.assertEqual(len(log.records), 1) - # self.assertIn('KeyError when creating summary:', log.output[0]) + with self.assertLogs(level='ERROR') as log: + LogEntry.add_log_entry( + self.justification, u'bad template test', u'this is a {bad} template' + ) + l = LogEntry.objects.filter(verb='bad template test').get() + self.assertEqual(l.summary, u'Error creating summary - see error log') + l.delete() + self.assertEqual(len(log.output), 1) + self.assertEqual(len(log.records), 1) + self.assertIn('KeyError when creating summary:', log.output[0]) def test_add_log_entry_actor_only(self): LogEntry.add_log_entry( From b954936d7fdb867efefbb7b0e82f0aff383442e9 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Wed, 8 May 2024 09:30:06 +0200 Subject: [PATCH 4/7] Add changelog entry --- changelog.d/+drop-py37-code-changes.changed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/+drop-py37-code-changes.changed.md diff --git a/changelog.d/+drop-py37-code-changes.changed.md b/changelog.d/+drop-py37-code-changes.changed.md new file mode 100644 index 0000000000..e18c39bb23 --- /dev/null +++ b/changelog.d/+drop-py37-code-changes.changed.md @@ -0,0 +1 @@ +Change Python code due to dropping Python 3.7 \ No newline at end of file From afa855bd9b1dd2a4b389bd4d9ce585a5e9279332 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Wed, 8 May 2024 09:44:41 +0200 Subject: [PATCH 5/7] Remove hack for ssl-socket calls needed for Python 2 --- python/nav/statemon/abstractchecker.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/python/nav/statemon/abstractchecker.py b/python/nav/statemon/abstractchecker.py index dff8e6681b..afadda8f0e 100644 --- a/python/nav/statemon/abstractchecker.py +++ b/python/nav/statemon/abstractchecker.py @@ -111,24 +111,11 @@ def run(self): service = "%s:%s" % (self.sysname, self.get_type()) _logger.info("%-20s -> %s", service, info) - if status == event.Event.UP: - # Dirty hack to check if we timed out... - # this is needed as ssl-socket calls may hang - # in python < 2.3 - if self.response_time > 2 * self.timeout: - _logger.info( - "Adjusting status due to high responsetime (%s, " "%s)", - service, - self.response_time, - ) - status = event.Event.DOWN - self.response_time = 2 * self.timeout - if status != self.status and (self.runcount < int(self._conf.get('retry', 3))): delay = int(self._conf.get('retry delay', 5)) self.runcount += 1 _logger.info( - "%-20s -> State changed. New check in %i sec. (%s, " "%s)", + "%-20s -> State changed. New check in %i sec. (%s, %s)", service, delay, status, From 4a309893ebcb3b976571493daeb97a73d9ef7868 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Wed, 8 May 2024 11:41:02 +0200 Subject: [PATCH 6/7] Directly import HStoreField from Django We don't need the adapter for different Django versions anymore since Django 1.8 --- python/nav/adapters.py | 31 ------------------------------- python/nav/models/api.py | 2 +- python/nav/models/manage.py | 2 +- python/nav/models/profiles.py | 6 +++--- 4 files changed, 5 insertions(+), 36 deletions(-) delete mode 100644 python/nav/adapters.py diff --git a/python/nav/adapters.py b/python/nav/adapters.py deleted file mode 100644 index 91ae2da761..0000000000 --- a/python/nav/adapters.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2018 Uninett AS -# -# This file is part of Network Administration Visualized (NAV). -# -# NAV is free software: you can redistribute it and/or modify it under the -# terms of the GNU General Public License version 3 as published by the Free -# Software Foundation. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. You should have received a copy of the GNU General Public -# License along with NAV. If not, see . -# - -from __future__ import absolute_import - -# pylint: disable=invalid-name -try: - from django.contrib.postgres.fields import HStoreField - - DictionaryField = HStoreField -except ImportError: - from django_hstore.hstore import DictionaryField - - HStoreField = DictionaryField - -__all__ = [ - 'DictionaryField', - 'HStoreField', -] diff --git a/python/nav/models/api.py b/python/nav/models/api.py index f7495fe9c5..d3ac6213c9 100644 --- a/python/nav/models/api.py +++ b/python/nav/models/api.py @@ -17,10 +17,10 @@ from datetime import datetime +from django.contrib.postgres.fields import HStoreField from django.db import models from django.urls import reverse -from nav.adapters import HStoreField from nav.models.fields import VarcharField from nav.models.profiles import Account diff --git a/python/nav/models/manage.py b/python/nav/models/manage.py index 2d5c3492ce..14d370db59 100644 --- a/python/nav/models/manage.py +++ b/python/nav/models/manage.py @@ -32,6 +32,7 @@ import IPy from django.conf import settings +from django.contrib.postgres.fields import HStoreField from django.core.exceptions import ValidationError from django.db import models from django.db.models import JSONField, Q @@ -39,7 +40,6 @@ from django.urls import reverse from nav import util -from nav.adapters import HStoreField from nav.bitvector import BitVector from nav.metrics.data import get_netboxes_availability from nav.metrics.graphs import get_simple_graph_url, Graph diff --git a/python/nav/models/profiles.py b/python/nav/models/profiles.py index c5d97f0203..5a3ce146ca 100644 --- a/python/nav/models/profiles.py +++ b/python/nav/models/profiles.py @@ -26,12 +26,12 @@ import re import json -from django.views.decorators.debug import sensitive_variables +from django.contrib.postgres.fields import HStoreField from django.db import models, transaction -from django.urls import reverse from django.forms.models import model_to_dict +from django.urls import reverse +from django.views.decorators.debug import sensitive_variables -from nav.adapters import HStoreField import nav.buildconf import nav.pwhash from nav.config import getconfig as get_alertengine_config From 17a5009841a57b8c7178c69016fd415bc3bbfc50 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Wed, 8 May 2024 11:45:38 +0200 Subject: [PATCH 7/7] Directly import lru_cache from functools This has been superfluous since dropping Django 2.2 --- python/nav/alertengine/base.py | 2 +- python/nav/compatibility.py | 9 --------- python/nav/metrics/lookup.py | 2 +- python/nav/web/ipdevinfo/host_information.py | 2 +- 4 files changed, 3 insertions(+), 12 deletions(-) delete mode 100644 python/nav/compatibility.py diff --git a/python/nav/alertengine/base.py b/python/nav/alertengine/base.py index 1698ed2744..8a678e764f 100644 --- a/python/nav/alertengine/base.py +++ b/python/nav/alertengine/base.py @@ -22,10 +22,10 @@ import gc import logging from datetime import datetime, timedelta +from functools import lru_cache from django.db import transaction, reset_queries -from nav.compatibility import lru_cache from nav.models.profiles import ( Account, AccountAlertQueue, diff --git a/python/nav/compatibility.py b/python/nav/compatibility.py deleted file mode 100644 index 07ca52d024..0000000000 --- a/python/nav/compatibility.py +++ /dev/null @@ -1,9 +0,0 @@ -# lru_cache isn't used that much but one application of sed is faster -# than changing a block into a line three times. - -# When no longer supporting 2.2: -# s/nav.compatibility import lru_cache/functools import lru_cache/ -try: - from functools import lru_cache -except ImportError: - from django.utils.lru_cache import lru_cache diff --git a/python/nav/metrics/lookup.py b/python/nav/metrics/lookup.py index 79b1f15c3c..8d1b87ba38 100644 --- a/python/nav/metrics/lookup.py +++ b/python/nav/metrics/lookup.py @@ -16,9 +16,9 @@ # """Functions for reverse-mapping metric names to NAV objects""" +from functools import lru_cache import re -from nav.compatibility import lru_cache from nav.models.manage import Netbox, Interface, Prefix, Sensor diff --git a/python/nav/web/ipdevinfo/host_information.py b/python/nav/web/ipdevinfo/host_information.py index fd7a685879..c60b27dd39 100644 --- a/python/nav/web/ipdevinfo/host_information.py +++ b/python/nav/web/ipdevinfo/host_information.py @@ -15,10 +15,10 @@ # """Provides a function for getting host information""" +from functools import lru_cache import IPy from nav import asyncdns -from nav.compatibility import lru_cache from nav.util import is_valid_ip