diff --git a/CHANGES b/CHANGES index 7536f9e..ca7956d 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,7 @@ Version 0.9.9 (unreleased) * Proxy Deepl translations suggestions through the back-end to avoid CORS issues. (#271 thanks @rafaelromon, @biermeester and @matthiask) * Format code with pre-commit * Test against Django 4.2a +* replace case sensitivity check with setting Version 0.9.8 diff --git a/docs/settings.rst b/docs/settings.rst index 55d5d08..a26780d 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -27,6 +27,7 @@ Rosetta can be configured via the following parameters, to be defined in your pr * ``ROSETTA_LOGIN_URL``: Use this if you want to override the login URL for rosetta. Defaults to ``settings.LOGIN_URL``. * ``ROSETTA_LANGUAGES``: List of languages that Rosetta will offer to translate. This is useful when you wish to translate a language that is not yet defined in ``settings.LANGUAGES``. Defaults to ``settings.LANGUAGES``. * ``ROSETTA_SHOW_OCCURRENCES``: Determines whether occurrences (where the original text appears) should be shown next to the translations for context. Defaults to ``True``. +* ``ROSETTA_CASE_SENSITIVE_FILESYSTEM``: Overrides auto-detection of case sensitive OS. Defaults to ``None`` which enables auto-detection. Useful when running case sensitive OS (e.g. Ubuntu) in docker on case insensitive OS (e.g. MacOS). diff --git a/rosetta/poutil.py b/rosetta/poutil.py index da9d28b..011e4b7 100644 --- a/rosetta/poutil.py +++ b/rosetta/poutil.py @@ -71,11 +71,18 @@ def find_pos(lang, project_apps=True, django_apps=False, third_party_apps=False) ) ) - case_sensitive_file_system = True - tmphandle, tmppath = tempfile.mkstemp() - if os.path.exists(tmppath.upper()): - # Case insensitive file system. - case_sensitive_file_system = False + # is OS case sensitive? settings preferred over auto detection + case_sensitive_file_system = getattr( + settings, "ROSETTA_CASE_SENSITIVE_FILESYSTEM", None + ) + + # in case of no settings, attempt auto detection + if case_sensitive_file_system is None: + case_sensitive_file_system = True + tmphandle, tmppath = tempfile.mkstemp() + if os.path.exists(tmppath.upper()): + # Case insensitive file system. + case_sensitive_file_system = False # django/locale if django_apps: diff --git a/rosetta/tests/tests.py b/rosetta/tests/tests.py index 9015ad1..f1d43aa 100644 --- a/rosetta/tests/tests.py +++ b/rosetta/tests/tests.py @@ -2,10 +2,9 @@ import filecmp import hashlib import os import shutil +from unittest import mock from urllib.parse import urlencode -import vcr - from django import VERSION from django.conf import settings from django.core.exceptions import ImproperlyConfigured @@ -16,7 +15,9 @@ from django.test.client import Client from django.urls import resolve, reverse from django.utils.encoding import force_bytes +import vcr from rosetta import views +from rosetta.poutil import find_pos from rosetta.signals import entry_changed, post_save from rosetta.storage import get_storage @@ -382,14 +383,16 @@ class RosettaTestCase(TestCase): # Post a translation, it should have properly wrapped lines data = { - "m_bb9d8fe6159187b9ea494c1b313d23d4": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean " - "commodo ligula eget dolor. Aenean massa. Cum sociis natoque " - "penatibus et magnis dis parturient montes, nascetur ridiculus " - "mus. Donec quam felis, ultricies nec, pellentesque eu, pretium " - "quis, sem. Nulla consequat massa quis enim. Donec pede justo, " - "fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, " - "rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum " - "felis eu pede mollis pretium." + "m_bb9d8fe6159187b9ea494c1b313d23d4": ( + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean " + "commodo ligula eget dolor. Aenean massa. Cum sociis natoque " + "penatibus et magnis dis parturient montes, nascetur ridiculus " + "mus. Donec quam felis, ultricies nec, pellentesque eu, pretium " + "quis, sem. Nulla consequat massa quis enim. Donec pede justo, " + "fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, " + "rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum " + "felis eu pede mollis pretium." + ) } r = self.client.post(self.xx_form_url, data) with open(self.dest_file, "r") as po_file: @@ -762,8 +765,9 @@ class RosettaTestCase(TestCase): msg_hashes = message_hashes() data = {msg_hashes["String 1"]: "Translation 1"} self.client.post(self.xx_form_url, data) - po_file_hash_before, mo_file_hash_before = file_hash(po_file), file_hash( - mo_file + po_file_hash_before, mo_file_hash_before = ( + file_hash(po_file), + file_hash(mo_file), ) # Make a change to the translations @@ -1053,6 +1057,23 @@ class RosettaTestCase(TestCase): resp = self.client.get(reverse("admin:index")) self.assertNotContains(resp, "rosetta-content-main") + @mock.patch("rosetta.poutil.os.path.exists") + def test_273_override_case_sensitivity(self, path_mock): + path_mock.exists.return_value = False + # no setting + find_pos("en") + path_mock.assert_called_with(mock.ANY) + + path_mock.reset_mock() + with override_settings(ROSETTA_CASE_SENSITIVE_FILESYSTEM=False): + find_pos("en") + path_mock.isfile.assert_not_called() + + path_mock.reset_mock() + with override_settings(ROSETTA_CASE_SENSITIVE_FILESYSTEM=True): + find_pos("en") + path_mock.isfile.assert_not_called() + # Stubbed access control function def no_access(user): diff --git a/rosetta/urls.py b/rosetta/urls.py index 2843a42..6c53856 100644 --- a/rosetta/urls.py +++ b/rosetta/urls.py @@ -27,12 +27,12 @@ urlpatterns = [ name="rosetta-file-list", ), re_path( - r"^files/(?P[\w-]+)/(?P[\w\-_\.]+)/(?P\d+)/$", + r"^files/(?P[\w-]+)/(?P[\w\-_\.@]+)/(?P\d+)/$", views.TranslationFormView.as_view(), name="rosetta-form", ), re_path( - r"^files/(?P[\w-]+)/(?P[\w\-_\.]+)/(?P\d+)/download/$", + r"^files/(?P[\w-]+)/(?P[\w\-_\.@]+)/(?P\d+)/download/$", views.TranslationFileDownload.as_view(), name="rosetta-download-file", ),