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

Typing [Fixed #1489!] #1536

Merged
merged 65 commits into from Oct 19, 2021
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
ff3ef2e
Create nl_NL
MarcelRobeer Oct 2, 2021
1d376d5
Delete nl_NL
MarcelRobeer Oct 2, 2021
ee2494e
Add date_time provider for nl_NL
MarcelRobeer Oct 2, 2021
2f56dfc
Added date_time nl_NL test case
MarcelRobeer Oct 2, 2021
74f130b
Merge branch 'joke2k:master' into master
MarcelRobeer Oct 7, 2021
dd9995d
Added nl_NL provider
MarcelRobeer Oct 7, 2021
82b4dd4
Added nl_NL test case
MarcelRobeer Oct 7, 2021
eecfaf0
Merge branch 'joke2k:master' into master
MarcelRobeer Oct 7, 2021
34f180e
Added nl_NL automotive provider
MarcelRobeer Oct 7, 2021
5990f65
Added tests for nl_NL automotive provider
MarcelRobeer Oct 7, 2021
aea16ed
flake8 fixes
MarcelRobeer Oct 7, 2021
0afa22d
flake8 fixes in test_automotive
MarcelRobeer Oct 7, 2021
7d1dc57
import order fixes
MarcelRobeer Oct 7, 2021
1c0981b
Added type annotations
MarcelRobeer Oct 10, 2021
b5673a8
mypy fixes
MarcelRobeer Oct 10, 2021
33b4054
isort fixes
MarcelRobeer Oct 10, 2021
2201cc8
minor flake8 fixes
MarcelRobeer Oct 10, 2021
f5a9985
Fixed circular import error in generator.py
MarcelRobeer Oct 10, 2021
64a2bfd
Circular import error fix
MarcelRobeer Oct 10, 2021
f2fee0a
Typing fixes for OrderedDict
MarcelRobeer Oct 10, 2021
28f7daa
OrderedDict Python 3.6 fix
MarcelRobeer Oct 10, 2021
80ac094
OrderedDictType fix in proxy
MarcelRobeer Oct 10, 2021
a7d257e
Added mypy test to tox.ini
MarcelRobeer Oct 10, 2021
1cf54eb
Update tox.ini
MarcelRobeer Oct 10, 2021
ff450d6
Update tox.ini
MarcelRobeer Oct 10, 2021
4fbb820
PyPy is incompatible with mypy
MarcelRobeer Oct 10, 2021
1bb4e05
Update tox.ini
MarcelRobeer Oct 10, 2021
72ef6da
Removed `automotive` provider `nl_NL`
MarcelRobeer Oct 11, 2021
fc1a851
Typo
MarcelRobeer Oct 11, 2021
bc93220
Many typing fixes
MarcelRobeer Oct 11, 2021
2d201e1
Added ElementsType (input for `BaseProvider.random_element()`)
MarcelRobeer Oct 12, 2021
951a0eb
First typing fixes in date_time
MarcelRobeer Oct 12, 2021
7acf2b1
Minor Typing fixes to date_time
MarcelRobeer Oct 12, 2021
6ea03fd
Typing fixes in `providers.company`
MarcelRobeer Oct 12, 2021
ca8ae4f
Minor typing fixes in `providers.barcode`
MarcelRobeer Oct 12, 2021
b026a0e
Minor typing fixes in `providers.address`
MarcelRobeer Oct 12, 2021
57a222b
Minor typing fixes in `providers.person`
MarcelRobeer Oct 12, 2021
a839ef0
Update decorators.py
MarcelRobeer Oct 12, 2021
ecd1224
Minor typing fixes in `providers.automotive`
MarcelRobeer Oct 12, 2021
43b5aab
Import typing.Pattern in test files
MarcelRobeer Oct 12, 2021
b90c6b8
Added type: ignore[attr-defined] hotfix
MarcelRobeer Oct 12, 2021
4225aa6
Added final missing Pattern imports
MarcelRobeer Oct 12, 2021
926c88b
Optional distrib, flake8 fix in test_user_agent
MarcelRobeer Oct 12, 2021
163d774
Minor typing fixes
MarcelRobeer Oct 12, 2021
100a0ee
Literal not supported before Python 3.8
MarcelRobeer Oct 12, 2021
3053b43
Bug fix in datetime.fromtimestamp
MarcelRobeer Oct 12, 2021
5eb091a
Fixed broken tests
MarcelRobeer Oct 12, 2021
b564666
Fixed test_ipv4_distribution_selection
MarcelRobeer Oct 13, 2021
f3addca
Update decimal in `geo.el_GR`
MarcelRobeer Oct 13, 2021
a67540f
Add mypy config and improve command for tox
nicarl Oct 13, 2021
d716a65
Fix last type errors
nicarl Oct 13, 2021
8bf0616
Merge pull request #1 from nicarl/fix_last_type_errors
MarcelRobeer Oct 14, 2021
5fc2af5
Updated MANIFEST.in to include mypy.ini
MarcelRobeer Oct 14, 2021
9786240
Renamed typing.py to typing.pyi
MarcelRobeer Oct 14, 2021
2b37692
Some Python versions don't like .pyi
MarcelRobeer Oct 14, 2021
5027aa1
Updated coding_style.rst
MarcelRobeer Oct 14, 2021
cfc1190
Added mypy to .github/workflows/ci.yml
MarcelRobeer Oct 14, 2021
23bb6d6
Merge branch 'master' into master
MarcelRobeer Oct 14, 2021
c3cf47b
Merge branch 'master' of https://github.com/MarcelRobeer/faker
MarcelRobeer Oct 14, 2021
85a225c
Added dependency order to ci.yml
MarcelRobeer Oct 16, 2021
b9c76f5
Python 3.10 to "3.10" in ci.yml
MarcelRobeer Oct 16, 2021
79ee364
Unused ignores across versions
MarcelRobeer Oct 16, 2021
d05ef2e
Show error codes
MarcelRobeer Oct 16, 2021
4e0724c
Python 3.6 mypy fix
MarcelRobeer Oct 16, 2021
016ef66
Final changes
MarcelRobeer Oct 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion faker/__main__.py
@@ -1,3 +1,3 @@
if __name__ == "__main__":
from faker.cli import execute_from_command_line
from .cli import execute_from_command_line
execute_from_command_line()
45 changes: 27 additions & 18 deletions faker/cli.py
Expand Up @@ -4,22 +4,27 @@
import random
import sys

from io import TextIOWrapper
from pathlib import Path
from typing import Any, Dict, List, Optional, TextIO
from typing import Dict, List, Optional, TextIO, TypeVar, Union

from faker import VERSION, Faker, documentor, exceptions
from faker.config import AVAILABLE_LOCALES, DEFAULT_LOCALE, META_PROVIDERS_MODULES
from . import VERSION, Faker, documentor, exceptions
from .config import AVAILABLE_LOCALES, DEFAULT_LOCALE, META_PROVIDERS_MODULES
from .documentor import Documentor
from .providers import BaseProvider

__author__ = 'joke2k'

T = TypeVar('T')

def print_provider(doc,
provider: List[str],
formatters: Dict[str, Any],
excludes=None,
output: Optional[TextIO] = None) -> None:

output = output or sys.stdout
def print_provider(doc: Documentor,
provider: BaseProvider,
formatters: Dict[str, T],
excludes: Optional[List[str]] = None,
output: Optional[TextIO] = None) -> None:
if output is None:
output = sys.stdout
if excludes is None:
excludes = []

Expand Down Expand Up @@ -48,11 +53,16 @@ def print_provider(doc,
signature = separator = ' '


def print_doc(provider_or_field=None,
args=None, lang: str = DEFAULT_LOCALE, output=None, seed=None,
includes=None) -> None:
args = args or []
output = output or sys.stdout
def print_doc(provider_or_field: Optional[str] = None,
args: Optional[List[T]] = None,
lang: str = DEFAULT_LOCALE,
output: Optional[Union[TextIO, TextIOWrapper]] = None,
seed: Optional[float] = None,
includes: Optional[List[str]] = None) -> None:
if args is None:
args = []
if output is None:
output = sys.stdout
fake = Faker(locale=lang, includes=includes)
fake.seed_instance(seed)

Expand Down Expand Up @@ -86,7 +96,7 @@ def print_doc(provider_or_field=None,

else:
doc = documentor.Documentor(fake)
unsupported = []
unsupported: List[str] = []

while True:
try:
Expand All @@ -97,7 +107,6 @@ def print_doc(provider_or_field=None,
break

for provider, fakers in formatters:

print_provider(doc, provider, fakers, output=output)

for language in AVAILABLE_LOCALES:
Expand All @@ -117,7 +126,7 @@ def print_doc(provider_or_field=None,

class Command:

def __init__(self, argv=None) -> None:
def __init__(self, argv: Optional[str] = None) -> None:
self.argv = argv or sys.argv[:]
self.prog_name = Path(self.argv[0]).name

Expand Down Expand Up @@ -259,7 +268,7 @@ def execute(self) -> None:
break


def execute_from_command_line(argv=None) -> None:
def execute_from_command_line(argv: Optional[str] = None) -> None:
"""A simple method that runs a Command."""
if sys.stdout.encoding is None:
print('please set python env PYTHONIOENCODING=UTF-8, example: '
Expand Down
2 changes: 1 addition & 1 deletion faker/config.py
@@ -1,6 +1,6 @@
from importlib import import_module

from faker.utils.loading import find_available_locales, find_available_providers
from .utils.loading import find_available_locales, find_available_providers

DEFAULT_LOCALE = 'en_US'

Expand Down
31 changes: 21 additions & 10 deletions faker/documentor.py
@@ -1,24 +1,33 @@
import inspect
import warnings

from typing import Dict, List, Optional, Tuple, Union

from .generator import Generator
from .providers import BaseProvider
from .proxy import Faker


class Documentor:

def __init__(self, generator):
def __init__(self, generator: Union[Generator, Faker]) -> None:
"""
:param generator: a localized Generator with providers filled,
for which to write the documentation
:type generator: faker.Generator()
"""
self.generator = generator
self.max_name_len = 0
self.already_generated = []
self.max_name_len: int = 0
self.already_generated: List[str] = []

def get_formatters(self, locale=None, excludes=None, **kwargs):
def get_formatters(self,
locale: Optional[str] = None,
excludes: Optional[List[str]] = None,
**kwargs) -> List[Tuple[BaseProvider, Dict[str, str]]]:
self.max_name_len = 0
self.already_generated = [] if excludes is None else excludes[:]
formatters = []
providers = self.generator.get_providers()
providers: List[BaseProvider] = self.generator.get_providers()
for provider in providers[::-1]: # reverse
if locale and provider.__lang__ != locale:
continue
Expand All @@ -27,9 +36,11 @@ def get_formatters(self, locale=None, excludes=None, **kwargs):
)
return formatters

def get_provider_formatters(self, provider, prefix='fake.',
with_args=True, with_defaults=True):

def get_provider_formatters(self,
provider: BaseProvider,
prefix: str = 'fake.',
with_args: bool = True,
with_defaults: bool = True) -> Dict[str, str]:
formatters = {}

for name, method in inspect.getmembers(provider, inspect.ismethod):
Expand All @@ -38,7 +49,7 @@ def get_provider_formatters(self, provider, prefix='fake.',
continue

arguments = []
faker_args = []
faker_args: List[str] = []
faker_kwargs = {}

if name == 'binary':
Expand Down Expand Up @@ -98,5 +109,5 @@ def get_provider_formatters(self, provider, prefix='fake.',
return formatters

@staticmethod
def get_provider_name(provider_class):
def get_provider_name(provider_class: BaseProvider) -> str:
return provider_class.__provider__
3 changes: 2 additions & 1 deletion faker/exceptions.py
Expand Up @@ -10,6 +10,7 @@ class UniquenessException(BaseFakerException):

class UnsupportedFeature(BaseFakerException):
"""The requested feature is not available on this system."""
def __init__(self, msg, name):

def __init__(self, msg: str, name: str) -> None:
self.name = name
super().__init__(msg)
23 changes: 12 additions & 11 deletions faker/factory.py
Expand Up @@ -3,10 +3,11 @@
import sys

from importlib import import_module
from typing import List, Optional

from faker.config import AVAILABLE_LOCALES, DEFAULT_LOCALE, PROVIDERS
from faker.generator import Generator
from faker.utils.loading import list_module
from .config import AVAILABLE_LOCALES, DEFAULT_LOCALE, PROVIDERS
from .generator import Generator
from .utils.loading import list_module

logger = logging.getLogger(__name__)

Expand All @@ -23,13 +24,13 @@ class Factory:
@classmethod
def create(
cls,
locale=None,
providers=None,
generator=None,
includes=None,
locale: Optional[str] = None,
providers: Optional[List[str]] = None,
generator: Generator = None,
includes: Optional[List[str]] = None,
# Should we use weightings (more realistic) or weight every element equally (faster)?
# By default, use weightings for backwards compatibility & realism
use_weighting=True,
use_weighting: bool = True,
**config):
if includes is None:
includes = []
Expand Down Expand Up @@ -63,7 +64,7 @@ def create(
return faker

@classmethod
def _get_provider_class(cls, provider, locale=''):
def _get_provider_class(cls, provider: str, locale: Optional[str] = ''):

provider_class = cls._find_provider_class(provider, locale)

Expand All @@ -85,7 +86,7 @@ def _get_provider_class(cls, provider, locale=''):
raise ValueError(msg)

@classmethod
def _find_provider_class(cls, provider_path, locale=None):
def _find_provider_class(cls, provider_path: str, locale: Optional[str] = None):

provider_module = import_module(provider_path)

Expand Down Expand Up @@ -117,4 +118,4 @@ def _find_provider_class(cls, provider_path, locale=None):
if locale is not None:
provider_module = import_module(provider_path)

return provider_module.Provider
return provider_module.Provider # type: ignore
45 changes: 25 additions & 20 deletions faker/generator.py
@@ -1,24 +1,29 @@
import random as random_module
import re

from typing import Callable, Dict, Hashable, List, Optional, TypeVar

_re_token = re.compile(r'\{\{\s*(\w+)(:\s*\w+?)?\s*\}\}')
random = random_module.Random()
mod_random = random # compat with name released in 0.8

T = TypeVar('T')
BaseProvider = TypeVar('BaseProvider')


class Generator:

__config = {
__config: Dict[str, Dict[Hashable, T]] = {
'arguments': {},
}

def __init__(self, **config):
self.providers = []
def __init__(self, **config) -> None:
self.providers: List[BaseProvider] = []
self.__config = dict(
list(self.__config.items()) + list(config.items()))
self.__random = random

def add_provider(self, provider):
def add_provider(self, provider: BaseProvider) -> None:

if isinstance(provider, type):
provider = provider(self)
Expand All @@ -36,27 +41,27 @@ def add_provider(self, provider):
# add all faker method to generator
self.set_formatter(method_name, faker_function)

def provider(self, name):
def provider(self, name: str) -> Optional[BaseProvider]:
try:
lst = [p for p in self.get_providers()
if p.__provider__ == name.lower()]
if hasattr(p, '__provider__') and p.__provider__ == name.lower()] # type: ignore[attr-defined]
return lst[0]
except IndexError:
return None

def get_providers(self):
def get_providers(self) -> List[BaseProvider]:
"""Returns added providers."""
return self.providers

@property
def random(self):
def random(self) -> random_module.Random:
return self.__random

@random.setter
def random(self, value):
def random(self, value: random_module.Random) -> None:
self.__random = value

def seed_instance(self, seed=None):
def seed_instance(self, seed: Optional[Hashable] = None):
"""Calls random.seed"""
if self.__random == random:
# create per-instance random obj when first time seed_instance() is
Expand All @@ -66,16 +71,16 @@ def seed_instance(self, seed=None):
return self

@classmethod
def seed(cls, seed=None):
def seed(cls, seed: Optional[Hashable] = None):
random.seed(seed)

def format(self, formatter, *args, **kwargs):
def format(self, formatter: str, *args, **kwargs) -> str:
"""
This is a secure way to make a fake from another Provider.
"""
return self.get_formatter(formatter)(*args, **kwargs)

def get_formatter(self, formatter):
def get_formatter(self, formatter: str) -> Callable:
try:
return getattr(self, formatter)
except AttributeError:
Expand All @@ -85,14 +90,14 @@ def get_formatter(self, formatter):
raise AttributeError(f'Unknown formatter {formatter!r}')
raise AttributeError(msg)

def set_formatter(self, name, method):
def set_formatter(self, name: str, method: Callable) -> None:
"""
This method adds a provider method to generator.
Override this method to add some decoration or logging stuff.
"""
setattr(self, name, method)

def set_arguments(self, group, argument, value=None):
def set_arguments(self, group: str, argument: str, value: T = None):
"""
Creates an argument group, with an individual argument or a dictionary
of arguments. The argument groups is used to apply arguments to tokens,
Expand All @@ -112,7 +117,7 @@ def set_arguments(self, group, argument, value=None):
else:
self.__config['arguments'][group][argument] = value

def get_arguments(self, group, argument=None):
def get_arguments(self, group: str, argument: Optional[str] = None):
"""
Get the value of an argument configured within a argument group, or
the entire group as a dictionary. Used in conjunction with the
Expand All @@ -122,13 +127,13 @@ def get_arguments(self, group, argument=None):
generator.get_arguments('small')
"""
if group in self.__config['arguments'] and argument:
result = self.__config['arguments'][group].get(argument)
result = self.__config['arguments'][group].get(argument) # type: ignore[attr-defined]
else:
result = self.__config['arguments'].get(group)

return result

def del_arguments(self, group, argument=None):
def del_arguments(self, group: str, argument: Optional[str] = None):
"""
Delete an argument from an argument group or the entire argument group.
Used in conjunction with the set_arguments() method.
Expand All @@ -138,15 +143,15 @@ def del_arguments(self, group, argument=None):
"""
if group in self.__config['arguments']:
if argument:
result = self.__config['arguments'][group].pop(argument)
result = self.__config['arguments'][group].pop(argument) # type: ignore[attr-defined]
else:
result = self.__config['arguments'].pop(group)
else:
result = None

return result

def parse(self, text):
def parse(self, text: str) -> str:
"""
Replaces tokens like '{{ tokenName }}' or '{{tokenName}}' in a string with
the result from the token method call. Arguments can be parsed by using an
Expand Down