fairdm.factories.core#

Key Features#

  1. Minimal by Default: Factories create only required fields unless explicitly requested.

  2. Opt-In Relationships: Use keyword arguments to create descriptions/dates:

    … code-block:: python

    No descriptions or dates created

    project = ProjectFactory()

    Create 2 descriptions

    project = ProjectFactory(descriptions=2)

    Create specific description types, named by address

    project = ProjectFactory( descriptions=2, descriptions__types=[ABSTRACT, f”{DESCRIPTION_TYPES}/introduction”], )

  3. Vocabulary Validation: All description/date types are validated against the collection the model’s type field offers. Invalid types raise ValueError.

  4. Controlled Vocabularies: Default types come from that collection (e.g., ProjectDescription.get_type_concepts()), ensuring factories create valid test data. The vocabularies must be loaded, as the test suite does once per session.

Factories Available#

  • ProjectFactory - Create Project instances with optional descriptions/dates

  • DatasetFactory - Create Dataset instances with optional descriptions/dates

  • SampleFactory - Abstract. The base every specimen factory builds on; it cannot be instantiated directly because the Sample model it declares cannot be created directly either. A reference implementation lives in demo.factories (e.g. RockSampleFactory); a portal defines its own alongside its own specimen types.

  • MeasurementFactory - Abstract. The base every measurement factory builds on; it cannot be instantiated directly because the Measurement model it declares cannot be created directly either. A reference implementation lives in demo.factories (e.g. ExampleMeasurementFactory); a portal defines its own alongside its own measurement types.

Metadata Factories#

  • ProjectDescriptionFactory, DatasetDescriptionFactory, etc.

  • SampleDescriptionFactory, SampleDateFactory, SampleIdentifierFactory, SampleRelationFactory

Usage Examples#

Basic creation::

project = ProjectFactory()
dataset = DatasetFactory(project=project)
from demo.factories import RockSampleFactory

sample = RockSampleFactory(dataset=dataset)

With metadata (opt-in)::

project = ProjectFactory(
    descriptions=2,  # Create 2 descriptions
    dates=1,  # Create 1 date
)

Custom types::

project = ProjectFactory(
    descriptions=2,
    descriptions__types=[ABSTRACT, f"{DESCRIPTION_TYPES}/objectives"],
)

Batch creation::

projects = ProjectFactory.create_batch(5, descriptions=2, dates=1)

Type validation::

# Raises ValueError - the address is not in the project description types
project = ProjectFactory(
    descriptions=1, descriptions__types=[f"{DESCRIPTION_TYPES}/invalid"]
)

For more details, see:

  • Portal developers: docs/developers/how-to/test-a-portal-with-fairdm-factories.md

  • Framework contributors: docs/contributing/testing/

Factories for FairDM’s core models.

These factory_boy factories create test instances of FairDM’s core models: Project, Dataset, Sample, and Measurement. These factories follow an opt-in pattern for creating related metadata objects (descriptions and dates).

Module Contents#

Classes#

ProjectDescriptionFactory

Factory for creating ProjectDescription instances.

ProjectDateFactory

Factory for creating ProjectDate instances.

ProjectIdentifierFactory

Factory for creating ProjectIdentifier instances.

ProjectFactory

Factory for creating Project instances.

DatasetDescriptionFactory

Factory for creating DatasetDescription instances.

DatasetDateFactory

Factory for creating DatasetDate instances.

DatasetIdentifierFactory

Factory for creating DatasetIdentifier instances.

LiteratureItemFactory

Factory for creating literature.Item instances.

DatasetLiteratureRelationFactory

Factory for creating DatasetLiteratureRelation instances.

DatasetFactory

Factory for creating Dataset instances.

SampleDescriptionFactory

Factory for creating SampleDescription instances.

SampleDateFactory

Factory for creating SampleDate instances.

SampleIdentifierFactory

Factory for creating SampleIdentifier instances.

SampleFactory

Abstract factory for creating Sample instances.

MeasurementDescriptionFactory

Factory for creating MeasurementDescription instances.

MeasurementDateFactory

Factory for creating MeasurementDate instances.

MeasurementIdentifierFactory

Factory for creating MeasurementIdentifier instances.

MeasurementFactory

Abstract factory for creating Measurement instances.

SampleRelationFactory

Factory for creating SampleRelation instances.

API#

class ProjectDescriptionFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating ProjectDescription instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class ProjectDateFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating ProjectDate instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class ProjectIdentifierFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating ProjectIdentifier instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class ProjectFactory#

Bases: factory.django.DjangoModelFactory

Factory for creating Project instances.

By default, creates a minimal Project with only required fields.

To create descriptions/dates: ProjectFactory(descriptions=2) # Creates 2 descriptions with default types ProjectFactory(descriptions=2, descriptions__types=[ABSTRACT, f”{DESCRIPTION_TYPES}/objectives”]) ProjectFactory(dates=1) # Creates 1 date with default type ProjectFactory(dates=2, dates__types=[PROJECT_START, PROJECT_END])

Image (opt-in, issue #323): ProjectFactory() # No image, no file written ProjectFactory(with_image=True) # A generated placeholder JPEG ProjectFactory(image=some_file) # That file used directly

class Meta#
model#

None

class Params#
with_image#

‘Trait(…)’

name#

‘Faker(…)’

status#

‘FuzzyChoice(…)’

funding#

‘LazyAttribute(…)’

owner#

‘SubFactory(…)’

descriptions(create, extracted, **kwargs)#

Create descriptions. Pass count as int and optionally types via descriptions__types.

dates(create, extracted, **kwargs)#

Create dates. Pass count as int and optionally types via dates__types.

class DatasetDescriptionFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating DatasetDescription instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class DatasetDateFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating DatasetDate instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class DatasetIdentifierFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating DatasetIdentifier instances.

class Meta#
model#

None

type#

None

value#

‘Sequence(…)’

class LiteratureItemFactory#

Bases: factory.django.DjangoModelFactory

Factory for creating literature.Item instances.

The item is built from a CSL JSON dictionary with literature.converters.from_csl_json, so the DOI, the issued year and the authors are stored as the package stores them.

Args: citation_key: The reference’s key. A unique sequence by default. title: The title. Derived from the citation key by default. type: The CSL item type. article-journal by default. doi: A DOI to store as an identifier. year: The year of the issued date. authors: (family, given) pairs, in order.

class Meta#
model#

‘literature.Item’

citation_key#

‘Sequence(…)’

type#

‘article-journal’

title#

‘LazyAttribute(…)’

doi#

None

year#

None

authors#

()

class DatasetLiteratureRelationFactory#

Bases: factory.django.DjangoModelFactory

Factory for creating DatasetLiteratureRelation instances.

Relates a dataset to a literature item under a DataCite relationship type.

class Meta#
model#

None

dataset#

‘SubFactory(…)’

literature_item#

‘SubFactory(…)’

relationship_type#

‘IsCitedBy’

class DatasetFactory#

Bases: factory.django.DjangoModelFactory

Factory for creating Dataset instances.

By default, creates a minimal Dataset with only required fields. Project is auto-created unless provided.

To create descriptions/dates: DatasetFactory(descriptions=2) # Creates 2 descriptions DatasetFactory(descriptions=2, descriptions__types=[ABSTRACT, f”{DESCRIPTION_TYPES}/methods”]) DatasetFactory(dates=1) # Creates 1 date

Image (opt-in, issue #323): same as ProjectFactory above.

class Meta#
model#

None

class Params#
with_image#

‘Trait(…)’

name#

‘Faker(…)’

project#

‘SubFactory(…)’

license()#

Use the portal’s default licence, creating it when it does not exist yet.

Never the first licence by name: where “CC0 1.0” sorts against “CC BY 4.0” depends on the database’s collation.

descriptions(create, extracted, **kwargs)#

Create descriptions. Pass count as int and optionally types via descriptions__types.

dates(create, extracted, **kwargs)#

Create dates. Pass count as int and optionally types via dates__types.

class SampleDescriptionFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating SampleDescription instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class SampleDateFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating SampleDate instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class SampleIdentifierFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating SampleIdentifier instances.

class Meta#
model#

None

type#

None

value#

‘Sequence(…)’

class SampleFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Abstract factory for creating Sample instances.

Sample is a polymorphic base that cannot be created directly (only a registered specimen type can be) - see fairdm.core.sample.models.Sample’s pre_save guard. This factory declares the fields every specimen shares and is meant to be subclassed, never instantiated on its own. The framework’s reference implementation supplies concrete subclasses in demo.factories (RockSampleFactory, WaterSampleFactory, SoilSampleFactory, …); a portal defines its own alongside its own specimen types.

To create descriptions/dates on a concrete subclass: RockSampleFactory(descriptions=2) RockSampleFactory(dates=1)

class Meta#
model#

None

abstract#

True

name#

‘Faker(…)’

local_id#

‘Faker(…)’

dataset#

‘SubFactory(…)’

location#

None

descriptions(create, extracted, **kwargs)#

Create descriptions. Pass count as int and optionally types via descriptions__types.

dates(create, extracted, **kwargs)#

Create dates. Pass count as int and optionally types via dates__types.

class MeasurementDescriptionFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating MeasurementDescription instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class MeasurementDateFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating MeasurementDate instances.

class Meta#
model#

None

type#

None

value#

‘Faker(…)’

class MeasurementIdentifierFactory#

Bases: fairdm.factories.utils.ConceptFieldFactory

Factory for creating MeasurementIdentifier instances.

class Meta#
model#

None

type#

None

value#

‘Sequence(…)’

class MeasurementFactory#

Bases: factory.django.DjangoModelFactory

Abstract factory for creating Measurement instances.

Measurement is a polymorphic base that cannot be created directly (only a registered measurement type can be) - see fairdm.core.measurement.models.Measurement’s clean guard. This factory declares the fields every measurement shares and is meant to be subclassed, never instantiated on its own. The framework’s reference implementation supplies concrete subclasses in demo.factories (ExampleMeasurementFactory, XRFMeasurementFactory, ICP_MS_MeasurementFactory, …); a portal defines its own alongside its own measurement types.

By default, creates a minimal Measurement with only required fields. Dataset is auto-created if not provided, but sample has no default and must always be passed explicitly: Sample is a polymorphic base that cannot be created directly, and this factory has no concrete specimen type of its own to fall back on (see SampleFactory). Pass a concrete specimen instance, e.g. XRFMeasurementFactory(sample=RockSampleFactory()).

To create descriptions/dates on a concrete subclass: ExampleMeasurementFactory(sample=some_sample, descriptions=2) ExampleMeasurementFactory(sample=some_sample, dates=1)

class Meta#
model#

None

abstract#

True

name#

‘Faker(…)’

dataset#

‘SubFactory(…)’

descriptions(create, extracted, **kwargs)#

Create descriptions. Pass count as int and optionally types via descriptions__types.

dates(create, extracted, **kwargs)#

Create dates. Pass count as int and optionally types via dates__types.

class SampleRelationFactory#

Bases: factory.django.DjangoModelFactory

Factory for creating SampleRelation instances.

Creates a typed relationship between two samples. source and target have no default and must always be provided - both are concrete specimens, and Sample (the class SampleFactory declares) cannot be created directly. Pass concrete specimen instances, e.g. SampleRelationFactory(source=RockSampleFactory(), target=parent).

class Meta#
model#

None

type#

‘child_of’