summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--Makefile4
-rw-r--r--README.rst6
-rw-r--r--dev_requirements.txt3
-rw-r--r--docs/conf.py2
-rw-r--r--docs/orms.rst2
-rw-r--r--docs/reference.rst17
-rw-r--r--factory/compat.py8
-rw-r--r--factory/fuzzy.py2
-rw-r--r--tests/test_fuzzy.py13
-rw-r--r--tests/test_using.py30
11 files changed, 74 insertions, 14 deletions
diff --git a/.travis.yml b/.travis.yml
index e1600bd..ff805b0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@ language: python
python:
- "2.7"
- "3.4"
+ - "3.5"
- "pypy"
script:
diff --git a/Makefile b/Makefile
index 35f635c..da8ac88 100644
--- a/Makefile
+++ b/Makefile
@@ -7,13 +7,13 @@ EXAMPLES_DIR=examples
COVERAGE = python $(shell which coverage)
# Dependencies
-DJANGO ?= 1.8
+DJANGO ?= 1.9
NEXT_DJANGO = $(shell python -c "v='$(DJANGO)'; parts=v.split('.'); parts[-1]=str(int(parts[-1])+1); print('.'.join(parts))")
ALCHEMY ?= 1.0
NEXT_ALCHEMY = $(shell python -c "v='$(ALCHEMY)'; parts=v.split('.'); parts[-1]=str(int(parts[-1])+1); print('.'.join(parts))")
-MONGOENGINE ?= 0.9
+MONGOENGINE ?= 0.10
NEXT_MONGOENGINE = $(shell python -c "v='$(MONGOENGINE)'; parts=v.split('.'); parts[-1]=str(int(parts[-1])+1); print('.'.join(parts))")
REQ_FILE = auto_dev_requirements_django$(DJANGO)_alchemy$(ALCHEMY)_mongoengine$(MONGOENGINE).txt
diff --git a/README.rst b/README.rst
index 9b82406..8914c62 100644
--- a/README.rst
+++ b/README.rst
@@ -181,7 +181,7 @@ It is also possible to create a bunch of objects in a single call:
Realistic, random values
""""""""""""""""""""""""
-Tests look better with random yet realistic values.
+Demos look better with random yet realistic values; and those realistic values can also help discover bugs.
For this, factory_boy relies on the excellent `fake-factory <https://pypi.python.org/pypi/fake-factory>`_ library:
.. code-block:: python
@@ -199,6 +199,10 @@ For this, factory_boy relies on the excellent `fake-factory <https://pypi.python
<User: Lucy Murray>
+.. note:: Use of fully randomized data in tests is quickly a problem for reproducing broken builds.
+ To that purpose, factory_boy provides helpers to handle the random seeds it uses.
+
+
Lazy Attributes
"""""""""""""""
diff --git a/dev_requirements.txt b/dev_requirements.txt
index 22261a1..c78aa9d 100644
--- a/dev_requirements.txt
+++ b/dev_requirements.txt
@@ -8,3 +8,6 @@ SQLAlchemy
mongoengine
mock
wheel
+
+Sphinx
+sphinx_rtd_theme
diff --git a/docs/conf.py b/docs/conf.py
index c3512e0..d5b86f4 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -114,7 +114,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'default'
+html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
diff --git a/docs/orms.rst b/docs/orms.rst
index bd481bd..d1b30fc 100644
--- a/docs/orms.rst
+++ b/docs/orms.rst
@@ -126,7 +126,7 @@ Extra fields
:param str from_path: Use data from the file located at ``from_path``,
and keep its filename
:param file from_file: Use the contents of the provided file object; use its filename
- if available
+ if available, unless ``filename`` is also provided.
:param bytes data: Use the provided bytes as file contents
:param str filename: The filename for the FileField
diff --git a/docs/reference.rst b/docs/reference.rst
index 6398d9a..b5ccd16 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -1412,6 +1412,23 @@ If a value if passed for the :class:`RelatedFactory` attribute, this disables
1
+.. note:: The target of the :class:`RelatedFactory` is evaluated *after* the initial factory has been instantiated.
+ This means that calls to :class:`factory.SelfAttribute` cannot go higher than this :class:`RelatedFactory`:
+
+ .. code-block:: python
+
+ class CountryFactory(factory.Factory):
+ class Meta:
+ model = Country
+
+ lang = 'fr'
+ capital_city = factory.RelatedFactory(CityFactory, 'capital_of',
+ # factory.SelfAttribute('..lang') will crash, since the context of
+ # ``CountryFactory`` has already been evaluated.
+ main_lang=factory.SelfAttribute('capital_of.lang'),
+ )
+
+
PostGeneration
""""""""""""""
diff --git a/factory/compat.py b/factory/compat.py
index 785d174..737d91a 100644
--- a/factory/compat.py
+++ b/factory/compat.py
@@ -42,14 +42,6 @@ else: # pragma: no cover
from io import BytesIO
-if sys.version_info[:2] == (2, 6): # pragma: no cover
- def float_to_decimal(fl):
- return decimal.Decimal(str(fl))
-else: # pragma: no cover
- def float_to_decimal(fl):
- return decimal.Decimal(fl)
-
-
try: # pragma: no cover
# Python >= 3.2
UTC = datetime.timezone.utc
diff --git a/factory/fuzzy.py b/factory/fuzzy.py
index 923d8b7..a7e834c 100644
--- a/factory/fuzzy.py
+++ b/factory/fuzzy.py
@@ -164,7 +164,7 @@ class FuzzyDecimal(BaseFuzzyAttribute):
super(FuzzyDecimal, self).__init__(**kwargs)
def fuzz(self):
- base = compat.float_to_decimal(_random.uniform(self.low, self.high))
+ base = decimal.Decimal(str(_random.uniform(self.low, self.high)))
return base.quantize(decimal.Decimal(10) ** -self.precision)
diff --git a/tests/test_fuzzy.py b/tests/test_fuzzy.py
index 3f9c434..4c3873a 100644
--- a/tests/test_fuzzy.py
+++ b/tests/test_fuzzy.py
@@ -189,6 +189,19 @@ class FuzzyDecimalTestCase(unittest.TestCase):
self.assertEqual(decimal.Decimal('8.001').quantize(decimal.Decimal(10) ** -3), res)
+ @unittest.skipIf(compat.PY2, "decimal.FloatOperation was added in Py3")
+ def test_no_approximation(self):
+ """We should not go through floats in our fuzzy calls unless actually needed."""
+ fuzz = fuzzy.FuzzyDecimal(0, 10)
+
+ decimal_context = decimal.getcontext()
+ old_traps = decimal_context.traps[decimal.FloatOperation]
+ try:
+ decimal_context.traps[decimal.FloatOperation] = True
+ fuzz.evaluate(2, None, None)
+ finally:
+ decimal_context.traps[decimal.FloatOperation] = old_traps
+
class FuzzyDateTestCase(unittest.TestCase):
@classmethod
diff --git a/tests/test_using.py b/tests/test_using.py
index c7d2b85..0a893c1 100644
--- a/tests/test_using.py
+++ b/tests/test_using.py
@@ -1924,6 +1924,36 @@ class PostGenerationTestCase(unittest.TestCase):
self.assertEqual(3, related.one)
self.assertEqual(4, related.two)
+ def test_related_factory_selfattribute(self):
+ class TestRelatedObject(object):
+ def __init__(self, obj=None, one=None, two=None):
+ obj.related = self
+ self.one = one
+ self.two = two
+ self.three = obj
+
+ class TestRelatedObjectFactory(factory.Factory):
+ class Meta:
+ model = TestRelatedObject
+ one = 1
+ two = factory.LazyAttribute(lambda o: o.one + 1)
+
+ class TestObjectFactory(factory.Factory):
+ class Meta:
+ model = TestObject
+ one = 3
+ two = 2
+ three = factory.RelatedFactory(TestRelatedObjectFactory, 'obj',
+ two=factory.SelfAttribute('obj.two'),
+ )
+
+ obj = TestObjectFactory.build(two=4)
+ self.assertEqual(3, obj.one)
+ self.assertEqual(4, obj.two)
+ self.assertEqual(1, obj.related.one)
+ self.assertEqual(4, obj.related.two)
+
+
class RelatedFactoryExtractionTestCase(unittest.TestCase):
def setUp(self):