Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow extension in file_path to take a list of allowed extensions, or empty for "no extension" #1966

Merged
merged 4 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions faker/providers/file/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import re
import string

from collections import OrderedDict
from typing import Dict, Optional
from typing import Dict, List, Optional, Union

from .. import BaseProvider, ElementsType

Expand Down Expand Up @@ -257,7 +258,7 @@ def file_path(
self,
depth: int = 1,
category: Optional[str] = None,
extension: Optional[str] = None,
extension: Optional[Union[str, List[str]]] = None,
absolute: Optional[bool] = True,
) -> str:
"""Generate an pathname to a file.
Expand All @@ -269,12 +270,28 @@ def file_path(
If ``absolute`` is ``True`` (default), the generated path starts with
``/`` and is absolute. Otherwise, the generated path is relative.

If used, ``extension`` can be either a string, forcing that extension, a
list of strings (one will be picked at random), or an empty list (the
path will have no extension). Default behaviour is the same as |file_name|

:sample: size=10
:sample: depth=3
:sample: depth=5, category='video'
:sample: depth=5, category='video', extension='abcdef'
:sample: extension=[]
:sample: extension=["a", "bc", "def"]
"""
no_extension = False
if isinstance(extension, list):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like for extension to also possibly a tuple.
We could type the argument with extension: Optional[Sequence[str]], and then check for not isinstance(extension, str) instead:

Suggested change
if isinstance(extension, list):
if not isinstance(extension, str):

I would also change the behavior of file_name, so that if the empty string is passed, no extension and no dot are added. This would allow us to pass "" to file_name and avoid stripping it out later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - also checking for None

if extension:
extension = self.random_element(extension)
else:
extension = None
no_extension = True

file: str = self.file_name(category, extension)
if no_extension:
file = re.sub(r"\.[^/]+$", "", file)
gotofritz marked this conversation as resolved.
Show resolved Hide resolved
path: str = f"/{file}"
for _ in range(0, depth):
path = f"/{self.generator.word()}{path}"
Expand Down
8 changes: 6 additions & 2 deletions tests/providers/test_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ def test_file_path(self):
file_path = self.fake.file_path(depth=3)
assert re.search(r"\/\w+\/\w+\/\w+\.\w+", file_path)
file_path = self.fake.file_path(extension="pdf")
assert re.search(r"\/\w+\/\w+\.pdf", file_path)
assert re.search(r"\/\w+\/\w+\.pdf$", file_path)
file_path = self.fake.file_path(extension=["a", "bc", "def", "ghij", "klmno"])
assert re.search(r"\/\w+\/\w+\.(a|bc|def|ghij|klmno)$", file_path)
file_path = self.fake.file_path(extension=[])
assert re.search(r"\/\w+\/\w+$", file_path)
file_path = self.fake.file_path(category="image")
assert re.search(r"\/\w+\/\w+\.(bmp|gif|jpeg|jpg|png|tiff)", file_path)
assert re.search(r"\/\w+\/\w+\.(bmp|gif|jpeg|jpg|png|tiff)$", file_path)

def test_unix_device(self):
reg_device = re.compile(r"^/dev/(vd|sd|xvd)[a-z]$")
Expand Down