• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

barseghyanartur / faker-file / 4866110878

pending completion
4866110878

push

github

Artur Barseghyan
Add explanations

1429 of 1431 relevant lines covered (99.86%)

5.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/faker_file/cli.py
1
import argparse
5✔
2
import inspect
5✔
3
import os
5✔
4
import sys
5✔
5
import typing
5✔
6
from copy import deepcopy
5✔
7
from typing import Any, Dict, Tuple, Type
5✔
8

9
from faker import Faker
5✔
10

11
from .base import FileMixin, StringValue
5✔
12
from .providers.bin_file import BinFileProvider
5✔
13
from .providers.csv_file import CsvFileProvider
5✔
14
from .providers.docx_file import DocxFileProvider
5✔
15
from .providers.eml_file import EmlFileProvider
5✔
16
from .providers.epub_file import EpubFileProvider
5✔
17
from .providers.ico_file import IcoFileProvider
5✔
18
from .providers.jpeg_file import JpegFileProvider
5✔
19
from .providers.mp3_file import Mp3FileProvider
5✔
20
from .providers.odp_file import OdpFileProvider
5✔
21
from .providers.ods_file import OdsFileProvider
5✔
22
from .providers.odt_file import OdtFileProvider
5✔
23
from .providers.pdf_file import PdfFileProvider
5✔
24
from .providers.png_file import PngFileProvider
5✔
25
from .providers.pptx_file import PptxFileProvider
5✔
26
from .providers.rtf_file import RtfFileProvider
5✔
27
from .providers.svg_file import SvgFileProvider
5✔
28
from .providers.tar_file import TarFileProvider
5✔
29
from .providers.txt_file import TxtFileProvider
5✔
30
from .providers.webp_file import WebpFileProvider
5✔
31
from .providers.xlsx_file import XlsxFileProvider
5✔
32
from .providers.zip_file import ZipFileProvider
5✔
33

34
__author__ = "Artur Barseghyan <artur.barseghyan@gmail.com>"
5✔
35
__copyright__ = "2023 Artur Barseghyan"
5✔
36
__license__ = "MIT"
5✔
37
__all__ = [
5✔
38
    "main",
39
    "get_method_kwargs",
40
    "generate_file",
41
]
42

43
KWARGS_DROP = {
5✔
44
    "self",  # Drop as irrelevant
45
    "storage",  # Drop as non-supported arg
46
    "return",  # Drop as irrelevant
47
    # "mp3_generator_cls",  # Drop as non-supported arg
48
    # "mp3_generator_kwargs",  # Drop as non-supported arg
49
    # "pdf_generator_cls",  # Drop as non-supported arg
50
    # "pdf_generator_kwargs",  # Drop as non-supported arg
51
    "raw",  # Drop `raw`, because we will be forcing raw=True for streaming
52
}
53
OVERRIDES = {
5✔
54
    "DocxFileProvider.docx_file": {
55
        "annotations": {
56
            "content": str,
57
        },
58
        "model_props": {
59
            "content": None,
60
        },
61
    },
62
    "Mp3FileProvider.mp3_file": {
63
        "annotations": {
64
            "mp3_generator_cls": str,
65
        },
66
        "model_props": {
67
            "mp3_generator_cls": (
68
                "faker_file.providers.mp3_file.generators"
69
                ".gtts_generator.GttsMp3Generator"
70
            ),
71
        },
72
    },
73
    "OdtFileProvider.odt_file": {
74
        "annotations": {
75
            "content": str,
76
        },
77
        "model_props": {
78
            "content": None,
79
        },
80
    },
81
    "PdfFileProvider.pdf_file": {
82
        "annotations": {
83
            "pdf_generator_cls": str,
84
        },
85
        "model_props": {
86
            "pdf_generator_cls": (
87
                "faker_file.providers.pdf_file.generators"
88
                ".pdfkit_generator.PdfkitPdfGenerator"
89
            ),
90
        },
91
    },
92
}
93
PROVIDERS = {
5✔
94
    BinFileProvider.bin_file.__name__: BinFileProvider,
95
    CsvFileProvider.csv_file.__name__: CsvFileProvider,
96
    DocxFileProvider.docx_file.__name__: DocxFileProvider,
97
    EmlFileProvider.eml_file.__name__: EmlFileProvider,
98
    EpubFileProvider.epub_file.__name__: EpubFileProvider,
99
    IcoFileProvider.ico_file.__name__: IcoFileProvider,
100
    JpegFileProvider.jpeg_file.__name__: JpegFileProvider,
101
    Mp3FileProvider.mp3_file.__name__: Mp3FileProvider,
102
    OdpFileProvider.odp_file.__name__: OdpFileProvider,
103
    OdsFileProvider.ods_file.__name__: OdsFileProvider,
104
    OdtFileProvider.odt_file.__name__: OdtFileProvider,
105
    PdfFileProvider.pdf_file.__name__: PdfFileProvider,
106
    PngFileProvider.png_file.__name__: PngFileProvider,
107
    PptxFileProvider.pptx_file.__name__: PptxFileProvider,
108
    RtfFileProvider.rtf_file.__name__: RtfFileProvider,
109
    SvgFileProvider.svg_file.__name__: SvgFileProvider,
110
    TarFileProvider.tar_file.__name__: TarFileProvider,
111
    TxtFileProvider.txt_file.__name__: TxtFileProvider,
112
    WebpFileProvider.webp_file.__name__: WebpFileProvider,
113
    XlsxFileProvider.xlsx_file.__name__: XlsxFileProvider,
114
    ZipFileProvider.zip_file.__name__: ZipFileProvider,
115
}
116

117

118
def get_method_kwargs(
5✔
119
    cls: Type[FileMixin], method_name: str
120
) -> Tuple[Dict[str, Any], Dict[str, Any]]:
121
    method = getattr(cls, method_name)
5✔
122
    method_specs = inspect.getfullargspec(method)
5✔
123

124
    kwargs = deepcopy(method_specs.args[1:])  # Omit `self`
5✔
125
    defaults = deepcopy(method_specs.defaults)
5✔
126
    model_props = dict(zip(kwargs, defaults))
5✔
127
    annotations = deepcopy(method_specs.annotations)
5✔
128

129
    # Override the type definition for mp3_generator_cls
130
    override = OVERRIDES.get(f"{cls.__name__}.{method_name}", None)
5✔
131
    if override:
5✔
132
        annotations.update(override["annotations"])
5✔
133
        model_props.update(override["model_props"])
5✔
134

135
    for kwarg_name in KWARGS_DROP:
5✔
136
        annotations.pop(kwarg_name, None)
5✔
137
        model_props.pop(kwarg_name, None)
5✔
138

139
    return model_props, annotations
5✔
140

141

142
def generate_file(method_name: str, **kwargs) -> StringValue:
5✔
143
    faker = Faker()
5✔
144
    cls = PROVIDERS[method_name]
5✔
145
    method = getattr(cls(faker), method_name)
5✔
146
    value = method(**kwargs)
5✔
147
    return value
5✔
148

149

150
def is_optional_type(t: Any) -> bool:
5✔
151
    if getattr(t, "__origin__", None) is typing.Union:
5✔
152
        return any(arg is type(None) for arg in t.__args__)
5✔
153
    return False
5✔
154

155

156
def generate_completion_file():
5✔
157
    completion_script = f"""#!/bin/bash
5✔
158

159
_faker_file_completion() {{
160
    local cur prev providers
161
    cur="${{COMP_WORDS[COMP_CWORD]}}"
162
    prev="${{COMP_WORDS[COMP_CWORD - 1]}}"
163
    providers="{(' '.join(PROVIDERS.keys()))}"
164

165
    case $prev in"""
166

167
    for method_name, provider in PROVIDERS.items():
5✔
168
        method_kwargs, _ = get_method_kwargs(provider, method_name)
5✔
169
        completion_script += f"""
5✔
170
        {method_name})
171
            COMPREPLY=($(compgen -W "{(' '.join('--' + k for k in method_kwargs.keys()))} --nb_files" -- "$cur"))
172
            ;;
173
        """  # noqa
174

175
    completion_script += """
5✔
176
        *)
177
            COMPREPLY=($(compgen -W "$providers" -- "$cur"))
178
            ;;
179
    esac
180

181
    return 0
182
}
183

184
complete -F _faker_file_completion faker-file
185
"""
186

187
    user_home_dir = os.path.expanduser("~")
5✔
188
    file_path = os.path.join(user_home_dir, "faker_file_completion.sh")
5✔
189
    with open(file_path, "w") as f:
5✔
190
        f.write(completion_script)
5✔
191

192
    print(f"Generated bash completion file: {file_path}")
5✔
193

194

195
def main():
5✔
196
    parser = argparse.ArgumentParser(
5✔
197
        description="CLI for the faker-file package."
198
    )
199
    subparsers = parser.add_subparsers(
5✔
200
        dest="command", help="Available file providers."
201
    )
202

203
    # Add generate-completion subparser
204
    __generate_completion_subparser = subparsers.add_parser(
5✔
205
        "generate-completion",
206
        help="Generate bash completion file.",
207
    )
208

209
    for method_name, provider in PROVIDERS.items():
5✔
210
        subparser = subparsers.add_parser(
5✔
211
            method_name,
212
            help=f"Generate a {method_name.split('_file')[0]} file.",
213
        )
214
        method_kwargs, annotations = get_method_kwargs(provider, method_name)
5✔
215
        for arg, default in method_kwargs.items():
5✔
216
            arg_type = annotations[arg]
5✔
217
            arg_kwargs = {
5✔
218
                "default": default,
219
                "help": f"{arg} (default: {default})",
220
                "type": (
221
                    arg_type.__args__[0]
222
                    if isinstance(arg_type, typing._GenericAlias)
223
                    and is_optional_type(arg_type)
224
                    else arg_type
225
                ),
226
            }
227

228
            subparser.add_argument(f"--{arg}", **arg_kwargs)
5✔
229

230
        # Add the optional num_files argument
231
        subparser.add_argument(
5✔
232
            "--nb_files",
233
            default=1,
234
            type=int,
235
            help="number of files to generate (default: 1)",
236
        )
237

238
    args = parser.parse_args()
5✔
239

240
    if args.command == "generate-completion":
5✔
241
        generate_completion_file()
5✔
242
    elif args.command:
5✔
243
        kwargs = {k: v for k, v in vars(args).items() if k not in ("command",)}
5✔
244
        for counter in range(args.nb_files):
5✔
245
            output_file = generate_file(args.command, **kwargs)
5✔
246
            print(
5✔
247
                f"Generated {args.command} file "
248
                f"({counter+1} of {args.nb_files}): {output_file}"
249
            )
250
    else:
251
        parser.print_help()
5✔
252
        sys.exit(1)
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc