Skip to content

Conversation

@leoschwarz
Copy link
Collaborator

No description provided.

@leoschwarz
Copy link
Collaborator Author

leoschwarz commented Jul 9, 2025

new deploy snippet

pkg_version=$(uv version --short)
uv build -o "dist/$pkg_version"
uv lock -U
uv export --no-emit-project --format pylock.toml > "dist/$pkg_version/pylock.toml"
rm -f "dist/$pkg_version/.gitignore"

@leoschwarz
Copy link
Collaborator Author

Snippet for core bfabric package.

# B-Fabric Entities

## Overview

The `bfabric.entities` module offers a high-level, **read-only** API for retrieval of entities in the B-Fabric system. This API simplifies entity access by providing lazy-loading capabilities for associated entities.

## User Guide

### Getting Started

To use the entities module, you need a configured B-Fabric client:

```python
from bfabric import Bfabric
from bfabric.entities import Project, Sample

client = Bfabric(...)  # Initialize with your configuration

# Find an entity by ID
project = Project.find(id=123, client=client)

# Access entity data
project_name = project["name"]
project_id = project.id

Finding Entities

The module provides several methods for retrieving entities:

# Find a single entity
project = Project.find(id=123, client=client)

# Find multiple entities efficiently
project_ids = [123, 456, 789]
projects = Project.find_all(ids=project_ids, client=client)

# Find entities matching a query
matching_projects = Project.find_by({"name": "My Project"}, client=client)

When working with multiple entities, always prefer find_all and find_by over repeated calls to find.

Working with Relationships

Entities can have relationships with other entities, defined using HasOne and HasMany descriptors:

# One-to-one relationship
sample = Sample.find(id=123, client=client)
project = sample.project  # Automatically loads the related project

# One-to-many relationship
project = Project.find(id=456, client=client)
for sample in project.samples:  # Automatically loads all related samples
    print(sample.id)

# Access just the IDs without loading entities
sample_ids = project.samples.ids

# Convert to a list or DataFrame
samples_list = project.samples.list
samples_df = project.samples.polars

Performance Tips

For optimal performance:

  1. Use find_all and find_by for retrieving multiple entities
  2. Access only the data you need (e.g., use .ids when you only need the IDs)
  3. Be aware that accessing a relationship property triggers an API request if the related entity hasn't been loaded
  4. Consider using the EntityLookupCache for frequently accessed entities

Developer Guide

This section is for developers who want to extend or modify the bfabric.entities module.

Module Structure

The module consists of several components:

  • Entity: Base class for all entity types
  • Relationship: Base class for relationship descriptors
  • HasOne: Descriptor for one-to-one relationships
  • HasMany: Descriptor for one-to-many relationships
  • Mixins like HasContainerMixin to add common functionality

Creating a New Entity Type

To create a new entity type:

from bfabric.entities.core.entity import Entity
from bfabric.entities.core.has_one import HasOne
from bfabric.entities.core.has_many import HasMany

class MyEntity(Entity):
    ENDPOINT = "MyEntityEndpoint"  # B-Fabric endpoint name
    
    # Define relationships
    parent = HasOne("ParentEntity", bfabric_field="parent")
    children = HasMany("ChildEntity", bfabric_field="children")
    
    # Add custom methods if needed
    def custom_method(self):
        return f"Custom functionality for {self.id}"

Design Principles

When extending the module, follow these principles:

  1. Read-Only Operations: Do not modify B-Fabric data through this module
  2. Lazy-Loading: Load related entities only when needed
  3. Avoid Circular Imports: Defer imports of other entities inside methods
  4. Modular Design: Keep entity classes focused on their core functionality

Entity Lookup Cache

The EntityLookupCache provides caching for entity instances:

from bfabric.experimental.entity_lookup_cache import EntityLookupCache

# Singleton instance
cache = EntityLookupCache.instance()

# Cache operations
cache.put(entity_type=MyEntity, entity_id=123, entity=my_entity)
cached_entity = cache.get(entity_type=MyEntity, entity_id=123)

API Reference

.. autoclass:: bfabric.entities.core.entity.Entity
    :members:
    :undoc-members:
    :special-members: __init__, __getitem__, __contains__
    :exclude-members: __dict__, __weakref__, __module__, __str__

.. autoclass:: bfabric.entities.core.has_one.HasOne
    :members:
    :undoc-members:
    :special-members: __init__, __get__

.. autoclass:: bfabric.entities.core.has_many.HasMany
    :members:
    :undoc-members:
    :special-members: __init__, __get__

.. autoclass:: bfabric.entities.core.has_many._HasManyProxy
    :members:
    :undoc-members:
    :special-members: __getitem__, __iter__, __len__

.. autoclass:: bfabric.entities.core.has_container_mixin.HasContainerMixin
    :members:
    :undoc-members:

.. autoclass:: bfabric.entities.core.relationship.Relationship
    :members:
    :undoc-members:
    :special-members: __init__

Key Features

  • Read-Only Access: This module is strictly for read-only operations
  • Lazy-Loading: Associated entities are not loaded until explicitly requested
  • Modular Design: Only generic functionality is included to ensure maintainability
  • Type Safety: Fully typed with Python type hints for better IDE support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants