from typing import Callable, Optional, Union, overload
from faker import Faker
from faker.generator import Generator
from faker.providers import BaseProvider
from faker.providers.python import Provider
from ..base import DEFAULT_FORMAT_FUNC, BytesValue, FileMixin, StringValue
from ..registry import FILE_REGISTRY
from ..storages.base import BaseStorage
from ..storages.filesystem import FileSystemStorage
__author__ = "Artur Barseghyan <artur.barseghyan@gmail.com>"
__copyright__ = "2022-2023 Artur Barseghyan"
__license__ = "MIT"
__all__ = ("GenericFileProvider",)
[docs]class GenericFileProvider(BaseProvider, FileMixin):
"""Generic file provider.
Usage example:
.. code-block:: python
from faker import Faker
from faker_file.providers.generic_file import GenericFileProvider
FAKER = Faker()
FAKER.add_provider(GenericFileProvider)
file = FAKER.generic_file(
content="<html><body><p>{{text}}</p></body></html>",
extension="html",
)
Usage example with options:
.. code-block:: python
file = FAKER.generic_file(
content="<html><body><p>{{text}}</p></body></html>",
extension="html",
prefix="zzz",
)
Usage example with `FileSystemStorage` storage (for `Django`):
.. code-block:: python
from django.conf import settings
from faker_file.storages.filesystem import FileSystemStorage
file = FAKER.generic_file(
content="<html><body><p>{{text}}</p></body></html>",
extension="html",
basename="index",
storage=FileSystemStorage(
root_path=settings.MEDIA_ROOT,
rel_path="tmp",
),
)
Usage example with AWS S3 storage:
.. code-block:: python
from faker_file.storages.aws_s3 import AWSS3Storage
file = FAKER.generic_file(
storage=AWSS3Storage(bucket_name="My-test-bucket"),
content="<html><body><p>{{text}}</p></body></html>",
extension="html",
)
"""
extension: str = None
@overload
def generic_file(
self: "GenericFileProvider",
content: Union[bytes, str],
extension: str,
storage: Optional[BaseStorage] = None,
basename: Optional[str] = None,
prefix: Optional[str] = None,
format_func: Callable[
[Union[Faker, Generator, Provider], str], str
] = DEFAULT_FORMAT_FUNC,
raw: bool = True,
**kwargs,
) -> BytesValue:
...
@overload
def generic_file(
self: "GenericFileProvider",
content: Union[bytes, str],
extension: str,
storage: Optional[BaseStorage] = None,
basename: Optional[str] = None,
prefix: Optional[str] = None,
format_func: Callable[
[Union[Faker, Generator, Provider], str], str
] = DEFAULT_FORMAT_FUNC,
**kwargs,
) -> StringValue:
...
[docs] def generic_file(
self: "GenericFileProvider",
content: Union[bytes, str],
extension: str,
storage: Optional[BaseStorage] = None,
basename: Optional[str] = None,
prefix: Optional[str] = None,
format_func: Callable[
[Union[Faker, Generator, Provider], str], str
] = DEFAULT_FORMAT_FUNC,
raw: bool = False,
**kwargs,
) -> Union[BytesValue, StringValue]:
"""Generate a generic file with given content.
:param content: File content. If given, used as is.
:param extension: File extension.
:param storage: Storage class. Defaults to `FileSystemStorage`.
:param basename: File basename (without extension).
:param prefix: File name prefix.
:param format_func: Callable responsible for formatting template
strings.
:param raw: If set to True, return `BytesValue` (binary content of
the file). Otherwise, return `StringValue` (path to the saved
file).
:return: Relative path (from root directory) of the generated file
or raw content of the file.
"""
self.extension = extension
# Generic
if storage is None:
storage = FileSystemStorage()
filename = storage.generate_filename(
extension=self.extension,
prefix=prefix,
basename=basename,
)
if self.generator is None:
self.generator = Faker()
data = {"content": content, "filename": filename, "storage": storage}
if raw:
if isinstance(content, bytes):
raw_content = BytesValue(content)
else:
raw_content = BytesValue(
format_func(self.generator, content).encode()
)
raw_content.data = data
return raw_content
if isinstance(content, bytes):
storage.write_bytes(filename, content)
else:
storage.write_text(
filename,
format_func(self.generator, content),
)
# Generic
file_name = StringValue(storage.relpath(filename))
file_name.data = data
FILE_REGISTRY.add(file_name)
return file_name