mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-18 17:34:39 -05:00
Compare commits
No commits in common. "f940ed0b7b680e62c10f7338dcc7c7828ce9719a" and "6b248ef1406305d3c5cef66f5e98cbbb3409a59c" have entirely different histories.
f940ed0b7b
...
6b248ef140
2
.github/workflows/translate-strings.yml
vendored
2
.github/workflows/translate-strings.yml
vendored
@ -61,7 +61,7 @@ jobs:
|
|||||||
cd src-ui
|
cd src-ui
|
||||||
pnpm run ng extract-i18n
|
pnpm run ng extract-i18n
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: stefanzweifel/git-auto-commit-action@v6
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
with:
|
with:
|
||||||
file_pattern: 'src-ui/messages.xlf src/locale/en_US/LC_MESSAGES/django.po'
|
file_pattern: 'src-ui/messages.xlf src/locale/en_US/LC_MESSAGES/django.po'
|
||||||
commit_message: "Auto translate strings"
|
commit_message: "Auto translate strings"
|
||||||
|
@ -457,22 +457,6 @@ of the index and usually makes queries faster and also ensures that the
|
|||||||
autocompletion works properly. This command is regularly invoked by the
|
autocompletion works properly. This command is regularly invoked by the
|
||||||
task scheduler.
|
task scheduler.
|
||||||
|
|
||||||
### Clearing the database read cache
|
|
||||||
|
|
||||||
If the database read cache is enabled, **you must run this command** after making any changes to the database outside the application context.
|
|
||||||
This includes operations such as restoring a database backup or executing SQL statements like UPDATE, INSERT, DELETE, ALTER, CREATE, or DROP.
|
|
||||||
|
|
||||||
Failing to invalidate the cache after such modifications can lead to stale data being served from the cache, and **may cause data corruption** or inconsistent behavior in the application.
|
|
||||||
|
|
||||||
Use the following management command to clear the cache:
|
|
||||||
|
|
||||||
```
|
|
||||||
invalidate_cachalot
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! info
|
|
||||||
The database read cache is based on Django-Cachalot. You can refer to their [documentation](https://django-cachalot.readthedocs.io/en/latest/quickstart.html#manage-py-command).
|
|
||||||
|
|
||||||
### Managing filenames {#renamer}
|
### Managing filenames {#renamer}
|
||||||
|
|
||||||
If you use paperless' feature to
|
If you use paperless' feature to
|
||||||
|
@ -159,41 +159,6 @@ Available options are `postgresql` and `mariadb`.
|
|||||||
|
|
||||||
Defaults to unset, which uses Django’s built-in defaults.
|
Defaults to unset, which uses Django’s built-in defaults.
|
||||||
|
|
||||||
#### [`PAPERLESS_DB_READ_CACHE_ENABLED=<bool>`](#PAPERLESS_DB_READ_CACHE_ENABLED) {#PAPERLESS_DB_READ_CACHE_ENABLED}
|
|
||||||
|
|
||||||
: Caches the database read query results into Redis. This can significantly improve application response times by caching database queries, at the cost of slightly increased memory usage.
|
|
||||||
|
|
||||||
Defaults to `false`.
|
|
||||||
|
|
||||||
!!! danger
|
|
||||||
|
|
||||||
**Do not modify the database outside the application while it is running.**
|
|
||||||
This includes actions such as restoring a backup, upgrading the database, or performing manual inserts. All external modifications must be done **only when the application is stopped**.
|
|
||||||
After making any such changes, you **must invalidate the DB read cache** using the `invalidate_cachalot` management command.
|
|
||||||
|
|
||||||
#### [`PAPERLESS_READ_CACHE_TTL=<int>`](#PAPERLESS_READ_CACHE_TTL) {#PAPERLESS_READ_CACHE_TTL}
|
|
||||||
|
|
||||||
: Specifies how long (in seconds) read data should be cached.
|
|
||||||
|
|
||||||
Allowed values are between `1` (one second) and `31536000` (one year). Defaults to `3600` (one hour).
|
|
||||||
|
|
||||||
!!! warning
|
|
||||||
|
|
||||||
A high TTL increases memory usage over time. Memory may be used until end of TTL, even if the cache is invalidated with the `invalidate_cachalot` command.
|
|
||||||
|
|
||||||
In case of an out-of-memory (OOM) situation, Redis may stop accepting new data — including cache entries, scheduled tasks, and documents to consume.
|
|
||||||
If your system has limited RAM, consider configuring a dedicated Redis instance for the read cache, with a memory limit and the eviction policy set to `allkeys-lru`.
|
|
||||||
For more details, refer to the [Redis eviction policy documentation](https://redis.io/docs/latest/develop/reference/eviction/), and see the `PAPERLESS_READ_CACHE_REDIS_URL` setting to specify a separate Redis broker.
|
|
||||||
|
|
||||||
#### [`PAPERLESS_READ_CACHE_REDIS_URL=<url>`](#PAPERLESS_READ_CACHE_REDIS_URL) {#PAPERLESS_READ_CACHE_REDIS_URL}
|
|
||||||
|
|
||||||
: Defines the Redis instance used for the read cache.
|
|
||||||
|
|
||||||
Defaults to `None`.
|
|
||||||
|
|
||||||
!!! Note
|
|
||||||
If this value is not set, the same Redis instance used for scheduled tasks will be used for caching as well.
|
|
||||||
|
|
||||||
## Optional Services
|
## Optional Services
|
||||||
|
|
||||||
### Tika {#tika}
|
### Tika {#tika}
|
||||||
@ -1003,22 +968,6 @@ still perform some basic text pre-processing before matching.
|
|||||||
|
|
||||||
Defaults to 1.
|
Defaults to 1.
|
||||||
|
|
||||||
#### [`PAPERLESS_DATE_PARSER_LANGUAGES=<lang>`](#PAPERLESS_DATE_PARSER_LANGUAGES) {#PAPERLESS_DATE_PARSER_LANGUAGES}
|
|
||||||
|
|
||||||
Specifies which language Paperless should use when parsing dates from documents.
|
|
||||||
|
|
||||||
This should be a language code supported by the dateparser library,
|
|
||||||
for example: "en", or a combination such as "en+de".
|
|
||||||
Locales are also supported (e.g., "en-AU").
|
|
||||||
Multiple languages can be combined using "+", for example: "en+de" or "en-AU+de".
|
|
||||||
For valid values, refer to the list of supported languages and locales in the [dateparser documentation](https://dateparser.readthedocs.io/en/latest/supported_locales.html).
|
|
||||||
|
|
||||||
Set this to match the languages in which most of your documents are written.
|
|
||||||
If not set, Paperless will attempt to infer the language(s) from the OCR configuration (`PAPERLESS_OCR_LANGUAGE`).
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
This format differs from the `PAPERLESS_OCR_LANGUAGE` setting, which uses ISO 639-2 codes (3 letters, e.g., "eng+deu" for Tesseract OCR).
|
|
||||||
|
|
||||||
#### [`PAPERLESS_EMAIL_TASK_CRON=<cron expression>`](#PAPERLESS_EMAIL_TASK_CRON) {#PAPERLESS_EMAIL_TASK_CRON}
|
#### [`PAPERLESS_EMAIL_TASK_CRON=<cron expression>`](#PAPERLESS_EMAIL_TASK_CRON) {#PAPERLESS_EMAIL_TASK_CRON}
|
||||||
|
|
||||||
: Configures the scheduled email fetching frequency. The value
|
: Configures the scheduled email fetching frequency. The value
|
||||||
|
@ -26,7 +26,6 @@ dependencies = [
|
|||||||
"django~=5.1.7",
|
"django~=5.1.7",
|
||||||
"django-allauth[socialaccount,mfa]~=65.4.0",
|
"django-allauth[socialaccount,mfa]~=65.4.0",
|
||||||
"django-auditlog~=3.1.2",
|
"django-auditlog~=3.1.2",
|
||||||
"django-cachalot~=2.8.0",
|
|
||||||
"django-celery-results~=2.6.0",
|
"django-celery-results~=2.6.0",
|
||||||
"django-compression-middleware~=0.5.0",
|
"django-compression-middleware~=0.5.0",
|
||||||
"django-cors-headers~=4.7.0",
|
"django-cors-headers~=4.7.0",
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
<trans-unit id="ngb.alert.close" datatype="html">
|
<trans-unit id="ngb.alert.close" datatype="html">
|
||||||
<source>Close</source>
|
<source>Close</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/alert/alert.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/alert/alert.ts</context>
|
||||||
<context context-type="linenumber">50</context>
|
<context context-type="linenumber">50</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.carousel.slide-number" datatype="html">
|
<trans-unit id="ngb.carousel.slide-number" datatype="html">
|
||||||
<source> Slide <x id="INTERPOLATION" equiv-text="ueryList<NgbSli"/> of <x id="INTERPOLATION_1" equiv-text="EventSource = N"/> </source>
|
<source> Slide <x id="INTERPOLATION" equiv-text="ueryList<NgbSli"/> of <x id="INTERPOLATION_1" equiv-text="EventSource = N"/> </source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/carousel/carousel.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/carousel/carousel.ts</context>
|
||||||
<context context-type="linenumber">131,135</context>
|
<context context-type="linenumber">131,135</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">Currently selected slide number read by screen reader</note>
|
<note priority="1" from="description">Currently selected slide number read by screen reader</note>
|
||||||
@ -20,212 +20,212 @@
|
|||||||
<trans-unit id="ngb.carousel.previous" datatype="html">
|
<trans-unit id="ngb.carousel.previous" datatype="html">
|
||||||
<source>Previous</source>
|
<source>Previous</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/carousel/carousel.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/carousel/carousel.ts</context>
|
||||||
<context context-type="linenumber">157,159</context>
|
<context context-type="linenumber">157,159</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.carousel.next" datatype="html">
|
<trans-unit id="ngb.carousel.next" datatype="html">
|
||||||
<source>Next</source>
|
<source>Next</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/carousel/carousel.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/carousel/carousel.ts</context>
|
||||||
<context context-type="linenumber">198</context>
|
<context context-type="linenumber">198</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.datepicker.previous-month" datatype="html">
|
<trans-unit id="ngb.datepicker.previous-month" datatype="html">
|
||||||
<source>Previous month</source>
|
<source>Previous month</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
||||||
<context context-type="linenumber">83,85</context>
|
<context context-type="linenumber">83,85</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
||||||
<context context-type="linenumber">112</context>
|
<context context-type="linenumber">112</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.datepicker.next-month" datatype="html">
|
<trans-unit id="ngb.datepicker.next-month" datatype="html">
|
||||||
<source>Next month</source>
|
<source>Next month</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
||||||
<context context-type="linenumber">112</context>
|
<context context-type="linenumber">112</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/datepicker/datepicker-navigation.ts</context>
|
||||||
<context context-type="linenumber">112</context>
|
<context context-type="linenumber">112</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.HH" datatype="html">
|
<trans-unit id="ngb.timepicker.HH" datatype="html">
|
||||||
<source>HH</source>
|
<source>HH</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.toast.close-aria" datatype="html">
|
<trans-unit id="ngb.toast.close-aria" datatype="html">
|
||||||
<source>Close</source>
|
<source>Close</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.datepicker.select-month" datatype="html">
|
<trans-unit id="ngb.datepicker.select-month" datatype="html">
|
||||||
<source>Select month</source>
|
<source>Select month</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.first" datatype="html">
|
<trans-unit id="ngb.pagination.first" datatype="html">
|
||||||
<source>««</source>
|
<source>««</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.hours" datatype="html">
|
<trans-unit id="ngb.timepicker.hours" datatype="html">
|
||||||
<source>Hours</source>
|
<source>Hours</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.previous" datatype="html">
|
<trans-unit id="ngb.pagination.previous" datatype="html">
|
||||||
<source>«</source>
|
<source>«</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.MM" datatype="html">
|
<trans-unit id="ngb.timepicker.MM" datatype="html">
|
||||||
<source>MM</source>
|
<source>MM</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.next" datatype="html">
|
<trans-unit id="ngb.pagination.next" datatype="html">
|
||||||
<source>»</source>
|
<source>»</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.datepicker.select-year" datatype="html">
|
<trans-unit id="ngb.datepicker.select-year" datatype="html">
|
||||||
<source>Select year</source>
|
<source>Select year</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.minutes" datatype="html">
|
<trans-unit id="ngb.timepicker.minutes" datatype="html">
|
||||||
<source>Minutes</source>
|
<source>Minutes</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.last" datatype="html">
|
<trans-unit id="ngb.pagination.last" datatype="html">
|
||||||
<source>»»</source>
|
<source>»»</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.first-aria" datatype="html">
|
<trans-unit id="ngb.pagination.first-aria" datatype="html">
|
||||||
<source>First</source>
|
<source>First</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.increment-hours" datatype="html">
|
<trans-unit id="ngb.timepicker.increment-hours" datatype="html">
|
||||||
<source>Increment hours</source>
|
<source>Increment hours</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.previous-aria" datatype="html">
|
<trans-unit id="ngb.pagination.previous-aria" datatype="html">
|
||||||
<source>Previous</source>
|
<source>Previous</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.decrement-hours" datatype="html">
|
<trans-unit id="ngb.timepicker.decrement-hours" datatype="html">
|
||||||
<source>Decrement hours</source>
|
<source>Decrement hours</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.next-aria" datatype="html">
|
<trans-unit id="ngb.pagination.next-aria" datatype="html">
|
||||||
<source>Next</source>
|
<source>Next</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.increment-minutes" datatype="html">
|
<trans-unit id="ngb.timepicker.increment-minutes" datatype="html">
|
||||||
<source>Increment minutes</source>
|
<source>Increment minutes</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.pagination.last-aria" datatype="html">
|
<trans-unit id="ngb.pagination.last-aria" datatype="html">
|
||||||
<source>Last</source>
|
<source>Last</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.decrement-minutes" datatype="html">
|
<trans-unit id="ngb.timepicker.decrement-minutes" datatype="html">
|
||||||
<source>Decrement minutes</source>
|
<source>Decrement minutes</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.SS" datatype="html">
|
<trans-unit id="ngb.timepicker.SS" datatype="html">
|
||||||
<source>SS</source>
|
<source>SS</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.seconds" datatype="html">
|
<trans-unit id="ngb.timepicker.seconds" datatype="html">
|
||||||
<source>Seconds</source>
|
<source>Seconds</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.increment-seconds" datatype="html">
|
<trans-unit id="ngb.timepicker.increment-seconds" datatype="html">
|
||||||
<source>Increment seconds</source>
|
<source>Increment seconds</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.decrement-seconds" datatype="html">
|
<trans-unit id="ngb.timepicker.decrement-seconds" datatype="html">
|
||||||
<source>Decrement seconds</source>
|
<source>Decrement seconds</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ngb.timepicker.PM" datatype="html">
|
<trans-unit id="ngb.timepicker.PM" datatype="html">
|
||||||
<source><x id="INTERPOLATION"/></source>
|
<source><x id="INTERPOLATION"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/ngb-config.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/ngb-config.ts</context>
|
||||||
<context context-type="linenumber">13</context>
|
<context context-type="linenumber">13</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -233,7 +233,7 @@
|
|||||||
<source><x id="INTERPOLATION" equiv-text="barConfig);
|
<source><x id="INTERPOLATION" equiv-text="barConfig);
|
||||||
pu"/></source>
|
pu"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.1_@angular+common@20.0.6_@angular+core@20.0.6_@angular+_05316f125479eb303e49e3702b630d0f/node_modules/src/progressbar/progressbar.ts</context>
|
<context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@19.0.0_@angular+common@20.0.5_@angular+core@20.0.5_@angular+_d3ede862fd3f3ef56c2b56ed21f85d68/node_modules/src/progressbar/progressbar.ts</context>
|
||||||
<context context-type="linenumber">41,42</context>
|
<context context-type="linenumber">41,42</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
@ -12,26 +12,26 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/cdk": "^20.0.4",
|
"@angular/cdk": "^20.0.4",
|
||||||
"@angular/common": "~20.0.6",
|
"@angular/common": "~20.0.5",
|
||||||
"@angular/compiler": "~20.0.6",
|
"@angular/compiler": "~20.0.5",
|
||||||
"@angular/core": "~20.0.6",
|
"@angular/core": "~20.0.5",
|
||||||
"@angular/forms": "~20.0.6",
|
"@angular/forms": "~20.0.5",
|
||||||
"@angular/localize": "~20.0.6",
|
"@angular/localize": "~20.0.5",
|
||||||
"@angular/platform-browser": "~20.0.6",
|
"@angular/platform-browser": "~20.0.5",
|
||||||
"@angular/platform-browser-dynamic": "~20.0.6",
|
"@angular/platform-browser-dynamic": "~20.0.5",
|
||||||
"@angular/router": "~20.0.6",
|
"@angular/router": "~20.0.5",
|
||||||
"@ng-bootstrap/ng-bootstrap": "^19.0.1",
|
"@ng-bootstrap/ng-bootstrap": "^19.0.0",
|
||||||
"@ng-select/ng-select": "^15.1.3",
|
"@ng-select/ng-select": "^15.1.2",
|
||||||
"@ngneat/dirty-check-forms": "^3.0.3",
|
"@ngneat/dirty-check-forms": "^3.0.3",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"bootstrap": "^5.3.7",
|
"bootstrap": "^5.3.6",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"mime-names": "^1.0.0",
|
"mime-names": "^1.0.0",
|
||||||
"ng2-pdf-viewer": "^10.4.0",
|
"ng2-pdf-viewer": "^10.4.0",
|
||||||
"ngx-bootstrap-icons": "^1.9.3",
|
"ngx-bootstrap-icons": "^1.9.3",
|
||||||
"ngx-color": "^10.0.0",
|
"ngx-color": "^10.0.0",
|
||||||
"ngx-cookie-service": "^20.0.1",
|
"ngx-cookie-service": "^19.1.2",
|
||||||
"ngx-device-detector": "^10.0.2",
|
"ngx-device-detector": "^9.0.0",
|
||||||
"ngx-ui-tour-ng-bootstrap": "^17.0.0",
|
"ngx-ui-tour-ng-bootstrap": "^17.0.0",
|
||||||
"rxjs": "^7.8.2",
|
"rxjs": "^7.8.2",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
@ -51,15 +51,15 @@
|
|||||||
"@angular-eslint/template-parser": "20.1.1",
|
"@angular-eslint/template-parser": "20.1.1",
|
||||||
"@angular/build": "^20.0.4",
|
"@angular/build": "^20.0.4",
|
||||||
"@angular/cli": "~20.0.4",
|
"@angular/cli": "~20.0.4",
|
||||||
"@angular/compiler-cli": "~20.0.6",
|
"@angular/compiler-cli": "~20.0.5",
|
||||||
"@codecov/webpack-plugin": "^1.9.1",
|
"@codecov/webpack-plugin": "^1.9.1",
|
||||||
"@playwright/test": "^1.53.2",
|
"@playwright/test": "^1.51.1",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^24.0.10",
|
"@types/node": "^22.15.29",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
"@typescript-eslint/eslint-plugin": "^8.33.1",
|
||||||
"@typescript-eslint/parser": "^8.35.1",
|
"@typescript-eslint/parser": "^8.33.1",
|
||||||
"@typescript-eslint/utils": "^8.35.1",
|
"@typescript-eslint/utils": "^8.33.1",
|
||||||
"eslint": "^9.30.1",
|
"eslint": "^9.28.0",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"jest-junit": "^16.0.0",
|
"jest-junit": "^16.0.0",
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
"ts-node": "~10.9.1",
|
"ts-node": "~10.9.1",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"webpack": "^5.99.9"
|
"webpack": "^5.98.0"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
|
1606
src-ui/pnpm-lock.yaml
generated
1606
src-ui/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -280,7 +280,6 @@ def parse_date_generator(filename, text) -> Iterator[datetime.datetime]:
|
|||||||
"RETURN_AS_TIMEZONE_AWARE": True,
|
"RETURN_AS_TIMEZONE_AWARE": True,
|
||||||
"TIMEZONE": settings.TIME_ZONE,
|
"TIMEZONE": settings.TIME_ZONE,
|
||||||
},
|
},
|
||||||
locales=settings.DATE_PARSER_LANGUAGES,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __filter(date: datetime.datetime) -> datetime.datetime | None:
|
def __filter(date: datetime.datetime) -> datetime.datetime | None:
|
||||||
|
@ -44,22 +44,12 @@ class TestDate:
|
|||||||
)
|
)
|
||||||
assert parse_date("", text) is None
|
assert parse_date("", text) is None
|
||||||
|
|
||||||
def test_date_format_7(
|
def test_date_format_7(self, settings_timezone: ZoneInfo):
|
||||||
self,
|
|
||||||
settings: SettingsWrapper,
|
|
||||||
settings_timezone: ZoneInfo,
|
|
||||||
):
|
|
||||||
settings.DATE_PARSER_LANGUAGES = []
|
|
||||||
text = "lorem ipsum\nMärz 2019\nlorem ipsum"
|
text = "lorem ipsum\nMärz 2019\nlorem ipsum"
|
||||||
date = parse_date("", text)
|
date = parse_date("", text)
|
||||||
assert date == datetime.datetime(2019, 3, 1, 0, 0, tzinfo=settings_timezone)
|
assert date == datetime.datetime(2019, 3, 1, 0, 0, tzinfo=settings_timezone)
|
||||||
|
|
||||||
def test_date_format_8(
|
def test_date_format_8(self, settings_timezone: ZoneInfo):
|
||||||
self,
|
|
||||||
settings: SettingsWrapper,
|
|
||||||
settings_timezone: ZoneInfo,
|
|
||||||
):
|
|
||||||
settings.DATE_PARSER_LANGUAGES = ["de"]
|
|
||||||
text = (
|
text = (
|
||||||
"lorem ipsum\n"
|
"lorem ipsum\n"
|
||||||
"Wohnort\n"
|
"Wohnort\n"
|
||||||
@ -81,12 +71,7 @@ class TestDate:
|
|||||||
tzinfo=settings_timezone,
|
tzinfo=settings_timezone,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_date_format_9(
|
def test_date_format_9(self, settings_timezone: ZoneInfo):
|
||||||
self,
|
|
||||||
settings: SettingsWrapper,
|
|
||||||
settings_timezone: ZoneInfo,
|
|
||||||
):
|
|
||||||
settings.DATE_PARSER_LANGUAGES = ["de"]
|
|
||||||
text = "lorem ipsum\n27. Nullmonth 2020\nMärz 2020\nlorem ipsum"
|
text = "lorem ipsum\n27. Nullmonth 2020\nMärz 2020\nlorem ipsum"
|
||||||
assert parse_date("", text) == datetime.datetime(
|
assert parse_date("", text) == datetime.datetime(
|
||||||
2020,
|
2020,
|
||||||
@ -265,12 +250,7 @@ class TestDate:
|
|||||||
def test_crazy_date_with_spaces(self):
|
def test_crazy_date_with_spaces(self):
|
||||||
assert parse_date("", "20 408000l 2475") is None
|
assert parse_date("", "20 408000l 2475") is None
|
||||||
|
|
||||||
def test_utf_month_names(
|
def test_utf_month_names(self, settings_timezone: ZoneInfo):
|
||||||
self,
|
|
||||||
settings: SettingsWrapper,
|
|
||||||
settings_timezone: ZoneInfo,
|
|
||||||
):
|
|
||||||
settings.DATE_PARSER_LANGUAGES = ["fr", "de", "hr", "cs", "pl", "tr"]
|
|
||||||
assert parse_date("", "13 décembre 2023") == datetime.datetime(
|
assert parse_date("", "13 décembre 2023") == datetime.datetime(
|
||||||
2023,
|
2023,
|
||||||
12,
|
12,
|
||||||
|
@ -2,7 +2,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: paperless-ngx\n"
|
"Project-Id-Version: paperless-ngx\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-07-01 05:58+0000\n"
|
"POT-Creation-Date: 2025-06-29 04:39+0000\n"
|
||||||
"PO-Revision-Date: 2022-02-17 04:17\n"
|
"PO-Revision-Date: 2022-02-17 04:17\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: English\n"
|
"Language-Team: English\n"
|
||||||
@ -1645,143 +1645,143 @@ msgstr ""
|
|||||||
msgid "paperless application settings"
|
msgid "paperless application settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:763
|
#: paperless/settings.py:755
|
||||||
msgid "English (US)"
|
msgid "English (US)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:764
|
#: paperless/settings.py:756
|
||||||
msgid "Arabic"
|
msgid "Arabic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:765
|
#: paperless/settings.py:757
|
||||||
msgid "Afrikaans"
|
msgid "Afrikaans"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:766
|
#: paperless/settings.py:758
|
||||||
msgid "Belarusian"
|
msgid "Belarusian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:767
|
#: paperless/settings.py:759
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:768
|
#: paperless/settings.py:760
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:769
|
#: paperless/settings.py:761
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:770
|
#: paperless/settings.py:762
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:771
|
#: paperless/settings.py:763
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:772
|
#: paperless/settings.py:764
|
||||||
msgid "Greek"
|
msgid "Greek"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:773
|
#: paperless/settings.py:765
|
||||||
msgid "English (GB)"
|
msgid "English (GB)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:774
|
#: paperless/settings.py:766
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:775
|
#: paperless/settings.py:767
|
||||||
msgid "Persian"
|
msgid "Persian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:776
|
#: paperless/settings.py:768
|
||||||
msgid "Finnish"
|
msgid "Finnish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:777
|
#: paperless/settings.py:769
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:778
|
#: paperless/settings.py:770
|
||||||
msgid "Hungarian"
|
msgid "Hungarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:779
|
#: paperless/settings.py:771
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:780
|
#: paperless/settings.py:772
|
||||||
msgid "Japanese"
|
msgid "Japanese"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:781
|
#: paperless/settings.py:773
|
||||||
msgid "Korean"
|
msgid "Korean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:782
|
#: paperless/settings.py:774
|
||||||
msgid "Luxembourgish"
|
msgid "Luxembourgish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:783
|
#: paperless/settings.py:775
|
||||||
msgid "Norwegian"
|
msgid "Norwegian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:784
|
#: paperless/settings.py:776
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:785
|
#: paperless/settings.py:777
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:786
|
#: paperless/settings.py:778
|
||||||
msgid "Portuguese (Brazil)"
|
msgid "Portuguese (Brazil)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:787
|
#: paperless/settings.py:779
|
||||||
msgid "Portuguese"
|
msgid "Portuguese"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:788
|
#: paperless/settings.py:780
|
||||||
msgid "Romanian"
|
msgid "Romanian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:789
|
#: paperless/settings.py:781
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:790
|
#: paperless/settings.py:782
|
||||||
msgid "Slovak"
|
msgid "Slovak"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:791
|
#: paperless/settings.py:783
|
||||||
msgid "Slovenian"
|
msgid "Slovenian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:792
|
#: paperless/settings.py:784
|
||||||
msgid "Serbian"
|
msgid "Serbian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:793
|
#: paperless/settings.py:785
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:794
|
#: paperless/settings.py:786
|
||||||
msgid "Turkish"
|
msgid "Turkish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:795
|
#: paperless/settings.py:787
|
||||||
msgid "Ukrainian"
|
msgid "Ukrainian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:796
|
#: paperless/settings.py:788
|
||||||
msgid "Chinese Simplified"
|
msgid "Chinese Simplified"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: paperless/settings.py:797
|
#: paperless/settings.py:789
|
||||||
msgid "Chinese Traditional"
|
msgid "Chinese Traditional"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
from cachalot.api import invalidate as cachalot_invalidate
|
|
||||||
from cachalot.utils import get_query_cache_key
|
|
||||||
from cachalot.utils import get_table_cache_key
|
|
||||||
|
|
||||||
PREFIX = "pngx_cachalot_"
|
|
||||||
|
|
||||||
|
|
||||||
def custom_get_query_cache_key(compiler):
|
|
||||||
return PREFIX + get_query_cache_key(compiler)
|
|
||||||
|
|
||||||
|
|
||||||
def custom_get_table_cache_key(db_alias, table):
|
|
||||||
return PREFIX + get_table_cache_key(db_alias, table)
|
|
||||||
|
|
||||||
|
|
||||||
def invalidate_db_cache():
|
|
||||||
return cachalot_invalidate(cache_alias="read-cache")
|
|
@ -1,7 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import logging
|
|
||||||
import logging.config
|
|
||||||
import math
|
import math
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
import os
|
||||||
@ -14,14 +12,9 @@ from urllib.parse import urlparse
|
|||||||
|
|
||||||
from celery.schedules import crontab
|
from celery.schedules import crontab
|
||||||
from concurrent_log_handler.queue import setup_logging_queues
|
from concurrent_log_handler.queue import setup_logging_queues
|
||||||
from dateparser.languages.loader import LocaleDataLoader
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
from paperless.utils import ocr_to_dateparser_languages
|
|
||||||
|
|
||||||
logger = logging.getLogger("paperless.settings")
|
|
||||||
|
|
||||||
# Tap paperless.conf if it's available
|
# Tap paperless.conf if it's available
|
||||||
for path in [
|
for path in [
|
||||||
os.getenv("PAPERLESS_CONFIGURATION_PATH"),
|
os.getenv("PAPERLESS_CONFIGURATION_PATH"),
|
||||||
@ -440,7 +433,6 @@ STORAGES = {
|
|||||||
_CELERY_REDIS_URL, _CHANNELS_REDIS_URL = _parse_redis_url(
|
_CELERY_REDIS_URL, _CHANNELS_REDIS_URL = _parse_redis_url(
|
||||||
os.getenv("PAPERLESS_REDIS", None),
|
os.getenv("PAPERLESS_REDIS", None),
|
||||||
)
|
)
|
||||||
_REDIS_KEY_PREFIX = os.getenv("PAPERLESS_REDIS_PREFIX", "")
|
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
@ -466,7 +458,7 @@ CHANNEL_LAYERS = {
|
|||||||
"hosts": [_CHANNELS_REDIS_URL],
|
"hosts": [_CHANNELS_REDIS_URL],
|
||||||
"capacity": 2000, # default 100
|
"capacity": 2000, # default 100
|
||||||
"expiry": 15, # default 60
|
"expiry": 15, # default 60
|
||||||
"prefix": _REDIS_KEY_PREFIX,
|
"prefix": os.getenv("PAPERLESS_REDIS_PREFIX", ""),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -871,10 +863,6 @@ LOGGING = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configure logging before calling any logger in settings.py so it will respect the log format, even if Django has not parsed the settings yet.
|
|
||||||
logging.config.dictConfig(LOGGING)
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Task queue #
|
# Task queue #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@ -894,7 +882,7 @@ CELERY_SEND_TASK_SENT_EVENT = True
|
|||||||
CELERY_BROKER_CONNECTION_RETRY = True
|
CELERY_BROKER_CONNECTION_RETRY = True
|
||||||
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
|
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
|
||||||
CELERY_BROKER_TRANSPORT_OPTIONS = {
|
CELERY_BROKER_TRANSPORT_OPTIONS = {
|
||||||
"global_keyprefix": _REDIS_KEY_PREFIX,
|
"global_keyprefix": os.getenv("PAPERLESS_REDIS_PREFIX", ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
CELERY_TASK_TRACK_STARTED = True
|
CELERY_TASK_TRACK_STARTED = True
|
||||||
@ -915,65 +903,22 @@ CELERY_BEAT_SCHEDULE = _parse_beat_schedule()
|
|||||||
# https://docs.celeryq.dev/en/stable/userguide/configuration.html#beat-schedule-filename
|
# https://docs.celeryq.dev/en/stable/userguide/configuration.html#beat-schedule-filename
|
||||||
CELERY_BEAT_SCHEDULE_FILENAME = str(DATA_DIR / "celerybeat-schedule.db")
|
CELERY_BEAT_SCHEDULE_FILENAME = str(DATA_DIR / "celerybeat-schedule.db")
|
||||||
|
|
||||||
|
# django setting.
|
||||||
# Cachalot: Database read cache.
|
CACHES = {
|
||||||
def _parse_cachalot_settings():
|
"default": {
|
||||||
ttl = __get_int("PAPERLESS_READ_CACHE_TTL", 3600)
|
"BACKEND": os.environ.get(
|
||||||
ttl = min(ttl, 31536000) if ttl > 0 else 3600
|
"PAPERLESS_CACHE_BACKEND",
|
||||||
_, redis_url = _parse_redis_url(
|
"django.core.cache.backends.redis.RedisCache",
|
||||||
os.getenv("PAPERLESS_READ_CACHE_REDIS_URL", _CHANNELS_REDIS_URL),
|
|
||||||
)
|
|
||||||
result = {
|
|
||||||
"CACHALOT_CACHE": "read-cache",
|
|
||||||
"CACHALOT_ENABLED": __get_boolean(
|
|
||||||
"PAPERLESS_DB_READ_CACHE_ENABLED",
|
|
||||||
default="no",
|
|
||||||
),
|
),
|
||||||
"CACHALOT_FINAL_SQL_CHECK": True,
|
"LOCATION": _CHANNELS_REDIS_URL,
|
||||||
"CACHALOT_QUERY_KEYGEN": "paperless.db_cache.custom_get_query_cache_key",
|
"KEY_PREFIX": os.getenv("PAPERLESS_REDIS_PREFIX", ""),
|
||||||
"CACHALOT_TABLE_KEYGEN": "paperless.db_cache.custom_get_table_cache_key",
|
},
|
||||||
"CACHALOT_REDIS_URL": redis_url,
|
}
|
||||||
"CACHALOT_TIMEOUT": ttl,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
if DEBUG and os.getenv("PAPERLESS_CACHE_BACKEND") is None:
|
||||||
cachalot_settings = _parse_cachalot_settings()
|
CACHES["default"]["BACKEND"] = (
|
||||||
CACHALOT_ENABLED = cachalot_settings["CACHALOT_ENABLED"]
|
"django.core.cache.backends.locmem.LocMemCache" # pragma: no cover
|
||||||
if CACHALOT_ENABLED: # pragma: no cover
|
)
|
||||||
INSTALLED_APPS.append("cachalot")
|
|
||||||
CACHALOT_CACHE = cachalot_settings["CACHALOT_CACHE"]
|
|
||||||
CACHALOT_TIMEOUT = cachalot_settings["CACHALOT_TIMEOUT"]
|
|
||||||
CACHALOT_QUERY_KEYGEN = cachalot_settings["CACHALOT_QUERY_KEYGEN"]
|
|
||||||
CACHALOT_TABLE_KEYGEN = cachalot_settings["CACHALOT_TABLE_KEYGEN"]
|
|
||||||
CACHALOT_FINAL_SQL_CHECK = cachalot_settings["CACHALOT_FINAL_SQL_CHECK"]
|
|
||||||
|
|
||||||
|
|
||||||
# Django default & Cachalot cache configuration
|
|
||||||
_CACHE_BACKEND = os.environ.get(
|
|
||||||
"PAPERLESS_CACHE_BACKEND",
|
|
||||||
"django.core.cache.backends.locmem.LocMemCache"
|
|
||||||
if DEBUG
|
|
||||||
else "django.core.cache.backends.redis.RedisCache",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_caches():
|
|
||||||
return {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": _CACHE_BACKEND,
|
|
||||||
"LOCATION": _CHANNELS_REDIS_URL,
|
|
||||||
"KEY_PREFIX": _REDIS_KEY_PREFIX,
|
|
||||||
},
|
|
||||||
"read-cache": {
|
|
||||||
"BACKEND": _CACHE_BACKEND,
|
|
||||||
"LOCATION": cachalot_settings["CACHALOT_REDIS_URL"],
|
|
||||||
"KEY_PREFIX": _REDIS_KEY_PREFIX,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CACHES = _parse_caches()
|
|
||||||
|
|
||||||
|
|
||||||
def default_threads_per_worker(task_workers) -> int:
|
def default_threads_per_worker(task_workers) -> int:
|
||||||
@ -1173,84 +1118,6 @@ POST_CONSUME_SCRIPT = os.getenv("PAPERLESS_POST_CONSUME_SCRIPT")
|
|||||||
DATE_ORDER = os.getenv("PAPERLESS_DATE_ORDER", "DMY")
|
DATE_ORDER = os.getenv("PAPERLESS_DATE_ORDER", "DMY")
|
||||||
FILENAME_DATE_ORDER = os.getenv("PAPERLESS_FILENAME_DATE_ORDER")
|
FILENAME_DATE_ORDER = os.getenv("PAPERLESS_FILENAME_DATE_ORDER")
|
||||||
|
|
||||||
|
|
||||||
def _ocr_to_dateparser_languages(ocr_languages: str) -> list[str]:
|
|
||||||
"""
|
|
||||||
Convert Tesseract OCR_LANGUAGE codes (ISO 639-2, e.g. "eng+fra", with optional scripts like "aze_Cyrl")
|
|
||||||
into a list of locales compatible with the `dateparser` library.
|
|
||||||
|
|
||||||
- If a script is provided (e.g., "aze_Cyrl"), attempts to use the full locale (e.g., "az-Cyrl").
|
|
||||||
Falls back to the base language (e.g., "az") if needed.
|
|
||||||
- If a language cannot be mapped or validated, it is skipped with a warning.
|
|
||||||
- Returns a list of valid locales, or an empty list if none could be converted.
|
|
||||||
"""
|
|
||||||
ocr_to_dateparser = ocr_to_dateparser_languages()
|
|
||||||
loader = LocaleDataLoader()
|
|
||||||
result = []
|
|
||||||
try:
|
|
||||||
for ocr_language in ocr_languages.split("+"):
|
|
||||||
# Split into language and optional script
|
|
||||||
ocr_lang_part, *script = ocr_language.split("_")
|
|
||||||
ocr_script_part = script[0] if script else None
|
|
||||||
|
|
||||||
language_part = ocr_to_dateparser.get(ocr_lang_part)
|
|
||||||
if language_part is None:
|
|
||||||
logger.warning(
|
|
||||||
f'Skipping unknown OCR language "{ocr_language}" — no dateparser equivalent.',
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Ensure base language is supported by dateparser
|
|
||||||
loader.get_locale_map(locales=[language_part])
|
|
||||||
|
|
||||||
# Try to add the script part if it's supported by dateparser
|
|
||||||
if ocr_script_part:
|
|
||||||
dateparser_language = f"{language_part}-{ocr_script_part.title()}"
|
|
||||||
try:
|
|
||||||
loader.get_locale_map(locales=[dateparser_language])
|
|
||||||
except Exception:
|
|
||||||
logger.warning(
|
|
||||||
f"Language variant '{dateparser_language}' not supported by dateparser; falling back to base language '{language_part}'. You can manually set PAPERLESS_DATE_PARSER_LANGUAGES if needed.",
|
|
||||||
)
|
|
||||||
dateparser_language = language_part
|
|
||||||
else:
|
|
||||||
dateparser_language = language_part
|
|
||||||
if dateparser_language not in result:
|
|
||||||
result.append(dateparser_language)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(
|
|
||||||
f"Could not configure dateparser languages. Set PAPERLESS_DATE_PARSER_LANGUAGES parameter to avoid this. Detail: {e}",
|
|
||||||
)
|
|
||||||
return []
|
|
||||||
if not result:
|
|
||||||
logger.warning(
|
|
||||||
"Could not configure any dateparser languages from OCR_LANGUAGE — fallback to autodetection.",
|
|
||||||
)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_dateparser_languages(languages: str | None):
|
|
||||||
language_list = languages.split("+") if languages else []
|
|
||||||
# There is an unfixed issue in zh-Hant and zh-Hans locales in the dateparser lib.
|
|
||||||
# See: https://github.com/scrapinghub/dateparser/issues/875
|
|
||||||
for index, language in enumerate(language_list):
|
|
||||||
if language.startswith("zh-") and "zh" not in language_list:
|
|
||||||
logger.warning(
|
|
||||||
f'Chinese locale detected: {language}. dateparser might fail to parse some dates with this locale, so Chinese ("zh") will be used as a fallback.',
|
|
||||||
)
|
|
||||||
language_list.append("zh")
|
|
||||||
|
|
||||||
return list(LocaleDataLoader().get_locale_map(locales=language_list))
|
|
||||||
|
|
||||||
|
|
||||||
if os.getenv("PAPERLESS_DATE_PARSER_LANGUAGES"):
|
|
||||||
DATE_PARSER_LANGUAGES = _parse_dateparser_languages(
|
|
||||||
os.getenv("PAPERLESS_DATE_PARSER_LANGUAGES"),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
DATE_PARSER_LANGUAGES = _ocr_to_dateparser_languages(OCR_LANGUAGE)
|
|
||||||
|
|
||||||
|
|
||||||
# Maximum number of dates taken from document start to end to show as suggestions for
|
# Maximum number of dates taken from document start to end to show as suggestions for
|
||||||
# `created` date in the frontend. Duplicates are removed, which can result in
|
# `created` date in the frontend. Duplicates are removed, which can result in
|
||||||
# fewer dates shown.
|
# fewer dates shown.
|
||||||
|
@ -1,156 +0,0 @@
|
|||||||
import os
|
|
||||||
import time
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from cachalot.settings import cachalot_settings
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import connection
|
|
||||||
from django.test import override_settings
|
|
||||||
from django.test.utils import CaptureQueriesContext
|
|
||||||
|
|
||||||
from documents.models import Tag
|
|
||||||
from paperless.db_cache import invalidate_db_cache
|
|
||||||
from paperless.settings import _parse_cachalot_settings
|
|
||||||
from paperless.settings import _parse_caches
|
|
||||||
|
|
||||||
|
|
||||||
def test_all_redis_caches_have_same_custom_prefix(monkeypatch):
|
|
||||||
"""
|
|
||||||
Check that when setting a custom Redis prefix,
|
|
||||||
it is set for both the Django default cache and the read cache.
|
|
||||||
"""
|
|
||||||
from paperless import settings
|
|
||||||
|
|
||||||
monkeypatch.setattr(settings, "_REDIS_KEY_PREFIX", "test_a_custom_key_prefix")
|
|
||||||
caches = _parse_caches()
|
|
||||||
assert caches["read-cache"]["KEY_PREFIX"] == "test_a_custom_key_prefix"
|
|
||||||
assert caches["default"]["KEY_PREFIX"] == "test_a_custom_key_prefix"
|
|
||||||
|
|
||||||
|
|
||||||
class TestDbCacheSettings:
|
|
||||||
def test_cachalot_default_settings(self):
|
|
||||||
# Cachalot must be installed even if disabled,
|
|
||||||
# so the cache can be invalidated anytime
|
|
||||||
assert "cachalot" not in settings.INSTALLED_APPS
|
|
||||||
cachalot_settings = _parse_cachalot_settings()
|
|
||||||
caches = _parse_caches()
|
|
||||||
|
|
||||||
# Default settings
|
|
||||||
assert not cachalot_settings["CACHALOT_ENABLED"]
|
|
||||||
assert cachalot_settings["CACHALOT_TIMEOUT"] == 3600
|
|
||||||
assert caches["read-cache"]["KEY_PREFIX"] == ""
|
|
||||||
assert caches["read-cache"]["LOCATION"] == "redis://localhost:6379"
|
|
||||||
|
|
||||||
# Fixed settings
|
|
||||||
assert cachalot_settings["CACHALOT_CACHE"] == "read-cache"
|
|
||||||
assert (
|
|
||||||
cachalot_settings["CACHALOT_QUERY_KEYGEN"]
|
|
||||||
== "paperless.db_cache.custom_get_query_cache_key"
|
|
||||||
)
|
|
||||||
assert (
|
|
||||||
cachalot_settings["CACHALOT_TABLE_KEYGEN"]
|
|
||||||
== "paperless.db_cache.custom_get_table_cache_key"
|
|
||||||
)
|
|
||||||
assert cachalot_settings["CACHALOT_FINAL_SQL_CHECK"] is True
|
|
||||||
|
|
||||||
@patch.dict(
|
|
||||||
os.environ,
|
|
||||||
{
|
|
||||||
"PAPERLESS_DB_READ_CACHE_ENABLED": "true",
|
|
||||||
"PAPERLESS_READ_CACHE_REDIS_URL": "redis://localhost:6380/7",
|
|
||||||
"PAPERLESS_READ_CACHE_TTL": "7200",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
def test_cachalot_custom_settings(self):
|
|
||||||
settings = _parse_cachalot_settings()
|
|
||||||
|
|
||||||
assert settings["CACHALOT_ENABLED"]
|
|
||||||
assert settings["CACHALOT_TIMEOUT"] == 7200
|
|
||||||
assert settings["CACHALOT_CACHE"] == "read-cache"
|
|
||||||
assert (
|
|
||||||
settings["CACHALOT_QUERY_KEYGEN"]
|
|
||||||
== "paperless.db_cache.custom_get_query_cache_key"
|
|
||||||
)
|
|
||||||
assert (
|
|
||||||
settings["CACHALOT_TABLE_KEYGEN"]
|
|
||||||
== "paperless.db_cache.custom_get_table_cache_key"
|
|
||||||
)
|
|
||||||
assert settings["CACHALOT_FINAL_SQL_CHECK"] is True
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
("env_var_ttl", "expected_cachalot_timeout"),
|
|
||||||
[
|
|
||||||
# 0 or less will be ignored, and the default TTL will be set
|
|
||||||
("0", 3600),
|
|
||||||
("-1", 3600),
|
|
||||||
("-500000", 3600),
|
|
||||||
# Any positive value will be set, for a maximum of one year
|
|
||||||
("1", 1),
|
|
||||||
("7524", 7524),
|
|
||||||
("99999999999999", 31536000),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_cachalot_ttl_parsing(
|
|
||||||
self,
|
|
||||||
env_var_ttl: int,
|
|
||||||
expected_cachalot_timeout: int,
|
|
||||||
):
|
|
||||||
with patch.dict(os.environ, {"PAPERLESS_READ_CACHE_TTL": f"{env_var_ttl}"}):
|
|
||||||
cachalot_timeout = _parse_cachalot_settings()["CACHALOT_TIMEOUT"]
|
|
||||||
assert cachalot_timeout == expected_cachalot_timeout
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(
|
|
||||||
CACHALOT_ENABLED=True,
|
|
||||||
CACHALOT_TIMEOUT=1,
|
|
||||||
)
|
|
||||||
@pytest.mark.django_db(transaction=True)
|
|
||||||
def test_cache_hit_when_enabled():
|
|
||||||
cachalot_settings.reload()
|
|
||||||
|
|
||||||
assert cachalot_settings.CACHALOT_ENABLED
|
|
||||||
assert cachalot_settings.CACHALOT_TIMEOUT == 1
|
|
||||||
assert settings.CACHALOT_TIMEOUT == 1
|
|
||||||
|
|
||||||
# Read a table to populate the cache
|
|
||||||
list(list(Tag.objects.values_list("id", flat=True)))
|
|
||||||
|
|
||||||
# Invalidate the cache then read the database, there should be DB hit
|
|
||||||
invalidate_db_cache()
|
|
||||||
with CaptureQueriesContext(connection) as ctx:
|
|
||||||
list(list(Tag.objects.values_list("id", flat=True)))
|
|
||||||
assert len(ctx)
|
|
||||||
|
|
||||||
# Doing the same request again should hit the cache, not the DB
|
|
||||||
with CaptureQueriesContext(connection) as ctx:
|
|
||||||
list(list(Tag.objects.values_list("id", flat=True)))
|
|
||||||
assert not len(ctx)
|
|
||||||
|
|
||||||
# Wait the end of TTL
|
|
||||||
# Redis expire accuracy should be between 0 and 1 ms
|
|
||||||
time.sleep(1.002)
|
|
||||||
|
|
||||||
# Read the DB again. The DB should be hit because the cache has expired
|
|
||||||
with CaptureQueriesContext(connection) as ctx:
|
|
||||||
list(list(Tag.objects.values_list("id", flat=True)))
|
|
||||||
assert len(ctx)
|
|
||||||
|
|
||||||
# Invalidate the cache at the end of test
|
|
||||||
invalidate_db_cache()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db(transaction=True)
|
|
||||||
def test_cache_is_disabled_by_default():
|
|
||||||
cachalot_settings.reload()
|
|
||||||
# Invalidate the cache just in case
|
|
||||||
invalidate_db_cache()
|
|
||||||
|
|
||||||
# Read the table multiple times: the DB should always be hit without cache
|
|
||||||
for _ in range(3):
|
|
||||||
with CaptureQueriesContext(connection) as ctx:
|
|
||||||
list(list(Tag.objects.values_list("id", flat=True)))
|
|
||||||
assert len(ctx)
|
|
||||||
|
|
||||||
# Invalidate the cache at the end of test
|
|
||||||
invalidate_db_cache()
|
|
@ -3,13 +3,10 @@ import os
|
|||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
|
||||||
from celery.schedules import crontab
|
from celery.schedules import crontab
|
||||||
|
|
||||||
from paperless.settings import _ocr_to_dateparser_languages
|
|
||||||
from paperless.settings import _parse_base_paths
|
from paperless.settings import _parse_base_paths
|
||||||
from paperless.settings import _parse_beat_schedule
|
from paperless.settings import _parse_beat_schedule
|
||||||
from paperless.settings import _parse_dateparser_languages
|
|
||||||
from paperless.settings import _parse_db_settings
|
from paperless.settings import _parse_db_settings
|
||||||
from paperless.settings import _parse_ignore_dates
|
from paperless.settings import _parse_ignore_dates
|
||||||
from paperless.settings import _parse_paperless_url
|
from paperless.settings import _parse_paperless_url
|
||||||
@ -474,50 +471,3 @@ class TestPathSettings(TestCase):
|
|||||||
base_paths = _parse_base_paths()
|
base_paths = _parse_base_paths()
|
||||||
self.assertEqual("/paperless/", base_paths[1]) # BASE_URL
|
self.assertEqual("/paperless/", base_paths[1]) # BASE_URL
|
||||||
self.assertEqual("/foobar/", base_paths[4]) # LOGOUT_REDIRECT_URL
|
self.assertEqual("/foobar/", base_paths[4]) # LOGOUT_REDIRECT_URL
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
("ocr_language", "expected"),
|
|
||||||
[
|
|
||||||
# One language
|
|
||||||
("eng", ["en"]),
|
|
||||||
# Multiple languages
|
|
||||||
("fra+ita+lao", ["fr", "it", "lo"]),
|
|
||||||
# Languages that don't have a two-letter equivalent
|
|
||||||
("fil", ["fil"]),
|
|
||||||
# Languages with a script part supported by dateparser
|
|
||||||
("aze_cyrl+srp_latn", ["az-Cyrl", "sr-Latn"]),
|
|
||||||
# Languages with a script part not supported by dateparser
|
|
||||||
# In this case, default to the language without script
|
|
||||||
("deu_frak", ["de"]),
|
|
||||||
# Traditional and simplified chinese don't have the same name in dateparser,
|
|
||||||
# so they're converted to the general chinese language
|
|
||||||
("chi_tra+chi_sim", ["zh"]),
|
|
||||||
# If a language is not supported by dateparser, fallback to the supported ones
|
|
||||||
("eng+unsupported_language+por", ["en", "pt"]),
|
|
||||||
# If no language is supported, fallback to default
|
|
||||||
("unsupported1+unsupported2", []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_ocr_to_dateparser_languages(ocr_language, expected):
|
|
||||||
assert sorted(_ocr_to_dateparser_languages(ocr_language)) == sorted(expected)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
("languages", "expected"),
|
|
||||||
[
|
|
||||||
("de", ["de"]),
|
|
||||||
("zh", ["zh"]),
|
|
||||||
("fr+en", ["fr", "en"]),
|
|
||||||
# Locales must be supported
|
|
||||||
("en-001+fr-CA", ["en-001", "fr-CA"]),
|
|
||||||
("en-001+fr", ["en-001", "fr"]),
|
|
||||||
# Special case for Chinese: variants seem to miss some dates,
|
|
||||||
# so we always add "zh" as a fallback.
|
|
||||||
("en+zh-Hans-HK", ["en", "zh-Hans-HK", "zh"]),
|
|
||||||
("en+zh-Hans", ["en", "zh-Hans", "zh"]),
|
|
||||||
("en+zh-Hans+zh-Hant", ["en", "zh-Hans", "zh-Hant", "zh"]),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_parser_date_parser_languages(languages, expected):
|
|
||||||
assert sorted(_parse_dateparser_languages(languages)) == sorted(expected)
|
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
def ocr_to_dateparser_languages() -> dict[str, str]:
|
|
||||||
"""
|
|
||||||
Translation map from languages supported by Tesseract OCR
|
|
||||||
to languages supported by dateparser.
|
|
||||||
To add a language, make sure it is supported by both libraries.
|
|
||||||
The ISO 639-2 will help you link a 3-char to 2-char language code.
|
|
||||||
Links:
|
|
||||||
- Tesseract languages: https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html
|
|
||||||
- Python dateparser languages: https://dateparser.readthedocs.io/en/latest/supported_locales.html
|
|
||||||
- ISO 639-2: https://www.loc.gov/standards/iso639-2/php/code_list.php
|
|
||||||
"""
|
|
||||||
# TODO check these Dateparser languages as they are not referenced on the ISO639-2 standard,
|
|
||||||
# so we didn't find the equivalent in Tesseract:
|
|
||||||
# agq, asa, bez, brx, cgg, ckb, dav, dje, dyo, ebu, guz, jgo, jmc, kde, kea, khq, kln,
|
|
||||||
# ksb, ksf, ksh, lag, lkt, lrc, luy, mer, mfe, mgh, mgo, mua, mzn, naq, nmg, nnh, nus,
|
|
||||||
# rof, rwk, saq, sbp, she, ses, shi, teo, twq, tzm, vun, wae, xog, yav, yue
|
|
||||||
return {
|
|
||||||
"afr": "af",
|
|
||||||
"amh": "am",
|
|
||||||
"ara": "ar",
|
|
||||||
"asm": "as",
|
|
||||||
"ast": "ast",
|
|
||||||
"aze": "az",
|
|
||||||
"bel": "be",
|
|
||||||
"bul": "bg",
|
|
||||||
"ben": "bn",
|
|
||||||
"bod": "bo",
|
|
||||||
"bre": "br",
|
|
||||||
"bos": "bs",
|
|
||||||
"cat": "ca",
|
|
||||||
"cher": "chr",
|
|
||||||
"ces": "cs",
|
|
||||||
"cym": "cy",
|
|
||||||
"dan": "da",
|
|
||||||
"deu": "de",
|
|
||||||
"dzo": "dz",
|
|
||||||
"ell": "el",
|
|
||||||
"eng": "en",
|
|
||||||
"epo": "eo",
|
|
||||||
"spa": "es",
|
|
||||||
"est": "et",
|
|
||||||
"eus": "eu",
|
|
||||||
"fas": "fa",
|
|
||||||
"fin": "fi",
|
|
||||||
"fil": "fil",
|
|
||||||
"fao": "fo", # codespell:ignore
|
|
||||||
"fra": "fr",
|
|
||||||
"fry": "fy",
|
|
||||||
"gle": "ga",
|
|
||||||
"gla": "gd",
|
|
||||||
"glg": "gl",
|
|
||||||
"guj": "gu",
|
|
||||||
"heb": "he",
|
|
||||||
"hin": "hi",
|
|
||||||
"hrv": "hr",
|
|
||||||
"hun": "hu",
|
|
||||||
"hye": "hy",
|
|
||||||
"ind": "id",
|
|
||||||
"isl": "is",
|
|
||||||
"ita": "it",
|
|
||||||
"jpn": "ja",
|
|
||||||
"kat": "ka",
|
|
||||||
"kaz": "kk",
|
|
||||||
"khm": "km",
|
|
||||||
"knda": "kn",
|
|
||||||
"kor": "ko",
|
|
||||||
"kir": "ky",
|
|
||||||
"ltz": "lb",
|
|
||||||
"lao": "lo",
|
|
||||||
"lit": "lt",
|
|
||||||
"lav": "lv",
|
|
||||||
"mal": "ml",
|
|
||||||
"mon": "mn",
|
|
||||||
"mar": "mr",
|
|
||||||
"msa": "ms",
|
|
||||||
"mlt": "mt",
|
|
||||||
"mya": "my",
|
|
||||||
"nep": "ne",
|
|
||||||
"nld": "nl",
|
|
||||||
"ori": "or",
|
|
||||||
"pan": "pa",
|
|
||||||
"pol": "pl",
|
|
||||||
"pus": "ps",
|
|
||||||
"por": "pt",
|
|
||||||
"que": "qu",
|
|
||||||
"ron": "ro",
|
|
||||||
"rus": "ru",
|
|
||||||
"sin": "si",
|
|
||||||
"slk": "sk",
|
|
||||||
"slv": "sl",
|
|
||||||
"sqi": "sq",
|
|
||||||
"srp": "sr",
|
|
||||||
"swe": "sv",
|
|
||||||
"swa": "sw",
|
|
||||||
"tam": "ta",
|
|
||||||
"tel": "te", # codespell:ignore
|
|
||||||
"tha": "th", # codespell:ignore
|
|
||||||
"tir": "ti",
|
|
||||||
"tgl": "tl",
|
|
||||||
"ton": "to",
|
|
||||||
"tur": "tr",
|
|
||||||
"uig": "ug",
|
|
||||||
"ukr": "uk",
|
|
||||||
"urd": "ur",
|
|
||||||
"uzb": "uz",
|
|
||||||
"via": "vi",
|
|
||||||
"yid": "yi",
|
|
||||||
"yor": "yo",
|
|
||||||
"chi": "zh",
|
|
||||||
}
|
|
14
uv.lock
generated
14
uv.lock
generated
@ -671,18 +671,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/af/34/47edd758abcb4426953b5ff2fa4dd9956c2304e96160ab1b95c3a1ab6e61/django_auditlog-3.1.2-py3-none-any.whl", hash = "sha256:6432a83fdf4397a726488d101fedcb62daafd6d4b825a0fc4c50e3657f5883cd", size = 37312, upload-time = "2025-04-26T11:01:16.776Z" },
|
{ url = "https://files.pythonhosted.org/packages/af/34/47edd758abcb4426953b5ff2fa4dd9956c2304e96160ab1b95c3a1ab6e61/django_auditlog-3.1.2-py3-none-any.whl", hash = "sha256:6432a83fdf4397a726488d101fedcb62daafd6d4b825a0fc4c50e3657f5883cd", size = 37312, upload-time = "2025-04-26T11:01:16.776Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "django-cachalot"
|
|
||||||
version = "2.8.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/53/1f781e58028a43028d6c799f2eab15eff65e841e3e288d6f2953e36f01a4/django_cachalot-2.8.0.tar.gz", hash = "sha256:30456720ac9f3fabeb90ce898530fe01130c25a1eca911cd016cfaeab251d627", size = 74673 }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9a/05/f5846fd186189ac0a1deddb9c67450c838e5c8ceceb35b5260c61f622599/django_cachalot-2.8.0-py3-none-any.whl", hash = "sha256:315da766a5356c7968318326f7b0579f64571ad909f64cad0601f38153ca4e16", size = 55671 },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-celery-results"
|
name = "django-celery-results"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@ -1904,7 +1892,6 @@ dependencies = [
|
|||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "django-allauth", extra = ["mfa", "socialaccount"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django-allauth", extra = ["mfa", "socialaccount"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "django-auditlog", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django-auditlog", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "django-cachalot", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
{ name = "django-celery-results", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django-celery-results", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "django-compression-middleware", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django-compression-middleware", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "django-cors-headers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django-cors-headers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
@ -2035,7 +2022,6 @@ requires-dist = [
|
|||||||
{ name = "django", specifier = "~=5.1.7" },
|
{ name = "django", specifier = "~=5.1.7" },
|
||||||
{ name = "django-allauth", extras = ["socialaccount", "mfa"], specifier = "~=65.4.0" },
|
{ name = "django-allauth", extras = ["socialaccount", "mfa"], specifier = "~=65.4.0" },
|
||||||
{ name = "django-auditlog", specifier = "~=3.1.2" },
|
{ name = "django-auditlog", specifier = "~=3.1.2" },
|
||||||
{ name = "django-cachalot", specifier = "~=2.8.0" },
|
|
||||||
{ name = "django-celery-results", specifier = "~=2.6.0" },
|
{ name = "django-celery-results", specifier = "~=2.6.0" },
|
||||||
{ name = "django-compression-middleware", specifier = "~=0.5.0" },
|
{ name = "django-compression-middleware", specifier = "~=0.5.0" },
|
||||||
{ name = "django-cors-headers", specifier = "~=4.7.0" },
|
{ name = "django-cors-headers", specifier = "~=4.7.0" },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user