Skip to content

Commit

Permalink
Improve code comments (#31)
Browse files Browse the repository at this point in the history
* Add pydocstyle as pre-commit hook

* Fix a few comments

* Fix unrelated stuff from flake8

* Remove non existent method from docstring

* Remove duplicated comments and improve docstring of a few tests
  • Loading branch information
anapaulagomes authored and berinhard committed Nov 20, 2019
1 parent a77a1e1 commit e57b42f
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 139 deletions.
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ repos:
rev: 3.7.6
hooks:
- id: flake8
- repo: https://gitlab.com/pycqa/pydocstyle
rev: 4.0.1
hooks:
- id: pydocstyle
1 change: 1 addition & 0 deletions model_bakery/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Model Bakery module configuration."""
__version__ = '1.0.2'
__title__ = 'model_bakery'
__author__ = 'Vanderson Mota'
Expand Down
80 changes: 38 additions & 42 deletions model_bakery/baker.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
ModelNotFound, AmbiguousModelName, InvalidQuantityException, RecipeIteratorEmpty,
CustomBakerNotFound, InvalidCustomBaker
)
from .utils import import_from_str, import_if_str
from .utils import import_from_str

recipes = None

Expand All @@ -35,10 +35,10 @@ def _valid_quantity(quantity):

def make(_model, _quantity=None, make_m2m=False, _save_kwargs=None, _refresh_after_create=False,
_create_files=False, **attrs):
"""
Creates a persisted instance from a given model its associated models.
It fill the fields with random values or you can specify
which fields you want to define its values by yourself.
"""Create a persisted instance from a given model its associated models.
It fill the fields with random values or you can specify which
fields you want to define its values by yourself.
"""
_save_kwargs = _save_kwargs or {}
baker = Baker.create(_model, make_m2m=make_m2m, create_files=_create_files)
Expand All @@ -62,11 +62,10 @@ def make(_model, _quantity=None, make_m2m=False, _save_kwargs=None, _refresh_aft


def prepare(_model, _quantity=None, _save_related=False, **attrs):
"""
Creates BUT DOESN'T persist an instance from a given model its
associated models.
It fill the fields with random values or you can specify
which fields you want to define its values by yourself.
"""Create but do not persist an instance from a given model.
It fill the fields with random values or you can specify which
fields you want to define its values by yourself.
"""
baker = Baker.create(_model)
if _valid_quantity(_quantity):
Expand Down Expand Up @@ -96,18 +95,20 @@ def prepare_recipe(baker_recipe_name, _quantity=None, _save_related=False, **new


class ModelFinder(object):
"""
Encapsulates all the logic for finding a model to Baker.
"""
"""Encapsulates all the logic for finding a model to Baker."""

_unique_models = None
_ambiguous_models = None

def get_model(self, name):
"""
Get a model.
"""Get a model.
Args:
name (str): A name on the form 'applabel.modelname' or 'modelname'
Returns:
object: a model class
:param name String on the form 'applabel.modelname' or 'modelname'.
:return a model class.
"""
try:
if '.' in name:
Expand All @@ -124,11 +125,10 @@ def get_model(self, name):
return model

def get_model_by_name(self, name):
"""
Get a model by name.
"""Get a model by name.
If a model with that name exists in more than one app,
raises AmbiguousModelName.
If a model with that name exists in more than one app, raises
AmbiguousModelName.
"""
name = name.lower()

Expand All @@ -142,9 +142,7 @@ def get_model_by_name(self, name):
return self._unique_models.get(name)

def _populate(self):
"""
Cache models for faster self._get_model.
"""
"""Cache models for faster self._get_model."""
unique_models = {}
ambiguous_models = []

Expand Down Expand Up @@ -172,9 +170,12 @@ def is_iterator(value):


def _custom_baker_class():
"""
Returns custom baker class specified by BAKER_CUSTOM_CLASS in the django
settings, or None if no custom class is defined
"""Return the specified custom baker class.
Returns:
object: The custom class is specified by BAKER_CUSTOM_CLASS in Django's
settings, or None if no custom class is defined.
"""
custom_class_string = getattr(settings, 'BAKER_CUSTOM_CLASS', None)
if custom_class_string is None:
Expand Down Expand Up @@ -204,9 +205,7 @@ class Baker(object):

@classmethod
def create(cls, _model, make_m2m=False, create_files=False):
"""
Factory which creates the baker class defined by the BAKER_CUSTOM_CLASS setting
"""
"""Create the baker class defined by the `BAKER_CUSTOM_CLASS` setting."""
baker_class = _custom_baker_class() or cls
return baker_class(_model, make_m2m, create_files)

Expand All @@ -230,8 +229,8 @@ def init_type_mapping(self):
self.type_mapping = generators.get_type_mapping()
generators_from_settings = getattr(settings, 'BAKER_CUSTOM_FIELDS_GEN', {})
for k, v in generators_from_settings.items():
field_class = import_if_str(k)
generator = import_if_str(v)
field_class = import_from_str(k)
generator = import_from_str(v)
self.type_mapping[field_class] = generator

def make(
Expand All @@ -241,8 +240,7 @@ def make(
_from_manager=None,
**attrs
):
"""Creates and persists an instance of the model associated
with Baker instance."""
"""Create and persist an instance of the model associated with Baker instance."""
params = {
'commit': True,
'commit_related': True,
Expand All @@ -254,8 +252,7 @@ def make(
return self._make(**params)

def prepare(self, _save_related=False, **attrs):
"""Creates, but does not persist, an instance of the model
associated with Baker instance."""
"""Create, but do not persist, an instance of the associated model."""
return self._make(commit=False, commit_related=_save_related, **attrs)

def get_fields(self):
Expand Down Expand Up @@ -444,8 +441,7 @@ def _remote_field(self, field):
return field.remote_field

def generate_value(self, field, commit=True):
"""
Calls the generator associated with a field passing all required args.
"""Call the associated generator with a field passing all required args.
Generator Resolution Precedence Order:
-- attr_mapping - mapping per attribute name
Expand Down Expand Up @@ -486,10 +482,10 @@ def generate_value(self, field, commit=True):


def get_required_values(generator, field):
"""
Gets required values for a generator from the field.
If required value is a function, calls it with field as argument.
If required value is a string, simply fetch the value from the field
"""Get required values for a generator from the field.
If required value is a function, calls it with field as argument. If
required value is a string, simply fetch the value from the field
and return.
"""
# FIXME: avoid abbreviations
Expand Down
4 changes: 2 additions & 2 deletions model_bakery/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from . import random_gen
from .gis import default_gis_mapping
from .utils import import_if_str
from .utils import import_from_str

try:
from django.contrib.postgres.fields import ArrayField
Expand Down Expand Up @@ -98,7 +98,7 @@ def get_type_mapping():


def add(field, func):
user_mapping[import_if_str(field)] = import_if_str(func)
user_mapping[import_from_str(field)] = import_from_str(func)


def get(field):
Expand Down
38 changes: 21 additions & 17 deletions model_bakery/random_gen.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""
Generators are callables that return a value used to populate a field.
If this callable has a `required` attribute (a list, mostly), for each item in
the list, if the item is a string, the field attribute with the same name will
be fetched from the field and used as argument for the generator. If it is a
callable (which will receive `field` as first argument), it should return a
list in the format (key, value) where key is the argument name for generator
and value is the value for that argument.
"""Generators are callables that return a value used to populate a field.
If this callable has a `required` attribute (a list, mostly), for each
item in the list, if the item is a string, the field attribute with the
same name will be fetched from the field and used as argument for the
generator. If it is a callable (which will receive `field` as first
argument), it should return a list in the format (key, value) where key
is the argument name for generator and value is the value for that
argument.
"""

import string
Expand Down Expand Up @@ -43,14 +43,18 @@ def gen_image_field():
return get_content_file(f.read(), name=name)


def gen_from_list(L):
'''Makes sure all values of the field are generated from the list L
Usage:
from baker import Baker
class ExperientBaker(Baker):
attr_mapping = {'some_field':gen_from_list([A, B, C])}
'''
return lambda: choice(list(L))
def gen_from_list(a_list):
"""Make sure all values of the field are generated from a list.
Examples:
Here how to use it.
>>> from baker import Baker
>>> class ExperienceBaker(Baker):
>>> attr_mapping = {'some_field': gen_from_list(['A', 'B', 'C'])}
"""
return lambda: choice(list(a_list))


# -- DEFAULT GENERATORS --
Expand Down
13 changes: 6 additions & 7 deletions model_bakery/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,15 @@ def __init__(self, recipe):


def foreign_key(recipe):
"""
Returns the callable, so that the associated _model
will not be created during the recipe definition.
"""Return a `RecipeForeignKey`.
Return the callable, so that the associated `_model` will not be created
during the recipe definition.
"""
return RecipeForeignKey(recipe)


class related(object):
class related(object): # FIXME
def __init__(self, *args):
self.related = []
for recipe in args:
Expand All @@ -109,7 +110,5 @@ def __init__(self, *args):
raise TypeError('Not a recipe')

def make(self):
"""
Persists objects to m2m relation
"""
"""Persist objects to m2m relation."""
return [m.make() for m in self.related]
4 changes: 2 additions & 2 deletions model_bakery/timezone.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Add support for Django 1.4+ safe datetimes.
"""Add support for Django 1.4+ safe datetimes.
https://docs.djangoproject.com/en/1.4/topics/i18n/timezones/
"""
# TODO: the whole file seems to be not needed anymore, since Django has this tooling built-in
Expand Down
28 changes: 9 additions & 19 deletions model_bakery/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,18 @@
from .timezone import tz_aware


def import_if_str(import_string_or_obj):
"""
Import and return an object defined as import string in the form of
path.to.module.object_name
or just return the object if it isn't a string.
"""
if isinstance(import_string_or_obj, str):
return import_from_str(import_string_or_obj)
return import_string_or_obj


def import_from_str(import_string):
"""
Import and return an object defined as import string in the form of
"""Import an object defined as import if it is an string.
path.to.module.object_name
If `import_string` follows the format `path.to.module.object_name`,
this method imports it; else it just return the object.
"""
path, field_name = import_string.rsplit('.', 1)
module = importlib.import_module(path)
return getattr(module, field_name)
if isinstance(import_string, str):
path, field_name = import_string.rsplit('.', 1)
module = importlib.import_module(path)
return getattr(module, field_name)
else:
return import_string


def seq(value, increment_by=1):
Expand Down
5 changes: 2 additions & 3 deletions tests/generic/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,12 +306,11 @@ class Movie(models.Model):

class MovieManager(models.Manager):
def get_queryset(self):
'''Annotate queryset with an alias field 'name'.
"""Annotate queryset with an alias field 'name'.
We want to test whether this annotation has been run after
calling baker.make().
'''
"""
return (
super(MovieManager, self).get_queryset()
.annotate(name=models.F('title'))
Expand Down
Loading

0 comments on commit e57b42f

Please sign in to comment.