Skip to content

Commit

Permalink
Allow extension in file_path to take a list of allowed extensions, …
Browse files Browse the repository at this point in the history
…or empty for "no extension". Remove dot from `file_name` when `extention` is the empty string (#1966)
  • Loading branch information
gotofritz committed Dec 29, 2023
1 parent 6961ade commit 58f49e0
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 15 deletions.
45 changes: 32 additions & 13 deletions faker/providers/file/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import string

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

from .. import BaseProvider, ElementsType

Expand Down Expand Up @@ -223,21 +223,24 @@ def mime_type(self, category: Optional[str] = None) -> str:
def file_name(self, category: Optional[str] = None, extension: Optional[str] = None) -> str:
"""Generate a random file name with extension.
If ``extension`` is ``None``, a random extension will be created under
the hood using |file_extension| with the specified ``category``. If a
value for ``extension`` is provided, the value will be used instead,
and ``category`` will be ignored. The actual name part itself is
generated using |word|.
If ``extension`` is ``None``, a random extension will be created
under the hood using |file_extension| with the specified
``category``. If a value for ``extension`` is provided, the
value will be used instead, and ``category`` will be ignored.
The actual name part itself is generated using |word|. If
extension is an empty string then no extension will be added,
and file_name will be the same as |word|.
:sample: size=10
:sample: category='audio'
:sample: extension='abcdef'
:sample: category='audio', extension='abcdef'
:sample: extension=''
"""
if extension is None:
extension = self.file_extension(category)
filename: str = self.generator.word()
return f"{filename}.{extension}"
return f"{filename}.{extension}" if extension else filename

def file_extension(self, category: Optional[str] = None) -> str:
"""Generate a file extension under the specified ``category``.
Expand All @@ -257,23 +260,39 @@ def file_path(
self,
depth: int = 1,
category: Optional[str] = None,
extension: Optional[str] = None,
extension: Optional[Union[str, Sequence[str]]] = None,
absolute: Optional[bool] = True,
) -> str:
"""Generate an pathname to a file.
This method uses |file_name| under the hood to generate the file name
itself, and ``depth`` controls the depth of the directory path, and
|word| is used under the hood to generate the different directory names.
This method uses |file_name| under the hood to generate the file
name itself, and ``depth`` controls the depth of the directory
path, and |word| is used under the hood to generate the
different directory names.
If ``absolute`` is ``True`` (default), the generated path starts with
``/`` and is absolute. Otherwise, the generated path is relative.
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 sequence of strings (one will be picked at random),
or an empty sequence (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=''
:sample: extension=["a", "bc", "def"]
"""
if extension is not None and not isinstance(extension, str):
if len(extension):
extension = self.random_element(extension)
else:
extension = ""

file: str = self.file_name(category, extension)
path: str = f"/{file}"
for _ in range(0, depth):
Expand Down
27 changes: 25 additions & 2 deletions tests/providers/test_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ def setUp(self):
self.fake = Faker()
Faker.seed(0)

def test_file_name(self):
for _ in range(100):
file_name = self.fake.file_name()
assert re.search(r"\w+\.\w+", file_name)
file_name = self.fake.file_name(extension=None)
assert re.search(r"\w+\.\w+", file_name)
file_name = self.fake.file_name(extension="pdf")
assert re.search(r"\w+\.pdf$", file_name)
file_name = self.fake.file_name(category="image")
assert re.search(r"\w+\.(bmp|gif|jpeg|jpg|png|tiff)$", file_name)
file_name = self.fake.file_name(category="image", extension="abcdef")
assert re.search(r"\w+\.abcdef$", file_name)
file_name = self.fake.file_name(extension="")
assert re.search(r"\w+$", file_name)

def test_file_path(self):
for _ in range(100):
file_path = self.fake.file_path()
Expand All @@ -20,9 +35,17 @@ 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=None)
assert re.search(r"\/\w+\/\w+\.\w+", file_path)
file_path = self.fake.file_path(extension="")
assert re.search(r"\/\w+\/\w+$", 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

0 comments on commit 58f49e0

Please sign in to comment.