Python library tools

This page is what pip install featuremesh gives you: BatchClient, Jupyter magic, sltest, and AccessClient. It does not start an HTTP or MCP server — those wrappers live in the demos repo .

Install and connection modes: Python library .

from featuremesh import BatchClient

client = BatchClient()
client.query("RETURN F := 1;")
client.translate("RETURN F := 1;")
client.validate("RETURN F := 1;")
python

Run and inspect

You want to…Call
Run FeatureQL and get rowsquery
See the generated SQL without running ittranslate

query returns a QueryResult with dataframe, sql, errors, and warnings. translate returns sql and errors only.

validate — check a draft before you trust it

validate does not return business rows. It:

  1. Normalizes syntax with FORMAT (FIX)
  2. Builds the feature graph (types, grain, dependencies)
  3. Dry-runs the generated SQL when an executor is available
result = client.validate("""
    RETURN A := 1, B := A + 1;
""")
print(result.formatted_featureql)
print(result.output_schema)
print(result.warnings)
python
FieldWhat it tells you
formatted_featureqlCanonical spelling of your query
output_schemaOutput column names and FeatureQL types
featuresDependency layers, formulas, grains
warningsIssues worth reviewing (code, message, location)
sql_valid / sql_errorWhether the backend accepted the dry-run SQL

Use validate while you are still shaping the query; switch to query when you want real results.

diagnose — find the first broken feature

When a large query fails and the error is hard to place, diagnose adds features one at a time and stops at the first failure.

result = client.diagnose("""
    RETURN A := 1, B := CONCAT(1, 2) + A;
""")
print(result.failed_step)
print(result.steps[result.failed_step].error)
python

Each step’s error is a list of objects with code, message, location, and sometimes a dependency path. Fix the failing feature, validate again, then run.

help — look up concepts and examples

client.help("mental_model", "getting_started").display()
client.help("extend", snippets=2)
client.help("fill missing values", more=3)
python

Each term returns two blocks, in a fixed order:

  1. Resolved parts — everything keyed exactly by the term (tag, alias, page#section, snippet id, UE/… error code, function name): the page body, then its runnable snippets as help('id') pointers. snippets=n inlines the first n of them in full (default 0).
  2. More — more other pages, sections, or snippets ranked by the words of the term (default 5), as one-line key (kind) — title — summary entries. Pass a key back to help() to go further.

Free text resolves nothing and returns only the ranked list. HelpResult.text is the markdown; parts and more hold the same rows as dicts. The same lookup is valid inline FeatureQL: HELP 'locf', 'fill gaps' WITH 3 MORE, 1 SNIPPET;.

Start with mental_model ( /llms/mental_model.md ) then getting_started. These are the same short pages an assistant loads through help() — you can open them yourself the same way.

describe — inspect the catalog skeleton

client.describe("FM.DEMO.").display()
python

Pass at least one namespace prefix. describe() is a namespace map: sources (NAME + FORMULA, so a source shows FROM TABLE(...)), one Grains table (entity / input / keyset), and a derived sample (at most 20, ranked by catalog POSITION) with the derived total. Markdown uses short names — a name that does not start with FM. lives in that namespace (FROM FM.DEMO or FM.DEMO.FEATURE_NAME). DescribeResult.features_list stays fully qualified. DescribeResult.next_queries are SHOW FEATURES WHERE IS_DOWNSTREAM_OF(...) follow-ups (full names) to run with query(). Useful after CREATE FEATURES, and before you share that registry with a colleague or an assistant.

Jupyter magic options

After loading the extension and selecting a client as shown in the Python library guide , run %%featureql --help for the current option list.

OptionWhat it does
--client CLIENTUse a specific client variable from the notebook namespace
--debug [LEVEL]Enable info, debug, or trace diagnostics; the default level when omitted is debug
--optimize [LEVEL]Select the SQLGlot optimization level
--timeitBenchmark DuckDB execution with warmup and measured runs
--show-sqlPrint the translated SQL alongside results
--hide-dataframeSuppress DataFrame display; the magic returns None
--show-sltPrint the result in SQL Logic Test format
--hook VARIABLEStore QueryResult.to_dict() in a variable

The hook value is a plain dict, not a QueryResult. Its "dataframe" value is None or a list of row dictionaries, not a pandas.DataFrame. Use VARIABLE["dataframe"], or get a real DataFrame with client.query(...).dataframe. Without --hide-dataframe, you can also capture the magic output from _ or Out[n] in the next cell.

Warnings you can acknowledge

Some warnings include an ACK token (ACK-EXWX…). After you have reviewed the warning and accept it, put that token in a comment on the query so it stops repeating. Works the same on validate and query. The FeatureQL side is on Tools in the query .

sltest from Python

client.sltest runs the documentation / conformance suite from the package. Filters, # depends:, and multi-backend checks:

→ Conformance tests

If you write your own SLT around these methods, the focused-payloads section on that page shows # match: jmespath against validate / help / describe / diagnose / translate.

AccessClient

Orgs, projects, invitations, tokens, and service accounts are AccessClient calls on the same package — not the demos repo.

→ Managing access

What Python returns

MethodResult typeHighlights
queryQueryResultdataframe, sql, errors, warnings
translateTranslateResultsql, errors
validateValidateResultformatted_featureql, features, warnings
diagnoseDiagnoseResultfailed_step, per-step errors
helpHelpResultdocs, samples, signatures, tests
describeDescribeResultskeleton features_list, next_queries
sltestlist[dict]per-test status, name, …

Related