factory_boy
factory_boy copied to clipboard
Add Dynamodb ORM Factory
The problem
I haven't found support for creating a factory with the Dynamodb ORM pynamodb. Sometimes I use a django-supported ORM for which the DjangoModelFactory
works great, and sometimes I need a NoSQL DB.
Proposed solution
I assume this would include implementing the base.Factory
interface, though I'm pretty unfamiliar with what's under the hood of factory_boy.
Edit: ORM (Object Relational Mapping) for a NoSQL DB is a misnomer :-P ONSQLM (Object NoSQL Mapping) would be more appropriate
Hi, and thanks for the suggestion!
It brings two subjects to mind: explaining how this base class can be built; and deciding where that code should live.
Coding the PynamoModelFactory
class
The simplest way is to take a look at the MogoFactory
or MongoEngineFactory
.
The first step is to create a subclass of base.Factory
, mark it as abstract, and override its _build
and _create
functions:
class PynamoModelFactory(base.Factory):
class Meta:
abstract = True
@classmethod
def _build(cls, model_class, *args, **kwargs):
return model_class.some_builder(*args, **kwargs)
@classmethod
def _create(cls, model_class, *args, **kwargs):
# Assuming the `.create()` is actually build+save
obj = cls._build(model_class, *args, **kwargs)
obj.save()
return obj
If the mapper needs additional settings (for instance emulating the django_get_or_create
part), or if you want advanced syntax to find the model, you'll have to add a custom FactoryOptions
subclass (cf. DjangoOptions
), and attach it at YourFactory._options_class
.
Hosting the code
Including factory classes for other ODMs (Object Database Mapper?) within FactoryBoy's codebase is useful to end users; however, it requires the maintainers of the project to have some insight as to how that DB adapter actually works — for instance, MogoFactory
or MongoEngineFactory
don't provide the same amount of features as DjangoModelFactory
or SQLAlchemyModelFactory
.
For this PynamoFactory
, once the code exists, I see two options:
- You create (and maintain) a
pynamo_factory_boy
project — we would be happy to welcome it within theFactoryBoy
org; - You join the FactoryBoy maintainers, so that someone on the team can handle issues about it.
What do you think?
Thanks for considering the request and the initial ideas on implementation. I'd prefer the option of joining the FactoryBoy maintainers, though I'm not positive I'll have the expertise to implement the Pynamo ODM (good suggestion). I'll take a stab at a pull request and if it goes alright within a reasonable amount of time I'd be happy to support the project.
For testing locally against DynamoDB, I'm considering adding a docker container provided by AWS. See the Docker tab in https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html. I suspect this would be the least overhead for new contributors, though I am of course new to this project and am not familiar with your ecosystem.
Would AWS Docker container work in your project?
The other options I see are
- different DynamoDB docker container maintained in localstack: https://github.com/localstack/localstack
- running the AWS-provided DynamoDB JAR on the host machine
@ezbc @rbarrois
Can I join the effort? I need a sound fixture replacement tool for my project (DynamoDB + PynamoDB), 'cuz those plain dictionary fixtures I have right now have started to go out of hands.
Hey @ezbc, a Pynamo ODM would make things a lot easier for me too, so I'd love to pitch in where I can. Any chance you've made some progress on that PR?
For the time being, I'm seeing some success using a (very slightly) adapted version of @rbarrois's snippet:
Pynamo ODM
from typing import Type
import factory
from pynamodb.models import Model
class PynamoModelFactory(factory.Factory):
@classmethod
def _build(cls, model_class: Type[BaseModel], *args, **kwargs):
return model_class(*args, **kwargs)
@classmethod
def _create(cls, model_class: Type[BaseModel], *args, **kwargs):
obj = cls._build(model_class, *args, **kwargs)
obj.save()
return obj
@tasercake @g-kisenkov sorry, I started and changed focus so I don't have anything for this. @tasercake could you share the adapted version of the Pynamo factory snippet? I'm curious what it looks like.