diff --git a/docs/changelog.rst b/docs/changelog.rst index 6c143a4e0c..d9cbb2d97a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,13 +9,13 @@ CHANGELOG - Add `include_externals` filter to Cirkwi trek exports, to allow excluding treks with an external id (eid) (#3947) - Tourism : add price to TouristicEvent model - ref #3587 +- Add `check_versions` command to check Geotrek, Python, Django, PostgreSQL and PostGIS versions. **Bug fixes** - Fix cache key for zoning cities - -**Improvments** +**Improvements** - Add popup button to add organizer in touristic event form - Change the `organizer` field of `TouristicEvent` model to a many to many field named `organizers` (#3587) diff --git a/docs/others/troubleshooting.rst b/docs/others/troubleshooting.rst index 004cea867d..27dc3dd81b 100644 --- a/docs/others/troubleshooting.rst +++ b/docs/others/troubleshooting.rst @@ -1,5 +1,5 @@ =============== -Troubleshouting +Troubleshooting =============== .. contents:: @@ -143,3 +143,35 @@ You have to update the signature key to get the last update : :: wget -O- "https://packages.geotrek.fr/geotrek.gpg.key" | sudo apt-key add - + + +Show main packages versions +--------------------------- + +To debug or to report a bug, you can check or provide in issue the main versions of Geotrek-admin and its dependencies : + +.. code-block :: bash + + geotrek check_versions + + +From docker: + +.. code-block :: bash + + docker compose run --rm web ./manage.py check_versions + + +Some examples: + +.. code-block :: bash + + geotrek check_versions --full + geotrek check_versions --postgis + + +Check command help for more options: + +.. code-block :: bash + + geotrek check_versions --help \ No newline at end of file diff --git a/geotrek/common/management/commands/check_versions.py b/geotrek/common/management/commands/check_versions.py new file mode 100644 index 0000000000..c4cbde480e --- /dev/null +++ b/geotrek/common/management/commands/check_versions.py @@ -0,0 +1,80 @@ +import sys + +import django +from django.core.management.base import BaseCommand +from django.db import connection + +from geotrek import __version__ + + +class Command(BaseCommand): + help = "Check Geotrek-admin, Python, Django, PostgreSQL and PostGIS version used by your system." + + def add_arguments(self, parser): + parser.add_argument('--geotrek', action='store_true', help="Show only Geotrek version.") + parser.add_argument('--python', action='store_true', help="Show only Python version.") + parser.add_argument('--django', action='store_true', help="Show only Django version.") + parser.add_argument('--postgresql', action='store_true', help="Show only PostgreSQL version.") + parser.add_argument('--postgis', action='store_true', help="Show only PostGIS version.") + parser.add_argument('--full', action='store_true', help="Show full version infos.") + + def get_geotrek_version(self): + return __version__ + + def get_python_version(self, full=False): + if full: + return sys.version + else: + major, minor, micro = sys.version_info[:3] + return f"{major}.{minor}.{micro}" + + def get_django_version(self): + return django.get_version() + + def get_postgresql_version(self, full=False): + with connection.cursor() as cursor: + if full: + cursor.execute("SELECT version()") + return cursor.fetchone()[0] + else: + cursor.execute("SHOW server_version") + return cursor.fetchone()[0].split(' ')[0] + + def get_postgis_version(self, full=False): + with connection.cursor() as cursor: + if full: + cursor.execute("SELECT PostGIS_full_version()") + return cursor.fetchone()[0] + else: + cursor.execute("SELECT PostGIS_version()") + return cursor.fetchone()[0].split(' ')[0] + + def handle(self, *args, **options): + full = options['full'] + + if options['geotrek']: + self.stdout.write(self.get_geotrek_version()) + return + + if options['python']: + self.stdout.write(self.get_python_version(full)) + return + + if options['django']: + self.stdout.write(self.get_django_version()) + return + + if options['postgresql']: + self.stdout.write(self.get_postgresql_version(full)) + return + + if options['postgis']: + self.stdout.write(self.get_postgis_version(full)) + return + + self.stdout.write(f"Geotrek version : {self.style.SUCCESS(self.get_geotrek_version())}") + self.stdout.write(f"Python version : {self.style.SUCCESS(self.get_python_version(full))}") + self.stdout.write(f"Django version : {self.style.SUCCESS(self.get_django_version())}") + self.stdout.write(f"PostgreSQL version : {self.style.SUCCESS(self.get_postgresql_version(full))}") + self.stdout.write(f"PostGIS version : {self.style.SUCCESS(self.get_postgis_version(full))}") + return diff --git a/geotrek/common/tests/test_command.py b/geotrek/common/tests/test_commands.py similarity index 76% rename from geotrek/common/tests/test_command.py rename to geotrek/common/tests/test_commands.py index b4f22514d1..b6ea812bef 100644 --- a/geotrek/common/tests/test_command.py +++ b/geotrek/common/tests/test_commands.py @@ -1,25 +1,24 @@ +import os +from io import StringIO +from unittest import mock +from unittest.mock import patch, PropertyMock + +from django.conf import settings from django.core.management import call_command from django.core.management.base import CommandError - from django.test import TestCase -from django.conf import settings +from easy_thumbnails.models import Thumbnail +from geotrek import __version__ from geotrek.authent.tests.factories import StructureFactory -from geotrek.common.tests.factories import AttachmentFactory, TargetPortalFactory from geotrek.common.models import TargetPortal +from geotrek.common.tests.factories import AttachmentFactory, TargetPortalFactory from geotrek.common.utils.testdata import get_dummy_uploaded_image -from geotrek.trekking.tests.factories import POIFactory -from geotrek.infrastructure.tests.factories import InfrastructureFactory, InfrastructureTypeFactory -from geotrek.infrastructure.models import InfrastructureType, Infrastructure from geotrek.core.models import Usage, Path from geotrek.core.tests.factories import UsageFactory, PathFactory - -from easy_thumbnails.models import Thumbnail - -from io import StringIO -import os - -from unittest import mock +from geotrek.infrastructure.models import InfrastructureType, Infrastructure +from geotrek.infrastructure.tests.factories import InfrastructureFactory, InfrastructureTypeFactory +from geotrek.trekking.tests.factories import POIFactory @mock.patch('sys.stdout', new_callable=StringIO) @@ -160,3 +159,51 @@ def test_clean_attachments_thumbnails(self): call_command('clean_attachments', stdout=output, verbosity=2) self.assertIn('%s... Thumbnail' % self.content.thumbnail.name, output.getvalue()) self.assertTrue(os.path.exists(self.content.thumbnail.path)) + + +class CheckVersionsCommandTestCase(TestCase): + def setUp(self): + self.output = StringIO() + + def test_geotrek_version(self): + call_command('check_versions', '--geotrek', stdout=self.output) + self.assertEqual(self.output.getvalue().strip(), __version__) + + @patch('geotrek.common.management.commands.check_versions.sys') + def test_python_version(self, mock_sys): + type(mock_sys).version_info = PropertyMock(return_value=(3, 9, 1, 'final', 0)) + call_command('check_versions', '--python', stdout=self.output) + self.assertEqual(self.output.getvalue().strip(), '3.9.1') + + @patch('django.get_version', return_value='3.2.7') + def test_django_version(self, mock_get_version): + call_command('check_versions', '--django', stdout=self.output) + self.assertEqual(self.output.getvalue().strip(), '3.2.7') + + @patch('django.db.connection.cursor') + def test_postgresql_version(self, mock_cursor): + mock_cursor.return_value.__enter__.return_value.fetchone.return_value = ['13.3'] + call_command('check_versions', '--postgresql', stdout=self.output) + self.assertEqual(self.output.getvalue().strip(), '13.3') + + @patch('django.db.connection.cursor') + def test_postgis_version(self, mock_cursor): + mock_cursor.return_value.__enter__.return_value.fetchone.return_value = ['3.1.0'] + call_command('check_versions', '--postgis', stdout=self.output) + self.assertEqual(self.output.getvalue().strip(), '3.1.0') + + @patch('geotrek.common.management.commands.check_versions.sys') + @patch('django.get_version', return_value='3.2.2') + @patch('django.db.connection.cursor') + def test_full_version(self, mock_cursor, mock_get_version, mock_version_info): + type(mock_version_info).version = PropertyMock(return_value="3.9.1") + mock_cursor.return_value.__enter__.return_value.fetchone.return_value = ['14', '3.0'] + call_command('check_versions', '--full', stdout=self.output) + expected_result = ( + f"Geotrek version : {__version__}\n" + "Python version : 3.9.1\n" + "Django version : 3.2.2\n" + "PostgreSQL version : 14\n" + "PostGIS version : 14" + ) + self.assertEqual(self.output.getvalue().strip(), expected_result)