> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pysquirrels.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SquirrelsProject

> Class to interact with a Squirrels project from Python

This class is used to interact with a Squirrels project from Python.

For example, you can create a `SquirrelsProject` object in Python (or Jupyter Notebook) as such:

```python theme={null}
from squirrels import SquirrelsProject

sqrl = SquirrelsProject(project_path="path/to/squirrels/project/")
```

And then call methods on the `SquirrelsProject` object to perform various operations.

This class can be imported from the `squirrels` module.

## Constructor

Creates a `SquirrelsProject` object.

```python theme={null}
def __init__(
    self, *, project_path: str = ".", load_dotenv_globally: bool = False,
    log_to_file: bool = False, 
    log_level: Literal["DEBUG", "INFO", "WARNING"] = "INFO", 
    log_format: Literal["text", "json"] = "text"
) -> None:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="project_path" type="string" default=".">
    Path to the Squirrels project folder. Defaults to current working directory.
  </ResponseField>

  <ResponseField name="load_dotenv_globally" type="boolean" default={false}>
    If True, loads variables from <code>.env</code> and <code>.env.local</code> into the process environment for the lifetime of this object.
  </ResponseField>

  <ResponseField name="log_to_file" type="boolean" default={false}>
    Whether to enable logging to file(s) in the "logs/" folder (or a custom folder). Default is from SQRL\_LOGGING\_\_TO\_FILE environment variable or false.
  </ResponseField>

  <ResponseField name="log_level" type="string" default="INFO">
    Logging level to include in the log file. One of "DEBUG", "INFO", "WARNING".
  </ResponseField>

  <ResponseField name="log_format" type="string" default="text">
    Format of the log file. One of "text", "json".
  </ResponseField>
</Expandable>

## Methods

Methods that can be invoked from the `SquirrelsProject` object.

### compile()

Async method to compile the SQL templates into files in the "target/" folder. Same functionality as the "sqrl compile" CLI.

```python theme={null}
async def compile(
    self, *, selected_model: str | None = None, test_set: str | None = None, 
    do_all_test_sets: bool = False, runquery: bool = False, clear: bool = False, 
    buildtime_only: bool = False, runtime_only: bool = False
) -> None:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="selected_model" type="string | None" default="None">
    Name of the model to compile. If specified, the compiled SQL is also printed (for SQL models). If None, compiles all models.
  </ResponseField>

  <ResponseField name="test_set" type="string | None" default="None">
    Name of the test set to compile with. If None, uses the default test set (varies by dataset). Ignored if <code>do\_all\_test\_sets</code> is True.
  </ResponseField>

  <ResponseField name="do_all_test_sets" type="boolean" default={false}>
    Compile all applicable test sets for the selected dataset(s). If True, <code>test\_set</code> is ignored.
  </ResponseField>

  <ResponseField name="runquery" type="boolean" default={false}>
    Run all compiled queries and save each result as CSV (runtime only). If True and <code>selected\_model</code> is specified, all upstream models of the selected model are compiled as well.
  </ResponseField>

  <ResponseField name="clear" type="boolean" default={false}>
    Clear the entire <code>target/compile/</code> folder before compiling.
  </ResponseField>

  <ResponseField name="buildtime_only" type="boolean" default={false}>
    Compile only buildtime (static/build) models.
  </ResponseField>

  <ResponseField name="runtime_only" type="boolean" default={false}>
    Compile only runtime (dbviews/federates) models.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="None">No return value.</ResponseField>

### get\_all\_data\_models()

Async method to list all data models in the project.

```python theme={null}
async def get_all_data_models(self) -> list[DataModelItem]:
```

<ResponseField name="returns" type="list[DataModelItem]">
  A list of DataModelItem objects. The DataModelItem object has the following properties:

  <Expandable title="DataModelItem properties">
    <ResponseField name="name" type="string">
      The name of the model.
    </ResponseField>

    <ResponseField name="model_type" type="string">
      The type of the model.
    </ResponseField>

    <ResponseField name="config" type="object">
      The configuration of the model.
    </ResponseField>

    <ResponseField name="is_queryable" type="boolean">
      Whether the model is queryable.
    </ResponseField>
  </Expandable>
</ResponseField>

### get\_all\_data\_lineage()

Async method to retrieve lineage across models, datasets, and dashboards.

```python theme={null}
async def get_all_data_lineage(self) -> list[LineageRelation]:
```

<ResponseField name="returns" type="LineageRelation[]">
  A list of LineageRelation objects. The LineageRelation object has the following properties:

  <Expandable title="LineageRelation properties">
    <ResponseField name="type" type="Literal['buildtime', 'runtime']">
      The type of the lineage relation.
    </ResponseField>

    <ResponseField name="source" type="LineageNode">
      The source of the lineage relation. A LineageNode object (defined below).
    </ResponseField>

    <ResponseField name="target" type="LineageNode">
      The target of the lineage relation. A LineageNode object (defined below).
    </ResponseField>
  </Expandable>

  <Expandable title="LineageNode properties">
    <ResponseField name="name" type="string">
      The name of the node.
    </ResponseField>

    <ResponseField name="type" type="Literal['model', 'dataset', 'dashboard']">
      The type of the node.
    </ResponseField>
  </Expandable>
</ResponseField>

### seed()

Method to retrieve a seed as a polars LazyFrame given a seed name.

```python theme={null}
def seed(self, name: str) -> polars.LazyFrame:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="name" type="string" required>
    Name of the seed to retrieve.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="polars.LazyFrame">A polars LazyFrame of the seed data.</ResponseField>

### build()

Async method to build the virtual data environment. Same functionality as the "sqrl build" CLI.

```python theme={null}
async def build(
  self, *, full_refresh: bool = False, select: str | None = None
) -> None:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="full_refresh" type="boolean" default={false}>
    Drop all tables and rebuild the virtual data environment from scratch.
  </ResponseField>

  <ResponseField name="select" type="string | None" default="None">
    Name of a single data model to build; if None, builds all data models.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="None">No return value.</ResponseField>

### dataset\_metadata()

Method to retrieve the metadata (descriptions, columns, etc.) for a dataset.

```python theme={null}
def dataset_metadata(self, name: str) -> DatasetMetadata:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="name" type="string" required>
    Name of the dataset to retrieve metadata for.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="DatasetMetadata">A [DatasetMetadata] object.</ResponseField>

### dataset\_result()

Async method to retrieve the dataset result given parameter selections.

Unlike the `dataset` method of [DashboardArgs], this method returns a [DatasetResult] object (which includes metadata) instead of a polars DataFrame. Furthermore, while the [DashboardArgs] method automatically borrows selections applied to the dashboard, this method requires selections to be explicitly provided through code.

```python theme={null}
async def dataset_result(
    self, name: str, *, selections: dict[str, Any] = {}, 
    user: RegisteredUser | None = None, configurables: dict[str, str] = {}
) -> DatasetResult:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="name" type="string" required>
    Name of the dataset to retrieve.
  </ResponseField>

  <ResponseField name="selections" type="dict[str, Any]" default={{}}>
    Parameter selections to apply to the dataset.
  </ResponseField>

  <ResponseField name="user" type="RegisteredUser | None" default="None">
    [RegisteredUser] object to use for authentication. If None, a guest user with default values for custom user fields is used.

    Since this method fetches the dataset through code instead of the API, this user is not used to check access on the scope of the dataset. Instead, this argument is more applicable for applying user attributes to the dataset result.
  </ResponseField>

  <ResponseField name="configurables" type="dict[str, str]" default={{}}>
    Optional overrides for configurable placeholders defined in your project.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="DatasetResult">A [DatasetResult] object.</ResponseField>

### dashboard()

Async method to retrieve a dashboard given parameter selections.

```python theme={null}
async def dashboard(
    self, name: str, *, selections: dict[str, Any] = {}, 
    user: RegisteredUser | None = None, 
    dashboard_type: type[PngDashboard | HtmlDashboard] = PngDashboard, 
    configurables: dict[str, str] = {}
) -> PngDashboard | HtmlDashboard:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="name" type="string" required>
    The name of the dashboard to retrieve.
  </ResponseField>

  <ResponseField name="selections" type="dict[str, Any]" default={{}}>
    Parameter selections to apply to the dashboard.
  </ResponseField>

  <ResponseField name="user" type="RegisteredUser | None" default="None">
    [RegisteredUser] object to use for authentication. If None, a guest user with default values for custom user fields is used.
  </ResponseField>

  <ResponseField name="dashboard_type" type="type[PngDashboard | HtmlDashboard]" default="PngDashboard">
    Return type used for type hints (if you rely on them). For example, provide [PngDashboard] to return a [PngDashboard].
  </ResponseField>

  <ResponseField name="configurables" type="dict[str, str]" default={{}}>
    Optional overrides for configurable placeholders defined in your project.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="PngDashboard | HtmlDashboard">
  A [PngDashboard] or [HtmlDashboard] object based on <code>dashboard\_type</code>.
</ResponseField>

### query\_models()

Async method to query the data models with SQL given parameter selections.

```python theme={null}
async def query_models(
    self, sql_query: str, *, selections: dict[str, Any] = {}, 
    user: RegisteredUser | None = None, configurables: dict[str, str] = {}
) -> DatasetResult:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="sql_query" type="string" required>
    SQL query to execute.
  </ResponseField>

  <ResponseField name="selections" type="dict[str, Any]" default={{}}>
    Parameter selections to apply to the data models.
  </ResponseField>

  <ResponseField name="user" type="RegisteredUser | None" default="None">
    [RegisteredUser] object to use for attributes of authenticated user. If None, a guest user with default values for custom user fields is used.
  </ResponseField>

  <ResponseField name="configurables" type="dict[str, str]" default={{}}>
    Optional overrides for configurable placeholders defined in your project.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="DatasetResult">A [DatasetResult] object.</ResponseField>

### get\_compiled\_model\_query()

Async method to compile a specific data model and return its language and compiled definition.

```python theme={null}
async def get_compiled_model_query(
    self, model_name: str, *, selections: dict[str, Any] = {}, 
    user: RegisteredUser | None = None, configurables: dict[str, str] = {}
) -> CompiledQueryModel:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="model_name" type="string" required>
    Name of the data model to compile.
  </ResponseField>

  <ResponseField name="selections" type="dict[str, Any]" default={{}}>
    Parameter selections to apply during compilation.
  </ResponseField>

  <ResponseField name="user" type="RegisteredUser | None" default="None">
    [RegisteredUser] object to use for attributes of authenticated user. If None, a guest user with default values for custom user fields is used.
  </ResponseField>

  <ResponseField name="configurables" type="dict[str, str]" default={{}}>
    Optional overrides for configurable placeholders defined in your project.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="CompiledQueryModel">
  A CompiledQueryModel object with <code>language</code>, <code>definition</code>, and <code>placeholders</code>.
</ResponseField>

### get\_fastapi\_components()

Get the FastAPI components for the Squirrels project including mount path, lifespan, and FastAPI app.

```python theme={null}
def get_fastapi_components(
    self, *, no_cache: bool = False, host: str | None = None, port: int | None = None, 
    mount_path_format: str = "/analytics/{project_name}/v{project_version}"
) -> FastAPIComponents:
```

<Expandable title="arguments" defaultOpen>
  <ResponseField name="no_cache" type="boolean" default={false}>
    Whether to disable caching for parameter options, datasets, and dashboard results in the API server.
  </ResponseField>

  <ResponseField name="host" type="string" default="localhost">
    The host the API server will listen on. Only used for the welcome banner.
  </ResponseField>

  <ResponseField name="port" type="integer" default="8000">
    The port the API server will listen on. Only used for the welcome banner.
  </ResponseField>

  <ResponseField name="mount_path_format" type="string" default="/analytics/{project_name}/v{project_version}">
    The format of the mount path. Use {project_name} and {project_version} as placeholders.

    Any underscores ("\_") in the project name are replaced by dash ("-") for the API path for the {project_name} placeholder.
  </ResponseField>
</Expandable>

<ResponseField name="returns" type="FastAPIComponents">
  A [FastAPIComponents] object with properties:

  * `mount_path` (str): The mount path for the Squirrels project.
  * `lifespan` (AsyncGeneratorContextManager): The lifespan context manager for the Squirrels project.
  * `fastapi_app` (FastAPI): The FastAPI app for the Squirrels project.
</ResponseField>

### close()

Use this method to deliberately close any database connections opened by the `SquirrelsProject` object.

The database connections may still be opened again by other methods invoked on the `SquirrelsProject` object after this method is called.

```python theme={null}
def close(self) -> None:
```

<ResponseField name="returns" type="None">No return value.</ResponseField>

## Examples

Here are some common usage patterns for the `SquirrelsProject` class. It is assumed that the code is running in an async context (e.g. inside an async function or a Jupyter Notebook cell).

### Basic project initialization

```python theme={null}
from squirrels import SquirrelsProject

# Initialize with default settings (current directory)
sqrl = SquirrelsProject()

# Initialize with specific project path
sqrl = SquirrelsProject(project_path="path/to/project")

# Initialize with environment variables and file logging
sqrl = SquirrelsProject(
    project_path="path/to/project",
    log_format="json",
    log_level="DEBUG"
)
```

### Compiling and building models

```python theme={null}
from squirrels import SquirrelsProject

sqrl = SquirrelsProject()

# Compile all models
await sqrl.compile()

# Compile a specific model and print its SQL
await sqrl.compile(selected_model="my_model")

# Compile with a specific test set
await sqrl.compile(test_set="test_set_1")

# Build the virtual data environment
await sqrl.build()

# Full refresh build (drop and rebuild everything)
await sqrl.build(full_refresh=True)

# Build only a specific model
await sqrl.build(select="my_model")
```

### Querying a dataset

```python theme={null}
from squirrels import SquirrelsProject

sqrl = SquirrelsProject()

# Get dataset metadata
metadata = sqrl.dataset_metadata("sales_data")
print(f"Description: {metadata.target_model_config.description}")
print(f"Columns: {[col.name for col in metadata.target_model_config.columns]}")

# Query a dataset with parameter selections
result = await sqrl.dataset_result(
    "sales_data",
    selections={
        "date_range": ["2024-01-01", "2024-12-31"],
        "region": "north-america"
    }
)

# The result.df attribute is a polars DataFrame
print(result.df.head())

# Convert to pandas if needed
pandas_df = result.df.to_pandas()
print(pandas_df.head())
```

### Working with authentication

```python theme={null}
from squirrels import SquirrelsProject
from squirrels.auth import RegisteredUser, CustomUserFields

from pyconfigs.user import CustomUserFields

sqrl = SquirrelsProject()

# Note: CustomUserFields must be extended in your project's user.py
custom_fields = CustomUserFields()  # Use your extended class

# Create a registered user with custom fields
user = RegisteredUser(username="john_doe", custom_fields=custom_fields)

# Query dataset as authenticated user
result = await sqrl.dataset_result(
    "protected_data",
    selections={"year": "2024"},
    user=user
)

# Querying protected datasets with code also allows for bypassing authentication
result = await sqrl.dataset_result(
    "protected_data",
    selections={"year": "2024"}
)

# Access the polars DataFrame
print(result.df)
```

### Working with dashboards

Render a PNG dashboard in a Jupyter Notebook:

```python theme={null}
from squirrels import SquirrelsProject
from squirrels.dashboards import PngDashboard, HtmlDashboard

sqrl = SquirrelsProject()

# Get a PNG dashboard
png_dashboard = await sqrl.dashboard(
    "sales_overview",
    selections={"quarter": "Q1"},
    dashboard_type=PngDashboard
)
png_dashboard
```

Render an HTML dashboard in a Jupyter Notebook:

```python theme={null}
from squirrels import SquirrelsProject
from squirrels.dashboards import HtmlDashboard

sqrl = SquirrelsProject()

# Get an HTML dashboard
html_dashboard = await sqrl.dashboard(
    "interactive_report",
    selections={"year": "2024"},
    dashboard_type=HtmlDashboard
)
html_dashboard
```

### Querying models directly

```python theme={null}
from squirrels import SquirrelsProject

sqrl = SquirrelsProject()

# Query models using custom SQL
result = await sqrl.query_models(
    "SELECT * FROM my_model WHERE amount > 1000",
    selections={"date_param": "2024-01-01"}
)

# Access the polars DataFrame
print(result.df)

# Get compiled query for a specific model
compiled = await sqrl.get_compiled_model_query(
    "my_model",
    selections={"region": "west"}
)

print(f"Language: {compiled.language}")
print(f"Query:\n{compiled.definition}")
```

### Working with seeds

```python theme={null}
from squirrels import SquirrelsProject

sqrl = SquirrelsProject()

# Get a seed as a polars LazyFrame
seed_lf = sqrl.seed("lookup_table")

# Collect and print the data
df = seed_lf.collect()
print(df)
```

### Exploring project metadata

```python theme={null}
from squirrels import SquirrelsProject

sqrl = SquirrelsProject()

# List all data models
models = await sqrl.get_all_data_models()
for model in models:
    print(f"{model.name} ({model.model_type}): queryable={model.is_queryable}")

# Get data lineage
lineage = await sqrl.get_all_data_lineage()
for relation in lineage:
    print(f"{relation.source.name} ({relation.source.type}) -> "
          f"{relation.target.name} ({relation.target.type}) [{relation.type}]")
```

### Close database connections

```python theme={null}
from squirrels import SquirrelsProject

sqrl = SquirrelsProject()

# Perform operations...

# Close database connections associated with the project when done
sqrl.close()
```

[DatasetMetadata]: /references/python/types/datasetmetadata

[DatasetResult]: /references/python/types/datasetresult

[RegisteredUser]: /references/python/auth/registereduser

[PngDashboard]: /references/python/dashboards/pngdashboard

[HtmlDashboard]: /references/python/dashboards/htmldashboard

[DashboardArgs]: /references/python/arguments/dashboardargs

[FastAPIComponents]: /references/python/types/fastapicomponents
