We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] FILENAME_FORMAT_REMOVE_NONE breaks certain storage paths
### Description

While investigating https://github.com/paperless-ngx/paperless-ngx/discussions/4856 I came across the following bug: 
The storage path `XX{correspondent}/{title}` will not work correctly, if the correspondent is missing and  `FILENAME_FORMAT_REMOVE_NONE` is `true`

In other words, the following test will fail, but should not:
```python
    @override_settings(
        FILENAME_FORMAT="XX{correspondent}/{title}",
        FILENAME_FORMAT_REMOVE_NONE=True,
    )
    def test_nested_directory_cleanup2(self):
        document = Document.objects.create(
            title="doc1",
            mime_type="application/pdf",
        )
        document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED
        document.save()

        # Ensure that filename is properly generated
        document.filename = generate_filename(document)
        self.assertEqual(document.filename, "XX/doc1.pdf")
```

### Steps to reproduce

1. Make sure `FILENAME_FORMAT_REMOVE_NONE=true`
2. Create a storage path `XX{correspondent}/{title}`
3. make sure the correspondent is missing
4. Apply the storage path to a document
5. observe that the generated path is `XXtitle.pdf`, not `XX/title.pdf` 

### Webserver logs

```bash
none
```


### Browser logs

_No response_

### Paperless-ngx version

2.2.1

### Host OS

any

### Installation method

Docker - official image

### Browser

_No response_

### Configuration changes

_No response_

### Other

Happy to fix this myself, but I am unsure what the correct approach is. I would usually suggest to use a regex here, but I saw that none are used in that code and I am wondering if there is a reason for this?

### Please confirm the following

- [X] I believe this issue is a bug that affects all users of Paperless-ngx, not something specific to my installation.
- [X] I have already searched for relevant existing issues and discussions before opening this report.
- [X] I have updated the title field above with a concise description.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/documents/file_handling.py`
Content:
```
1 import logging
2 import os
3 from collections import defaultdict
4 from pathlib import PurePath
5 
6 import pathvalidate
7 from django.conf import settings
8 from django.template.defaultfilters import slugify
9 from django.utils import timezone
10 
11 from documents.models import Document
12 
13 logger = logging.getLogger("paperless.filehandling")
14 
15 
16 class defaultdictNoStr(defaultdict):
17     def __str__(self):
18         raise ValueError("Don't use {tags} directly.")
19 
20 
21 def create_source_path_directory(source_path):
22     os.makedirs(os.path.dirname(source_path), exist_ok=True)
23 
24 
25 def delete_empty_directories(directory, root):
26     if not os.path.isdir(directory):
27         return
28 
29     # Go up in the directory hierarchy and try to delete all directories
30     directory = os.path.normpath(directory)
31     root = os.path.normpath(root)
32 
33     if not directory.startswith(root + os.path.sep):
34         # don't do anything outside our originals folder.
35 
36         # append os.path.set so that we avoid these cases:
37         #   directory = /home/originals2/test
38         #   root = /home/originals ("/" gets appended and startswith fails)
39         return
40 
41     while directory != root:
42         if not os.listdir(directory):
43             # it's empty
44             try:
45                 os.rmdir(directory)
46             except OSError:
47                 # whatever. empty directories aren't that bad anyway.
48                 return
49         else:
50             # it's not empty.
51             return
52 
53         # go one level up
54         directory = os.path.normpath(os.path.dirname(directory))
55 
56 
57 def many_to_dictionary(field):
58     # Converts ManyToManyField to dictionary by assuming, that field
59     # entries contain an _ or - which will be used as a delimiter
60     mydictionary = dict()
61 
62     for index, t in enumerate(field.all()):
63         # Populate tag names by index
64         mydictionary[index] = slugify(t.name)
65 
66         # Find delimiter
67         delimiter = t.name.find("_")
68 
69         if delimiter == -1:
70             delimiter = t.name.find("-")
71 
72         if delimiter == -1:
73             continue
74 
75         key = t.name[:delimiter]
76         value = t.name[delimiter + 1 :]
77 
78         mydictionary[slugify(key)] = slugify(value)
79 
80     return mydictionary
81 
82 
83 def generate_unique_filename(doc, archive_filename=False):
84     """
85     Generates a unique filename for doc in settings.ORIGINALS_DIR.
86 
87     The returned filename is guaranteed to be either the current filename
88     of the document if unchanged, or a new filename that does not correspondent
89     to any existing files. The function will append _01, _02, etc to the
90     filename before the extension to avoid conflicts.
91 
92     If archive_filename is True, return a unique archive filename instead.
93 
94     """
95     if archive_filename:
96         old_filename = doc.archive_filename
97         root = settings.ARCHIVE_DIR
98     else:
99         old_filename = doc.filename
100         root = settings.ORIGINALS_DIR
101 
102     # If generating archive filenames, try to make a name that is similar to
103     # the original filename first.
104 
105     if archive_filename and doc.filename:
106         new_filename = os.path.splitext(doc.filename)[0] + ".pdf"
107         if new_filename == old_filename or not os.path.exists(
108             os.path.join(root, new_filename),
109         ):
110             return new_filename
111 
112     counter = 0
113 
114     while True:
115         new_filename = generate_filename(
116             doc,
117             counter,
118             archive_filename=archive_filename,
119         )
120         if new_filename == old_filename:
121             # still the same as before.
122             return new_filename
123 
124         if os.path.exists(os.path.join(root, new_filename)):
125             counter += 1
126         else:
127             return new_filename
128 
129 
130 def generate_filename(
131     doc: Document,
132     counter=0,
133     append_gpg=True,
134     archive_filename=False,
135 ):
136     path = ""
137     filename_format = settings.FILENAME_FORMAT
138 
139     try:
140         if doc.storage_path is not None:
141             logger.debug(
142                 f"Document has storage_path {doc.storage_path.id} "
143                 f"({doc.storage_path.path}) set",
144             )
145             filename_format = doc.storage_path.path
146 
147         if filename_format is not None:
148             tags = defaultdictNoStr(
149                 lambda: slugify(None),
150                 many_to_dictionary(doc.tags),
151             )
152 
153             tag_list = pathvalidate.sanitize_filename(
154                 ",".join(
155                     sorted(tag.name for tag in doc.tags.all()),
156                 ),
157                 replacement_text="-",
158             )
159 
160             no_value_default = "-none-"
161 
162             if doc.correspondent:
163                 correspondent = pathvalidate.sanitize_filename(
164                     doc.correspondent.name,
165                     replacement_text="-",
166                 )
167             else:
168                 correspondent = no_value_default
169 
170             if doc.document_type:
171                 document_type = pathvalidate.sanitize_filename(
172                     doc.document_type.name,
173                     replacement_text="-",
174                 )
175             else:
176                 document_type = no_value_default
177 
178             if doc.archive_serial_number:
179                 asn = str(doc.archive_serial_number)
180             else:
181                 asn = no_value_default
182 
183             if doc.owner is not None:
184                 owner_username_str = str(doc.owner.username)
185             else:
186                 owner_username_str = no_value_default
187 
188             if doc.original_filename is not None:
189                 # No extension
190                 original_name = PurePath(doc.original_filename).with_suffix("").name
191             else:
192                 original_name = no_value_default
193 
194             # Convert UTC database datetime to localized date
195             local_added = timezone.localdate(doc.added)
196             local_created = timezone.localdate(doc.created)
197 
198             path = filename_format.format(
199                 title=pathvalidate.sanitize_filename(doc.title, replacement_text="-"),
200                 correspondent=correspondent,
201                 document_type=document_type,
202                 created=local_created.isoformat(),
203                 created_year=local_created.strftime("%Y"),
204                 created_year_short=local_created.strftime("%y"),
205                 created_month=local_created.strftime("%m"),
206                 created_month_name=local_created.strftime("%B"),
207                 created_month_name_short=local_created.strftime("%b"),
208                 created_day=local_created.strftime("%d"),
209                 added=local_added.isoformat(),
210                 added_year=local_added.strftime("%Y"),
211                 added_year_short=local_added.strftime("%y"),
212                 added_month=local_added.strftime("%m"),
213                 added_month_name=local_added.strftime("%B"),
214                 added_month_name_short=local_added.strftime("%b"),
215                 added_day=local_added.strftime("%d"),
216                 asn=asn,
217                 tags=tags,
218                 tag_list=tag_list,
219                 owner_username=owner_username_str,
220                 original_name=original_name,
221                 doc_pk=f"{doc.pk:07}",
222             ).strip()
223 
224             if settings.FILENAME_FORMAT_REMOVE_NONE:
225                 path = path.replace("-none-/", "")  # remove empty directories
226                 path = path.replace(" -none-", "")  # remove when spaced, with space
227                 path = path.replace("-none-", "")  # remove rest of the occurences
228 
229             path = path.replace("-none-", "none")  # backward compatibility
230             path = path.strip(os.sep)
231 
232     except (ValueError, KeyError, IndexError):
233         logger.warning(
234             f"Invalid filename_format '{filename_format}', falling back to default",
235         )
236 
237     counter_str = f"_{counter:02}" if counter else ""
238 
239     filetype_str = ".pdf" if archive_filename else doc.file_type
240 
241     if len(path) > 0:
242         filename = f"{path}{counter_str}{filetype_str}"
243     else:
244         filename = f"{doc.pk:07}{counter_str}{filetype_str}"
245 
246     # Append .gpg for encrypted files
247     if append_gpg and doc.storage_type == doc.STORAGE_TYPE_GPG:
248         filename += ".gpg"
249 
250     return filename
251
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/documents/file_handling.py b/src/documents/file_handling.py
--- a/src/documents/file_handling.py
+++ b/src/documents/file_handling.py
@@ -222,7 +222,7 @@
             ).strip()
 
             if settings.FILENAME_FORMAT_REMOVE_NONE:
-                path = path.replace("-none-/", "")  # remove empty directories
+                path = path.replace("/-none-/", "/")  # remove empty directories
                 path = path.replace(" -none-", "")  # remove when spaced, with space
                 path = path.replace("-none-", "")  # remove rest of the occurences

{"golden_diff": "diff --git a/src/documents/file_handling.py b/src/documents/file_handling.py\n--- a/src/documents/file_handling.py\n+++ b/src/documents/file_handling.py\n@@ -222,7 +222,7 @@\n             ).strip()\n \n             if settings.FILENAME_FORMAT_REMOVE_NONE:\n-                path = path.replace(\"-none-/\", \"\")  # remove empty directories\n+                path = path.replace(\"/-none-/\", \"/\")  # remove empty directories\n                 path = path.replace(\" -none-\", \"\")  # remove when spaced, with space\n                 path = path.replace(\"-none-\", \"\")  # remove rest of the occurences\n", "issue": "[BUG] FILENAME_FORMAT_REMOVE_NONE breaks certain storage paths\n### Description\n\nWhile investigating https://github.com/paperless-ngx/paperless-ngx/discussions/4856 I came across the following bug: \r\nThe storage path `XX{correspondent}/{title}` will not work correctly, if the correspondent is missing and  `FILENAME_FORMAT_REMOVE_NONE` is `true`\r\n\r\nIn other words, the following test will fail, but should not:\r\n```python\r\n    @override_settings(\r\n        FILENAME_FORMAT=\"XX{correspondent}/{title}\",\r\n        FILENAME_FORMAT_REMOVE_NONE=True,\r\n    )\r\n    def test_nested_directory_cleanup2(self):\r\n        document = Document.objects.create(\r\n            title=\"doc1\",\r\n            mime_type=\"application/pdf\",\r\n        )\r\n        document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED\r\n        document.save()\r\n\r\n        # Ensure that filename is properly generated\r\n        document.filename = generate_filename(document)\r\n        self.assertEqual(document.filename, \"XX/doc1.pdf\")\r\n```\n\n### Steps to reproduce\n\n1. Make sure `FILENAME_FORMAT_REMOVE_NONE=true`\r\n2. Create a storage path `XX{correspondent}/{title}`\r\n3. make sure the correspondent is missing\r\n4. Apply the storage path to a document\r\n5. observe that the generated path is `XXtitle.pdf`, not `XX/title.pdf` \n\n### Webserver logs\n\n```bash\nnone\n```\n\n\n### Browser logs\n\n_No response_\n\n### Paperless-ngx version\n\n2.2.1\n\n### Host OS\n\nany\n\n### Installation method\n\nDocker - official image\n\n### Browser\n\n_No response_\n\n### Configuration changes\n\n_No response_\n\n### Other\n\nHappy to fix this myself, but I am unsure what the correct approach is. I would usually suggest to use a regex here, but I saw that none are used in that code and I am wondering if there is a reason for this?\n\n### Please confirm the following\n\n- [X] I believe this issue is a bug that affects all users of Paperless-ngx, not something specific to my installation.\n- [X] I have already searched for relevant existing issues and discussions before opening this report.\n- [X] I have updated the title field above with a concise description.\n", "before_files": [{"content": "import logging\nimport os\nfrom collections import defaultdict\nfrom pathlib import PurePath\n\nimport pathvalidate\nfrom django.conf import settings\nfrom django.template.defaultfilters import slugify\nfrom django.utils import timezone\n\nfrom documents.models import Document\n\nlogger = logging.getLogger(\"paperless.filehandling\")\n\n\nclass defaultdictNoStr(defaultdict):\n    def __str__(self):\n        raise ValueError(\"Don't use {tags} directly.\")\n\n\ndef create_source_path_directory(source_path):\n    os.makedirs(os.path.dirname(source_path), exist_ok=True)\n\n\ndef delete_empty_directories(directory, root):\n    if not os.path.isdir(directory):\n        return\n\n    # Go up in the directory hierarchy and try to delete all directories\n    directory = os.path.normpath(directory)\n    root = os.path.normpath(root)\n\n    if not directory.startswith(root + os.path.sep):\n        # don't do anything outside our originals folder.\n\n        # append os.path.set so that we avoid these cases:\n        #   directory = /home/originals2/test\n        #   root = /home/originals (\"/\" gets appended and startswith fails)\n        return\n\n    while directory != root:\n        if not os.listdir(directory):\n            # it's empty\n            try:\n                os.rmdir(directory)\n            except OSError:\n                # whatever. empty directories aren't that bad anyway.\n                return\n        else:\n            # it's not empty.\n            return\n\n        # go one level up\n        directory = os.path.normpath(os.path.dirname(directory))\n\n\ndef many_to_dictionary(field):\n    # Converts ManyToManyField to dictionary by assuming, that field\n    # entries contain an _ or - which will be used as a delimiter\n    mydictionary = dict()\n\n    for index, t in enumerate(field.all()):\n        # Populate tag names by index\n        mydictionary[index] = slugify(t.name)\n\n        # Find delimiter\n        delimiter = t.name.find(\"_\")\n\n        if delimiter == -1:\n            delimiter = t.name.find(\"-\")\n\n        if delimiter == -1:\n            continue\n\n        key = t.name[:delimiter]\n        value = t.name[delimiter + 1 :]\n\n        mydictionary[slugify(key)] = slugify(value)\n\n    return mydictionary\n\n\ndef generate_unique_filename(doc, archive_filename=False):\n    \"\"\"\n    Generates a unique filename for doc in settings.ORIGINALS_DIR.\n\n    The returned filename is guaranteed to be either the current filename\n    of the document if unchanged, or a new filename that does not correspondent\n    to any existing files. The function will append _01, _02, etc to the\n    filename before the extension to avoid conflicts.\n\n    If archive_filename is True, return a unique archive filename instead.\n\n    \"\"\"\n    if archive_filename:\n        old_filename = doc.archive_filename\n        root = settings.ARCHIVE_DIR\n    else:\n        old_filename = doc.filename\n        root = settings.ORIGINALS_DIR\n\n    # If generating archive filenames, try to make a name that is similar to\n    # the original filename first.\n\n    if archive_filename and doc.filename:\n        new_filename = os.path.splitext(doc.filename)[0] + \".pdf\"\n        if new_filename == old_filename or not os.path.exists(\n            os.path.join(root, new_filename),\n        ):\n            return new_filename\n\n    counter = 0\n\n    while True:\n        new_filename = generate_filename(\n            doc,\n            counter,\n            archive_filename=archive_filename,\n        )\n        if new_filename == old_filename:\n            # still the same as before.\n            return new_filename\n\n        if os.path.exists(os.path.join(root, new_filename)):\n            counter += 1\n        else:\n            return new_filename\n\n\ndef generate_filename(\n    doc: Document,\n    counter=0,\n    append_gpg=True,\n    archive_filename=False,\n):\n    path = \"\"\n    filename_format = settings.FILENAME_FORMAT\n\n    try:\n        if doc.storage_path is not None:\n            logger.debug(\n                f\"Document has storage_path {doc.storage_path.id} \"\n                f\"({doc.storage_path.path}) set\",\n            )\n            filename_format = doc.storage_path.path\n\n        if filename_format is not None:\n            tags = defaultdictNoStr(\n                lambda: slugify(None),\n                many_to_dictionary(doc.tags),\n            )\n\n            tag_list = pathvalidate.sanitize_filename(\n                \",\".join(\n                    sorted(tag.name for tag in doc.tags.all()),\n                ),\n                replacement_text=\"-\",\n            )\n\n            no_value_default = \"-none-\"\n\n            if doc.correspondent:\n                correspondent = pathvalidate.sanitize_filename(\n                    doc.correspondent.name,\n                    replacement_text=\"-\",\n                )\n            else:\n                correspondent = no_value_default\n\n            if doc.document_type:\n                document_type = pathvalidate.sanitize_filename(\n                    doc.document_type.name,\n                    replacement_text=\"-\",\n                )\n            else:\n                document_type = no_value_default\n\n            if doc.archive_serial_number:\n                asn = str(doc.archive_serial_number)\n            else:\n                asn = no_value_default\n\n            if doc.owner is not None:\n                owner_username_str = str(doc.owner.username)\n            else:\n                owner_username_str = no_value_default\n\n            if doc.original_filename is not None:\n                # No extension\n                original_name = PurePath(doc.original_filename).with_suffix(\"\").name\n            else:\n                original_name = no_value_default\n\n            # Convert UTC database datetime to localized date\n            local_added = timezone.localdate(doc.added)\n            local_created = timezone.localdate(doc.created)\n\n            path = filename_format.format(\n                title=pathvalidate.sanitize_filename(doc.title, replacement_text=\"-\"),\n                correspondent=correspondent,\n                document_type=document_type,\n                created=local_created.isoformat(),\n                created_year=local_created.strftime(\"%Y\"),\n                created_year_short=local_created.strftime(\"%y\"),\n                created_month=local_created.strftime(\"%m\"),\n                created_month_name=local_created.strftime(\"%B\"),\n                created_month_name_short=local_created.strftime(\"%b\"),\n                created_day=local_created.strftime(\"%d\"),\n                added=local_added.isoformat(),\n                added_year=local_added.strftime(\"%Y\"),\n                added_year_short=local_added.strftime(\"%y\"),\n                added_month=local_added.strftime(\"%m\"),\n                added_month_name=local_added.strftime(\"%B\"),\n                added_month_name_short=local_added.strftime(\"%b\"),\n                added_day=local_added.strftime(\"%d\"),\n                asn=asn,\n                tags=tags,\n                tag_list=tag_list,\n                owner_username=owner_username_str,\n                original_name=original_name,\n                doc_pk=f\"{doc.pk:07}\",\n            ).strip()\n\n            if settings.FILENAME_FORMAT_REMOVE_NONE:\n                path = path.replace(\"-none-/\", \"\")  # remove empty directories\n                path = path.replace(\" -none-\", \"\")  # remove when spaced, with space\n                path = path.replace(\"-none-\", \"\")  # remove rest of the occurences\n\n            path = path.replace(\"-none-\", \"none\")  # backward compatibility\n            path = path.strip(os.sep)\n\n    except (ValueError, KeyError, IndexError):\n        logger.warning(\n            f\"Invalid filename_format '{filename_format}', falling back to default\",\n        )\n\n    counter_str = f\"_{counter:02}\" if counter else \"\"\n\n    filetype_str = \".pdf\" if archive_filename else doc.file_type\n\n    if len(path) > 0:\n        filename = f\"{path}{counter_str}{filetype_str}\"\n    else:\n        filename = f\"{doc.pk:07}{counter_str}{filetype_str}\"\n\n    # Append .gpg for encrypted files\n    if append_gpg and doc.storage_type == doc.STORAGE_TYPE_GPG:\n        filename += \".gpg\"\n\n    return filename\n", "path": "src/documents/file_handling.py"}], "after_files": [{"content": "import logging\nimport os\nfrom collections import defaultdict\nfrom pathlib import PurePath\n\nimport pathvalidate\nfrom django.conf import settings\nfrom django.template.defaultfilters import slugify\nfrom django.utils import timezone\n\nfrom documents.models import Document\n\nlogger = logging.getLogger(\"paperless.filehandling\")\n\n\nclass defaultdictNoStr(defaultdict):\n    def __str__(self):\n        raise ValueError(\"Don't use {tags} directly.\")\n\n\ndef create_source_path_directory(source_path):\n    os.makedirs(os.path.dirname(source_path), exist_ok=True)\n\n\ndef delete_empty_directories(directory, root):\n    if not os.path.isdir(directory):\n        return\n\n    # Go up in the directory hierarchy and try to delete all directories\n    directory = os.path.normpath(directory)\n    root = os.path.normpath(root)\n\n    if not directory.startswith(root + os.path.sep):\n        # don't do anything outside our originals folder.\n\n        # append os.path.set so that we avoid these cases:\n        #   directory = /home/originals2/test\n        #   root = /home/originals (\"/\" gets appended and startswith fails)\n        return\n\n    while directory != root:\n        if not os.listdir(directory):\n            # it's empty\n            try:\n                os.rmdir(directory)\n            except OSError:\n                # whatever. empty directories aren't that bad anyway.\n                return\n        else:\n            # it's not empty.\n            return\n\n        # go one level up\n        directory = os.path.normpath(os.path.dirname(directory))\n\n\ndef many_to_dictionary(field):\n    # Converts ManyToManyField to dictionary by assuming, that field\n    # entries contain an _ or - which will be used as a delimiter\n    mydictionary = dict()\n\n    for index, t in enumerate(field.all()):\n        # Populate tag names by index\n        mydictionary[index] = slugify(t.name)\n\n        # Find delimiter\n        delimiter = t.name.find(\"_\")\n\n        if delimiter == -1:\n            delimiter = t.name.find(\"-\")\n\n        if delimiter == -1:\n            continue\n\n        key = t.name[:delimiter]\n        value = t.name[delimiter + 1 :]\n\n        mydictionary[slugify(key)] = slugify(value)\n\n    return mydictionary\n\n\ndef generate_unique_filename(doc, archive_filename=False):\n    \"\"\"\n    Generates a unique filename for doc in settings.ORIGINALS_DIR.\n\n    The returned filename is guaranteed to be either the current filename\n    of the document if unchanged, or a new filename that does not correspondent\n    to any existing files. The function will append _01, _02, etc to the\n    filename before the extension to avoid conflicts.\n\n    If archive_filename is True, return a unique archive filename instead.\n\n    \"\"\"\n    if archive_filename:\n        old_filename = doc.archive_filename\n        root = settings.ARCHIVE_DIR\n    else:\n        old_filename = doc.filename\n        root = settings.ORIGINALS_DIR\n\n    # If generating archive filenames, try to make a name that is similar to\n    # the original filename first.\n\n    if archive_filename and doc.filename:\n        new_filename = os.path.splitext(doc.filename)[0] + \".pdf\"\n        if new_filename == old_filename or not os.path.exists(\n            os.path.join(root, new_filename),\n        ):\n            return new_filename\n\n    counter = 0\n\n    while True:\n        new_filename = generate_filename(\n            doc,\n            counter,\n            archive_filename=archive_filename,\n        )\n        if new_filename == old_filename:\n            # still the same as before.\n            return new_filename\n\n        if os.path.exists(os.path.join(root, new_filename)):\n            counter += 1\n        else:\n            return new_filename\n\n\ndef generate_filename(\n    doc: Document,\n    counter=0,\n    append_gpg=True,\n    archive_filename=False,\n):\n    path = \"\"\n    filename_format = settings.FILENAME_FORMAT\n\n    try:\n        if doc.storage_path is not None:\n            logger.debug(\n                f\"Document has storage_path {doc.storage_path.id} \"\n                f\"({doc.storage_path.path}) set\",\n            )\n            filename_format = doc.storage_path.path\n\n        if filename_format is not None:\n            tags = defaultdictNoStr(\n                lambda: slugify(None),\n                many_to_dictionary(doc.tags),\n            )\n\n            tag_list = pathvalidate.sanitize_filename(\n                \",\".join(\n                    sorted(tag.name for tag in doc.tags.all()),\n                ),\n                replacement_text=\"-\",\n            )\n\n            no_value_default = \"-none-\"\n\n            if doc.correspondent:\n                correspondent = pathvalidate.sanitize_filename(\n                    doc.correspondent.name,\n                    replacement_text=\"-\",\n                )\n            else:\n                correspondent = no_value_default\n\n            if doc.document_type:\n                document_type = pathvalidate.sanitize_filename(\n                    doc.document_type.name,\n                    replacement_text=\"-\",\n                )\n            else:\n                document_type = no_value_default\n\n            if doc.archive_serial_number:\n                asn = str(doc.archive_serial_number)\n            else:\n                asn = no_value_default\n\n            if doc.owner is not None:\n                owner_username_str = str(doc.owner.username)\n            else:\n                owner_username_str = no_value_default\n\n            if doc.original_filename is not None:\n                # No extension\n                original_name = PurePath(doc.original_filename).with_suffix(\"\").name\n            else:\n                original_name = no_value_default\n\n            # Convert UTC database datetime to localized date\n            local_added = timezone.localdate(doc.added)\n            local_created = timezone.localdate(doc.created)\n\n            path = filename_format.format(\n                title=pathvalidate.sanitize_filename(doc.title, replacement_text=\"-\"),\n                correspondent=correspondent,\n                document_type=document_type,\n                created=local_created.isoformat(),\n                created_year=local_created.strftime(\"%Y\"),\n                created_year_short=local_created.strftime(\"%y\"),\n                created_month=local_created.strftime(\"%m\"),\n                created_month_name=local_created.strftime(\"%B\"),\n                created_month_name_short=local_created.strftime(\"%b\"),\n                created_day=local_created.strftime(\"%d\"),\n                added=local_added.isoformat(),\n                added_year=local_added.strftime(\"%Y\"),\n                added_year_short=local_added.strftime(\"%y\"),\n                added_month=local_added.strftime(\"%m\"),\n                added_month_name=local_added.strftime(\"%B\"),\n                added_month_name_short=local_added.strftime(\"%b\"),\n                added_day=local_added.strftime(\"%d\"),\n                asn=asn,\n                tags=tags,\n                tag_list=tag_list,\n                owner_username=owner_username_str,\n                original_name=original_name,\n                doc_pk=f\"{doc.pk:07}\",\n            ).strip()\n\n            if settings.FILENAME_FORMAT_REMOVE_NONE:\n                path = path.replace(\"/-none-/\", \"/\")  # remove empty directories\n                path = path.replace(\" -none-\", \"\")  # remove when spaced, with space\n                path = path.replace(\"-none-\", \"\")  # remove rest of the occurences\n\n            path = path.replace(\"-none-\", \"none\")  # backward compatibility\n            path = path.strip(os.sep)\n\n    except (ValueError, KeyError, IndexError):\n        logger.warning(\n            f\"Invalid filename_format '{filename_format}', falling back to default\",\n        )\n\n    counter_str = f\"_{counter:02}\" if counter else \"\"\n\n    filetype_str = \".pdf\" if archive_filename else doc.file_type\n\n    if len(path) > 0:\n        filename = f\"{path}{counter_str}{filetype_str}\"\n    else:\n        filename = f\"{doc.pk:07}{counter_str}{filetype_str}\"\n\n    # Append .gpg for encrypted files\n    if append_gpg and doc.storage_type == doc.STORAGE_TYPE_GPG:\n        filename += \".gpg\"\n\n    return filename\n", "path": "src/documents/file_handling.py"}]}