mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-08-12 00:19:48 +00:00
Adds testing coverage plus a check for the locale being valid
This commit is contained in:
@@ -465,9 +465,6 @@ The `get_cf_value` filter retrieves a value from custom field data with optional
|
||||
|
||||
<!-- With default value -->
|
||||
{{ custom_fields | get_cf_value('phone', 'Not provided') }}
|
||||
|
||||
<!-- Handling missing fields -->
|
||||
{{ custom_fields | get_cf_value('optional_field', 'N/A') }}
|
||||
```
|
||||
|
||||
##### Datetime Formatting
|
||||
@@ -510,7 +507,7 @@ for the possible codes and their meanings.
|
||||
|
||||
##### Date Localization
|
||||
|
||||
The `localize_date1 filter formats a date or datetime object into a localized string using Babel internationalization.
|
||||
The `localize_date` filter formats a date or datetime object into a localized string using Babel internationalization.
|
||||
This takes into account the provided locale for translation.
|
||||
|
||||
###### Syntax
|
||||
@@ -558,7 +555,7 @@ This takes into account the provided locale for translation.
|
||||
<!-- Output: "15/01/2024" -->
|
||||
```
|
||||
|
||||
See the [supported locale codes]() for more options,
|
||||
See the [supported format codes](https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns) for more options.
|
||||
|
||||
### Format Presets
|
||||
|
||||
@@ -567,18 +564,6 @@ See the [supported locale codes]() for more options,
|
||||
- **long**: Long format with full month name (e.g., "January 15, 2024")
|
||||
- **full**: Full format including day of week (e.g., "Monday, January 15, 2024")
|
||||
|
||||
## Usage Notes
|
||||
|
||||
- All filters handle `None` values gracefully
|
||||
- Date strings are automatically parsed when needed
|
||||
- Timezone-aware datetime objects are recommended for `localize_date`
|
||||
- Custom field data should follow the expected dictionary structure for `get_cf_value`
|
||||
- Invalid format strings will raise appropriate Python exceptions
|
||||
|
||||
````
|
||||
|
||||
|
||||
|
||||
#### Additional Variables
|
||||
|
||||
- `{{ tag_name_list }}`: A list of tag names applied to the document, ordered by the tag name. Note this is a list, not a single string
|
||||
@@ -606,7 +591,7 @@ somepath/
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
/{{ title }}
|
||||
````
|
||||
```
|
||||
|
||||
For a document with an ASN of 205, it would result in `somepath/asn-201-400/asn-2xx/Title.pdf`, but
|
||||
a document with an ASN of 355 would be placed in `somepath/asn-201-400/asn-3xx/Title.pdf`.
|
||||
|
@@ -7,6 +7,7 @@ from datetime import datetime
|
||||
from pathlib import PurePath
|
||||
|
||||
import pathvalidate
|
||||
from babel import Locale
|
||||
from babel import dates
|
||||
from django.utils import timezone
|
||||
from django.utils.dateparse import parse_date
|
||||
@@ -116,6 +117,11 @@ def localize_date(value: date | datetime, format: str, locale: str) -> str:
|
||||
Raises:
|
||||
TypeError: If `value` is not a date or datetime instance.
|
||||
"""
|
||||
try:
|
||||
Locale.parse(locale)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Invalid locale identifier: {locale}") from e
|
||||
|
||||
if isinstance(value, datetime):
|
||||
return dates.format_datetime(value, format=format, locale=locale)
|
||||
elif isinstance(value, date):
|
||||
|
@@ -4,6 +4,7 @@ import tempfile
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from auditlog.context import disable_auditlog
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
@@ -22,6 +23,7 @@ from documents.models import Document
|
||||
from documents.models import DocumentType
|
||||
from documents.models import StoragePath
|
||||
from documents.tasks import empty_trash
|
||||
from documents.templating.filepath import localize_date
|
||||
from documents.tests.utils import DirectoriesMixin
|
||||
from documents.tests.utils import FileSystemAssertsMixin
|
||||
|
||||
@@ -1586,3 +1588,164 @@ class TestFilenameGeneration(DirectoriesMixin, TestCase):
|
||||
generate_filename(doc),
|
||||
Path("brussels-belgium/some-title-with-special-characters.pdf"),
|
||||
)
|
||||
|
||||
|
||||
class TestDateLocalization:
|
||||
"""
|
||||
Groups all tests related to the `localize_date` function.
|
||||
"""
|
||||
|
||||
TEST_DATE = datetime.date(2023, 10, 26)
|
||||
|
||||
TEST_DATETIME = datetime.datetime(
|
||||
2023,
|
||||
10,
|
||||
26,
|
||||
14,
|
||||
30,
|
||||
5,
|
||||
tzinfo=datetime.timezone.utc,
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value, format_style, locale_str, expected_output",
|
||||
[
|
||||
pytest.param(
|
||||
TEST_DATE,
|
||||
"EEEE, MMM d, yyyy",
|
||||
"en_US",
|
||||
"Thursday, Oct 26, 2023",
|
||||
id="date-en_US-custom",
|
||||
),
|
||||
pytest.param(
|
||||
TEST_DATE,
|
||||
"dd.MM.yyyy",
|
||||
"de_DE",
|
||||
"26.10.2023",
|
||||
id="date-de_DE-custom",
|
||||
),
|
||||
# German weekday and month name translation
|
||||
pytest.param(
|
||||
TEST_DATE,
|
||||
"EEEE",
|
||||
"de_DE",
|
||||
"Donnerstag",
|
||||
id="weekday-de_DE",
|
||||
),
|
||||
pytest.param(
|
||||
TEST_DATE,
|
||||
"MMMM",
|
||||
"de_DE",
|
||||
"October",
|
||||
id="month-de_DE",
|
||||
),
|
||||
# French weekday and month name translation
|
||||
pytest.param(
|
||||
TEST_DATE,
|
||||
"EEEE",
|
||||
"fr_FR",
|
||||
"jeudi",
|
||||
id="weekday-fr_FR",
|
||||
),
|
||||
pytest.param(
|
||||
TEST_DATE,
|
||||
"MMMM",
|
||||
"fr_FR",
|
||||
"octobre",
|
||||
id="month-fr_FR",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_localize_date_with_date_objects(
|
||||
self,
|
||||
value: datetime.date,
|
||||
format_style: str,
|
||||
locale_str: str,
|
||||
expected_output: str,
|
||||
):
|
||||
"""
|
||||
Tests `localize_date` with `date` objects across different locales and formats.
|
||||
"""
|
||||
assert localize_date(value, format_style, locale_str) == expected_output
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value, format_style, locale_str, expected_output",
|
||||
[
|
||||
pytest.param(
|
||||
TEST_DATETIME,
|
||||
"yyyy.MM.dd G 'at' HH:mm:ss zzz",
|
||||
"en_US",
|
||||
"2023.10.26 AD at 14:30:05 UTC",
|
||||
id="datetime-en_US-custom",
|
||||
),
|
||||
pytest.param(
|
||||
TEST_DATETIME,
|
||||
"dd.MM.yyyy",
|
||||
"fr_FR",
|
||||
"26.10.2023",
|
||||
id="date-fr_FR-custom",
|
||||
),
|
||||
# Spanish weekday and month translation
|
||||
pytest.param(
|
||||
TEST_DATETIME,
|
||||
"EEEE",
|
||||
"es_ES",
|
||||
"jueves",
|
||||
id="weekday-es_ES",
|
||||
),
|
||||
pytest.param(
|
||||
TEST_DATETIME,
|
||||
"MMMM",
|
||||
"es_ES",
|
||||
"octubre",
|
||||
id="month-es_ES",
|
||||
),
|
||||
# Italian weekday and month translation
|
||||
pytest.param(
|
||||
TEST_DATETIME,
|
||||
"EEEE",
|
||||
"it_IT",
|
||||
"giovedì",
|
||||
id="weekday-it_IT",
|
||||
),
|
||||
pytest.param(
|
||||
TEST_DATETIME,
|
||||
"MMMM",
|
||||
"it_IT",
|
||||
"ottobre",
|
||||
id="month-it_IT",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_localize_date_with_datetime_objects(
|
||||
self,
|
||||
value: datetime.datetime,
|
||||
format_style: str,
|
||||
locale_str: str,
|
||||
expected_output: str,
|
||||
):
|
||||
# To handle the non-breaking space in French and other locales
|
||||
result = localize_date(value, format_style, locale_str)
|
||||
assert result.replace("\u202f", " ") == expected_output.replace("\u202f", " ")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"invalid_value",
|
||||
[
|
||||
"2023-10-26",
|
||||
1698330605,
|
||||
None,
|
||||
[],
|
||||
{},
|
||||
],
|
||||
)
|
||||
def test_localize_date_raises_type_error_for_invalid_input(self, invalid_value):
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
localize_date(invalid_value, "medium", "en_US")
|
||||
|
||||
assert f"Unsupported type {type(invalid_value)}" in str(excinfo.value)
|
||||
|
||||
def test_localize_date_raises_error_for_invalid_locale(self):
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
localize_date(self.TEST_DATE, "medium", "invalid_locale_code")
|
||||
|
||||
assert "Invalid locale identifier" in str(excinfo.value)
|
||||
|
Reference in New Issue
Block a user