Tyler Smith
Posted on July 27, 2024
Before language server powered autocomplete was ubiquitous, it didn't matter if code was written in a way that made autocomplete easy. Popular text editors like Sublime weren't able to understand code enough to provide meaningful suggestions. Programmers either memorized the commands of their dependencies or they referenced the documentation.
In 2024 autocomplete is everywhere, but our packages haven't necessarily made its job easy. Take this example from Factory Boy's documentation:
import factory
from datetime import datetime
from .models import User
class UserFactory(factory.Factory):
class Meta:
model = User
arrival = factory.Faker(
'date_between_dates',
date_start=datetime.date(2020, 1, 1),
date_end=datetime.date(2020, 5, 31),
)
The arrival
attribute calls Faker's date_between_dates()
method. Unfortunately, factory.Faker()
does not tell you what Faker methods are available, and it won't tell you what parameters a Faker method accepts once you select one. This code mitigates the benefits that language servers provide.
Autocompleting Faker in factories
You can get autocomplete while using Faker with factory_boy
by wrapping a Faker call in factory.LazyFunction()
:
import factory
from datetime import datetime
from .models import User
fake = Faker()
class UserFactory(factory.Factory):
class Meta:
model = User
arrival = factory.LazyFunction(lambda: fake.date_between_dates(
date_start=datetime.date(2020, 1, 1),
date_end=datetime.date(2020, 5, 31),
))
Functions passed to factory.LazyFunction()
evaluate when the factory creates an instance. We wrap our faker call in a lambda so we can provide it arguments. And your language server can show you what parameters fake.date_between_dates()
accepts.
There's less set-up when the faker function doesn't need any arguments. Here is how you could use factory.LazyFunction()
with Faker's first_name()
and last_name()
methods:
import factory
from datetime import datetime
from .models import User
fake = Faker()
class UserFactory(factory.Factory):
class Meta:
model = User
first_name = factory.LazyFunction(fake.first_name)
last_name = factory.LazyFunction(fake.last_name)
The biggest advantage of using factory.LazyFunction()
is that it doesn't just work for Faker: you can use it to get factory_boy
to call any function. The resulting code is a little longer than it would be if we had used factory.Faker()
, but the assistance from the language server is worth it to me. Without it, I might need to constantly check documentation.
If it's too much to type, you can alias it to something shorter such as LazyFn
:
from factory import Factory, LazyFunction as LazyFn
from datetime import datetime
from .models import User
fake = Faker()
class UserFactory(Factory):
class Meta:
model = User
first_name = LazyFn(fake.first_name)
last_name = LazyFn(fake.last_name)
Posted on July 27, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.