summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--factory/__init__.py6
-rw-r--r--factory/base.py68
-rw-r--r--factory/containers.py22
-rw-r--r--factory/declarations.py24
4 files changed, 60 insertions, 60 deletions
diff --git a/factory/__init__.py b/factory/__init__.py
index 650f572..bf0fca2 100644
--- a/factory/__init__.py
+++ b/factory/__init__.py
@@ -1,15 +1,15 @@
# Copyright (c) 2010 Mark Sandstrom
-#
+#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
diff --git a/factory/base.py b/factory/base.py
index 5f712a2..d7c40c1 100644
--- a/factory/base.py
+++ b/factory/base.py
@@ -1,15 +1,15 @@
# Copyright (c) 2010 Mark Sandstrom
-#
+#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -33,7 +33,7 @@ STUB_STRATEGY = 'stub'
# Creation functions. Use Factory.set_creation_function() to set a creation function appropriate for your ORM.
DJANGO_CREATION = lambda class_to_create, **kwargs: class_to_create.objects.create(**kwargs)
-
+
# Special declarations
FACTORY_CLASS_DECLARATION = 'FACTORY_FOR'
@@ -56,10 +56,10 @@ def get_factory_base(bases):
class BaseFactoryMetaClass(type):
'''Factory metaclass for handling ordered declarations.'''
-
+
def __call__(cls, **kwargs):
'''Create an associated class instance using the default build strategy. Never create a Factory instance.'''
-
+
if cls.default_strategy == BUILD_STRATEGY:
return cls.build(**kwargs)
elif cls.default_strategy == CREATE_STRATEGY:
@@ -68,16 +68,16 @@ class BaseFactoryMetaClass(type):
return cls.stub(**kwargs)
else:
raise BaseFactory.UnknownStrategy('Unknown default_strategy: {0}'.format(cls.default_strategy))
-
+
def __new__(cls, class_name, bases, dict, extra_dict={}):
'''Record attributes (unordered declarations) and ordered declarations for construction of
an associated class instance at a later time.'''
-
+
base = get_factory_base(bases)
if not base:
# If this isn't a subclass of Factory, don't do anything special.
return super(BaseFactoryMetaClass, cls).__new__(cls, class_name, bases, dict)
-
+
ordered_declarations = getattr(base, CLASS_ATTRIBUTE_ORDERED_DECLARATIONS, [])
unordered_declarations = getattr(base, CLASS_ATTRIBUTE_UNORDERED_DECLARATIONS, [])
@@ -95,7 +95,7 @@ class BaseFactoryMetaClass(type):
dict[CLASS_ATTRIBUTE_ORDERED_DECLARATIONS] = ordered_declarations
dict[CLASS_ATTRIBUTE_UNORDERED_DECLARATIONS] = unordered_declarations
-
+
for name, value in extra_dict.iteritems():
dict[name] = value
@@ -103,26 +103,26 @@ class BaseFactoryMetaClass(type):
class FactoryMetaClass(BaseFactoryMetaClass):
'''Factory metaclass for handling class association and ordered declarations.'''
-
+
ERROR_MESSAGE = '''Could not determine what class this factory is for.
Use the {0} attribute to specify a class.'''
ERROR_MESSAGE_AUTODISCOVERY = ERROR_MESSAGE + '''
Also, autodiscovery failed using the name '{1}'
based on the Factory name '{2}' in {3}.'''
-
+
def __new__(cls, class_name, bases, dict):
'''Determine the associated class based on the factory class name. Record the associated class
for construction of an associated class instance at a later time.'''
-
+
base = get_factory_base(bases)
if not base:
# If this isn't a subclass of Factory, don't do anything special.
return super(FactoryMetaClass, cls).__new__(cls, class_name, bases, dict)
-
+
inherited_associated_class = getattr(base, CLASS_ATTRIBUTE_ASSOCIATED_CLASS, None)
own_associated_class = None
used_auto_discovery = False
-
+
if FACTORY_CLASS_DECLARATION in dict:
own_associated_class = dict[FACTORY_CLASS_DECLARATION]
del dict[FACTORY_CLASS_DECLARATION]
@@ -136,41 +136,41 @@ class FactoryMetaClass(BaseFactoryMetaClass):
own_associated_class = getattr(factory_module, associated_class_name)
except AttributeError:
pass
-
+
if own_associated_class != None and inherited_associated_class != None and own_associated_class != inherited_associated_class:
format = 'These factories are for conflicting classes: {0} and {1}'
raise Factory.AssociatedClassError(format.format(inherited_associated_class, own_associated_class))
elif inherited_associated_class != None:
own_associated_class = inherited_associated_class
-
+
if not own_associated_class and used_auto_discovery:
format_args = FACTORY_CLASS_DECLARATION, associated_class_name, class_name, factory_module
raise Factory.AssociatedClassError(FactoryMetaClass.ERROR_MESSAGE_AUTODISCOVERY.format(*format_args))
elif not own_associated_class:
raise Factory.AssociatedClassError(FactoryMetaClass.ERROR_MESSAGE.format(FACTORY_CLASS_DECLARATION))
-
+
extra_dict = {CLASS_ATTRIBUTE_ASSOCIATED_CLASS: own_associated_class}
- return super(FactoryMetaClass, cls).__new__(cls, class_name, bases, dict, extra_dict=extra_dict)
+ return super(FactoryMetaClass, cls).__new__(cls, class_name, bases, dict, extra_dict=extra_dict)
# Factory base classes
class BaseFactory(object):
'''Factory base support for sequences, attributes and stubs.'''
-
+
class UnknownStrategy(RuntimeError): pass
class UnsupportedStrategy(RuntimeError): pass
-
+
def __new__(cls, *args, **kwargs):
raise RuntimeError('You cannot instantiate BaseFactory')
-
+
_next_sequence = 0
-
+
@classmethod
def _generate_next_sequence(cls):
next_sequence = cls._next_sequence
cls._next_sequence += 1
return next_sequence
-
+
@classmethod
def attributes(cls, **kwargs):
attributes = {}
@@ -195,15 +195,15 @@ class BaseFactory(object):
attributes[name] = kwargs[name]
return attributes
-
+
@classmethod
def build(cls, **kwargs):
raise cls.UnsupportedStrategy()
-
+
@classmethod
def create(cls, **kwargs):
raise cls.UnsupportedStrategy()
-
+
@classmethod
def stub(cls, **kwargs):
stub_object = StubObject()
@@ -218,15 +218,15 @@ class StubFactory(BaseFactory):
class Factory(BaseFactory):
'''Factory base with build and create support.
-
+
This class has the ability to support multiple ORMs by using custom creation functions.'''
-
+
__metaclass__ = FactoryMetaClass
-
+
default_strategy = CREATE_STRATEGY
-
+
class AssociatedClassError(RuntimeError): pass
-
+
_creation_function = (DJANGO_CREATION,) # Using a tuple to keep the creation function from turning into an instance method
@classmethod
def set_creation_function(cls, creation_function):
@@ -234,11 +234,11 @@ class Factory(BaseFactory):
@classmethod
def get_creation_function(cls):
return cls._creation_function[0]
-
+
@classmethod
def build(cls, **kwargs):
return getattr(cls, CLASS_ATTRIBUTE_ASSOCIATED_CLASS)(**cls.attributes(**kwargs))
-
+
@classmethod
def create(cls, **kwargs):
return cls.get_creation_function()(getattr(cls, CLASS_ATTRIBUTE_ASSOCIATED_CLASS), **cls.attributes(**kwargs))
diff --git a/factory/containers.py b/factory/containers.py
index 08f0450..023055c 100644
--- a/factory/containers.py
+++ b/factory/containers.py
@@ -1,15 +1,15 @@
# Copyright (c) 2010 Mark Sandstrom
-#
+#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -20,28 +20,28 @@
class ObjectParamsWrapper(object):
'''A generic container that allows for getting but not setting of attributes.
-
+
Attributes are set at initialization time.'''
-
+
initialized = False
-
+
def __init__(self, dict):
self.dict = dict
self.initialized = True
-
+
def __setattr__(self, name, value):
if not self.initialized:
return super(ObjectParamsWrapper, self).__setattr__(name, value)
else:
raise AttributeError('Setting of object attributes is not allowed')
-
+
def __getattr__(self, name):
try:
return self.dict[name]
except KeyError:
raise AttributeError("The param '{0}' does not exist. Perhaps your declarations are out of order?".format(name))
-
+
class StubObject(object):
'''A generic container.'''
-
- pass \ No newline at end of file
+
+ pass
diff --git a/factory/declarations.py b/factory/declarations.py
index 37c8cbd..cf54f07 100644
--- a/factory/declarations.py
+++ b/factory/declarations.py
@@ -1,15 +1,15 @@
# Copyright (c) 2010 Mark Sandstrom
-#
+#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -20,34 +20,34 @@
class OrderedDeclaration(object):
'''A factory declaration.
-
+
Ordered declarations keep track of the order in which they're defined so that later declarations
can refer to attributes created by earlier declarations when the declarations are evaluated.'''
_next_order = 0
-
+
def __init__(self):
self.order = self.next_order()
-
+
@classmethod
def next_order(cls):
next_order = cls._next_order
cls._next_order += 1
return next_order
-
+
def evaluate(self, factory, attributes):
'''Evaluate this declaration.
-
+
Args:
factory: The factory this declaration was defined in.
attributes: The attributes created by the unordered and ordered declarations up to this point.'''
-
+
raise NotImplementedError('This is an abstract method')
class LazyAttribute(OrderedDeclaration):
def __init__(self, function):
super(LazyAttribute, self).__init__()
self.function = function
-
+
def evaluate(self, factory, attributes):
return self.function(attributes)
@@ -56,7 +56,7 @@ class Sequence(OrderedDeclaration):
super(Sequence, self).__init__()
self.function = function
self.type = type
-
+
def evaluate(self, factory, attributes):
return self.function(self.type(factory.sequence))
@@ -73,4 +73,4 @@ def sequence(func):
return Sequence(func)
def lazy_attribute_sequence(func):
- return LazyAttributeSequence(func) \ No newline at end of file
+ return LazyAttributeSequence(func)