# -*- coding: utf-8 -*-

"""
This module contains list of white- and black-listed ``python`` members.

It contains lists of keywords and built-in functions we discourage to use.
It also contains some exceptions that we allow to use in our codebase.
"""

import re
import sys

# TODO: use consistent `.` for the `#:` comments
# TODO: use consistent names: `*_BLACKLIST` and `*_WHITELIST`

#: List of functions we forbid to use.
BAD_FUNCTIONS = frozenset((
    # Code generation:
    'eval',
    'exec',
    'compile',

    # Magic:
    'globals',
    'locals',
    'vars',
    'dir',

    # IO:
    'input',

    # Attribute access:
    'hasattr',
    'delattr',

    # Misc:
    'copyright',
    'help',

    # Dynamic imports:
    '__import__',

    # OOP:
    'staticmethod',
))

#: List of module metadata we forbid to use.
BAD_MODULE_METADATA_VARIABLES = frozenset((
    '__author__',
    '__all__',
    '__version__',
    '__about__',
))


_BAD_VARIABLE_NAMES = [
    # Meaningless words:
    'data',
    'result',
    'results',
    'item',
    'items',
    'value',
    'values',
    'val',
    'vals',
    'var',
    'vars',
    'content',
    'contents',
    'info',
    'handle',
    'handler',
    'file',
    'obj',
    'objects',
    'objs',
    'some',

    # Confusables:
    'no',
    'true',
    'false',

    # Names from examples:
    'foo',
    'bar',
    'baz',
]

if sys.version_info < (3, 7):  # pragma: no cover
    _BAD_VARIABLE_NAMES.extend([
        # Compatibility with `python3.7`:
        'async',
        'await',
    ])

#: List of variable names we forbid to use.
BAD_VARIABLE_NAMES = frozenset(_BAD_VARIABLE_NAMES)

#: List of magic methods that are forbiden to use.
BAD_MAGIC_METHODS = frozenset((
    # Since we don't use `del`:
    '__del__',
    '__delitem__',
    '__delete__',

    '__dir__',  # since we don't use `dir()`
    '__delattr__',  # since we don't use `delattr()`
))

#: List of nested classes' names we allow to use.
NESTED_CLASSES_WHITELIST = frozenset((
    'Meta',  # django forms, models, drf, etc
    'Params',  # factoryboy specific
))

#: List of nested functions' names we allow to use.
NESTED_FUNCTIONS_WHITELIST = frozenset((
    'decorator',
    'factory',
))

#: List of allowed ``__future__`` imports.
FUTURE_IMPORTS_WHITELIST = frozenset((
    'annotations',
    'generator_stop',
))

#: List of blacklisted module names:
BAD_MODULE_NAMES = frozenset((
    'util',
    'utils',
    'utilities',
    'helpers',
))

#: List of allowed module magic names:
MAGIC_MODULE_NAMES_WHITELIST = frozenset((
    '__init__',
    '__main__',
))

#: Regex pattern to name modules:
MODULE_NAME_PATTERN = re.compile(r'^_?_?[a-z][a-z\d_]+[a-z\d](__)?$')

#: Common numbers that are allowed to be used without being called "magic":
MAGIC_NUMBERS_WHITELIST = frozenset((
    0.5,
    100,
    1000,
    1024,  # bytes
    24,  # hours
    60,  # seconds, minutes
))


# Internal variables
# They are not publicly documented since they are not used by the end user.

# This variable is used as a default filename, when it is not passed by flake8:
STDIN = 'stdin'

# TODO: rename to `INIT_MODULE`
# This variable is used to specify as a placeholder for `__init__.py`:
INIT = '__init__'

wemake_python_styleguide/constants.py
# -*- coding: utf-8 -*-

"""
This module contains list of white- and black-listed ``python`` members.

It contains lists of keywords and built-in functions we discourage to use.
It also contains some exceptions that we allow to use in our codebase.
"""

import re
import sys

# TODO: use consistent `.` for the `#:` comments
# TODO: use consistent names: `*_BLACKLIST` and `*_WHITELIST`

#: List of functions we forbid to use.
BAD_FUNCTIONS = frozenset((
    # Code generation:
    'eval',
    'exec',
    'compile',

    # Magic:
    'globals',
    'locals',
    'vars',
    'dir',

    # IO:
    'input',

    # Attribute access:
    'hasattr',
    'delattr',

    # Misc:
    'copyright',
    'help',
    'credits',

    # Dynamic imports:
    '__import__',

    # OOP:
    'staticmethod',
))

#: List of module metadata we forbid to use.
BAD_MODULE_METADATA_VARIABLES = frozenset((
    '__author__',
    '__all__',
    '__version__',
    '__about__',
))


_BAD_VARIABLE_NAMES = [
    # Meaningless words:
    'data',
    'result',
    'results',
    'item',
    'items',
    'value',
    'values',
    'val',
    'vals',
    'var',
    'vars',
    'content',
    'contents',
    'info',
    'handle',
    'handler',
    'file',
    'obj',
    'objects',
    'objs',
    'some',

    # Confusables:
    'no',
    'true',
    'false',

    # Names from examples:
    'foo',
    'bar',
    'baz',
]

if sys.version_info < (3, 7):  # pragma: no cover
    _BAD_VARIABLE_NAMES.extend([
        # Compatibility with `python3.7`:
        'async',
        'await',
    ])

#: List of variable names we forbid to use.
BAD_VARIABLE_NAMES = frozenset(_BAD_VARIABLE_NAMES)

#: List of magic methods that are forbiden to use.
BAD_MAGIC_METHODS = frozenset((
    # Since we don't use `del`:
    '__del__',
    '__delitem__',
    '__delete__',

    '__dir__',  # since we don't use `dir()`
    '__delattr__',  # since we don't use `delattr()`
))

#: List of nested classes' names we allow to use.
NESTED_CLASSES_WHITELIST = frozenset((
    'Meta',  # django forms, models, drf, etc
    'Params',  # factoryboy specific
))

#: List of nested functions' names we allow to use.
NESTED_FUNCTIONS_WHITELIST = frozenset((
    'decorator',
    'factory',
))

#: List of allowed ``__future__`` imports.
FUTURE_IMPORTS_WHITELIST = frozenset((
    'annotations',
    'generator_stop',
))

#: List of blacklisted module names:
BAD_MODULE_NAMES = frozenset((
    'util',
    'utils',
    'utilities',
    'helpers',
))

#: List of allowed module magic names:
MAGIC_MODULE_NAMES_WHITELIST = frozenset((
    '__init__',
    '__main__',
))

#: Regex pattern to name modules:
MODULE_NAME_PATTERN = re.compile(r'^_?_?[a-z][a-z\d_]+[a-z\d](__)?$')

#: Common numbers that are allowed to be used without being called "magic":
MAGIC_NUMBERS_WHITELIST = frozenset((
    0.5,
    100,
    1000,
    1024,  # bytes
    24,  # hours
    60,  # seconds, minutes
))


# Internal variables
# They are not publicly documented since they are not used by the end user.

# This variable is used as a default filename, when it is not passed by flake8:
STDIN = 'stdin'

# TODO: rename to `INIT_MODULE`
# This variable is used to specify as a placeholder for `__init__.py`:
INIT = '__init__'

wemake_python_styleguide/constants.py
diff --git a/wemake_python_styleguide/constants.py b/wemake_python_styleguide/constants.py
index 22989f326..311820fee 100644
--- a/wemake_python_styleguide/constants.py
+++ b/wemake_python_styleguide/constants.py
@@ -36,6 +36,7 @@
     # Misc:
     'copyright',
     'help',
+    'credits',
 
     # Dynamic imports:
     '__import__',

Feature: forbid `credits()` builtin function
We should add `credits()` as a forbidden function:

```
» python -c 'credits()'
    Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
    for supporting Python development.  See www.python.org for more information.

```

We need to add it here: https://github.com/wemake-services/wemake-python-styleguide/blob/3cedeb3c13ab6b16980a39edf657ab93d4c1f19e/wemake_python_styleguide/constants.py#L36-L38
