Skip to main content

Fyrefly

A quant-based library to compute mathematical operations, run SQL queries, get AI-powered insights, visualize your data, and test APIs.

📖 Full documentation

Installation

pip install fyrefly

Usage — Math functions

from fyrefly import add, mul, div, mod, diff

add(5, 4, 6, 10)     # 25
mul(5, 4, 6, 10)     # 1200
div(100, 5, 2)       # 10.0
mod(17, 5)           # 2
diff(10, 3, 2)       # 5

Each function accepts any number of arguments:

add(1)                # 1
add(1, 2, 3, 4, 5)    # 15
mul()                  # 1 (identity)
diff(10, 3)            # 7

Usage — Quant formulas

from fyrefly import si, ci, si_ci_diff, profit, loss, ap, gp, hp, avg, avgc, mode, median, hyp, slope, centroid, dist

# Interest
si(1000, 2, 5)                    # 100.0   (Simple Interest: p, n, r)
ci(1000, 2, 10)                   # 210.0   (Compound Interest, annual by default)
ci(1000, 2, 10, "semi-annual")    # 215.5   (compounded twice a year)
si_ci_diff(1000, 10, 2)           # 10.0    (CI - SI, supports n = 2 or 3 only)

# Profit / Loss — smart-detects if you called the wrong one
profit(120, 100)         # 20
profit(120, 100, "%")    # (20, 20.0)   value + percentage
loss(80, 100)             # 20
loss(80, 100, "%")        # (20, 20.0)
profit(80, 100)           # raises: "this is a LOSS, not a profit. Use loss(80, 100) instead."

# Sequences: AP, GP, HP
ap(2, 3, 4)          # [2, 5, 8, 11]        full sequence
ap.tn(2, 3, 4)       # 11                    nth term
ap.sn(2, 3, 4)       # 26.0                  sum of first n terms

gp(2, 3, 4)          # [2, 6, 18, 54]
gp.tn(2, 3, 4)       # 54
gp.sn(2, 3, 4)       # 80.0

hp(2, 3, 4)          # [2.0, 0.2857..., 0.1538..., 0.1052...]
hp.tn(2, 3, 4)       # 0.10526315789473684
hp.sn(2, 3, 4)       # 2.5448235974551765

# Averages, mode, median
avg(10, 12, 13)          # 11.666666666666666        plain average of individual numbers
avgc(5, 3, 10, 2)         # 7.0                        weighted avg from (value, count) pairs
mode(1, 1, 2, 2)          # [1, 2]
median(1, 2, 3, 4)        # 2.5

# Geometry
hyp(3, 4)                              # 5.0
slope((1, 2), (3, 4))                  # 1.0
centroid((1, 2), (3, 2), (4, 5))       # (2.6666666666666665, 3.0)
dist((6, 2), (10, 5))                  # 5.0

Usage — Mensuration (2D & 3D shapes)

from fyrefly import circle, square, triangle, cube, sphere, cylinder, cone

# 2D — area and perimeter
circle.area(7)                      # 153.93804002589985
circle.perimeter(7)                 # 43.982297150257104
square.area(5)                      # 25
triangle.area_sides(3, 4, 5)        # 6.0   (Heron's formula, from the three sides)

# 3D — volume and surface area
# Surface area splits into .tsa() (total), .csa() (curved only), .lsa() (sides only)
# Sphere and Torus use plain .surface_area() since there's nothing to disambiguate
cube.volume(3)                      # 27
cube.tsa(3)                         # 54   (all 6 faces)
sphere.volume(3)                    # 113.09733552923254
cylinder.csa(3, 7)                  # 131.94689145077132   (side only, excludes the two ends)
cylinder.tsa(3, 7)                  # 188.49555921538757   (side + both ends)
cone.tsa(3, 4)                      # 75.39822368615503    (slant height computed internally)

2D shapes: circle, semicircle, square, rectangle, triangle, equilateral_triangle, parallelogram, rhombus, kite, trapezoid, ellipse, polygon, sector, annulus

3D shapes: cube, cuboid, sphere, hemisphere, cylinder, cone, frustum, pyramid, prism, torus

Usage — Equations, logs, exponents, roots, trigonometry

from fyrefly import eqn, log, exp, sqrt, curt, nroot, sin, cos, tan, cosec, sec, cot

# Linear systems — n equations, n unknowns. Each equation: (coefficients..., constant)
eqn.l((2, 3, 5), (7, 6, 10))                          # (x, y) solving 2x+3y=5, 7x+6y=10
eqn.l((1, 1, 1, 6), (2, -1, 1, 3), (1, 2, -1, 2))     # (a, b, c) — scales to any n unknowns

# Polynomial roots — any degree, plus sum/product of roots (Vieta's formulas)
eqn.q(1, 3, 4)              # roots of x^2 + 3x + 4 = 0
eqn.q(3, 4, 6, 9, 10)       # roots of 3x^4 + 4x^3 + 6x^2 + 9x + 10 = 0
eqn.q.sum(5, 2, 3)          # -0.4   sum of roots of 5x^2 + 2x + 3 = 0
eqn.q.mul(5, 2, 3)          # 0.6    product of roots

# Logs and exponents
log(math.e)          # 1.0   natural log by default
log(8, 2)             # 3.0   log base 2
exp(2, 5)             # 32    2 to the power 5
exp(2, -1)            # 0.5   negative exponents work too

# Roots
sqrt(16)              # 4.0
curt(27)              # 3.0
curt(-27)             # -3.0   odd roots of negative numbers work correctly
nroot(16, 2)          # 4.0    generic nth root

# Trigonometry — degrees by default, pass mode="rad" for radians
sin(30)               # 0.5
cos(60)               # 0.5
tan(45)               # 1.0
cosec(30)             # 2.0
sec(60)               # 2.0
cot(45)               # 1.0

Usage — Units, casting & rounding

from fyrefly import convert, cast, round

# Unit conversion — length, mass, volume, area, time, speed, data, energy, pressure, temperature
convert(10, "km", "miles")       # 6.213711922373339
convert(98.6, "F", "C")          # 37.0
convert(5, "kg", "lb")           # 11.023113109243878
convert(1, "gb", "mb")           # 1024.0

# Type casting — fixes Python's bool("False") gotcha (which is actually True!)
cast("123", "int")               # 123
cast("False", "bool")            # False
cast("[1, 2, 3]", "list")        # [1, 2, 3]
cast("2024-01-15", "date")       # date(2024, 1, 15)
c["age"] = cast(c["age"], "int") # casts an entire DataFrame column

# Rounding — standard round-half-up (like Excel), not Python's banker's rounding
round(2.5)            # 3   (Python's own round(2.5) gives 2)
round(1250, -2)       # 1300 (Python's own round(1250, -2) gives 1200)

Usage — Data functions

from fyrefly import load, loadh, loadc, loads, sql, xtract, clean

c = load("data.csv")                 # loads a CSV/Excel/Google Sheet, previews it
loadh(c)                             # preview column headers
loadc(c)                             # preview record count
loads(c)                             # preview schema (columns + datatypes)

c = clean(c)                         # dedupe, strip whitespace, standardize column names

d = sql("select * from c where age > 30")   # run ANY SQL query on loaded data
xtract(d)                                    # export the result to CSV
xtract(sql("select * from c"), filename="all.csv")  # chained form also works

Note: for Google Sheets, the sheet must be shared as "Anyone with the link – Viewer" for load() to access it.

Usage — Lookups & Excel functions

from fyrefly import vlook, xlook, countif, sumif, avgif

c = load("employees.csv")

# VLOOKUP — searches the FIRST column, just like Excel
vlook("Alice", "salary")                  # 85000
vlook("Alice", "salary", default=0)       # returns 0 instead of raising if not found

# XLOOKUP — searches ANY column you specify
xlook("Engineering", "department", "name")   # "Alice"

# COUNTIF / SUMIF / AVERAGEIF
countif("department", "Engineering")              # 3
sumif("department", "Engineering", "salary")      # 250000
avgif("department", "Engineering", "salary")      # 83333.33

All five auto-detect your loaded dataset — if you've loaded more than one, pass it explicitly: vlook("Alice", "salary", df=d).

Usage — AI functions (require an API key)

from fyrefly import ask, insights

c = load("sales.csv")

# Ask questions in plain English — converted to SQL and run automatically
ask(c, "what were total sales by region last quarter?", api_key="AIza...")

# Query across multiple datasets (e.g. a join) — scales to any count
ask((c, d), "who are our top customers by total sales?", api_key="AIza...")
ask((c, d, e), "...", api_key="AIza...")

# Get a plain-English summary of a dataset
insights(c, api_key="AIza...")

The provider (Anthropic, OpenAI, Gemini, or any OpenAI-compatible API like Groq/Mistral) is auto-detected from your API key's format — you usually don't need to specify it. API keys can also be set via environment variables instead of passing them directly: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY.

Transient provider errors (rate limits, temporary server issues) are retried automatically with backoff before giving up.

⚠️ Never commit an API key into a script you push to GitHub. Use an environment variable instead:

export GEMINI_API_KEY="AIza..."
ask(c, "what were total sales by region?")   # picked up automatically from the env var

Usage — Visualization (no AI, no API key needed)

from fyrefly import viz

viz(c)                                # auto -> correlation heatmap
viz(c, "department")                  # auto -> bar chart of counts
viz(c, "age")                         # auto -> histogram
viz(c, "age", "salary")               # auto -> scatter (both numeric)
viz(c, "department", "salary")        # auto -> bar (mixed types)
viz(c, "age", "salary", kind="scatter")
viz(c, "department", "salary", kind="box")
viz(c, "department", kind="pie")
viz(c, "date", "revenue", kind="line")
viz(c, kind="pairplot", hue="department")
viz(c, "department", "salary", kind="bar", save="chart.png")   # also saves a file

Supported chart types: line, bar, barh, scatter, hist, box, violin, kde, pie, heatmap, pairplot, area, plus "auto" which picks a sensible chart based on your data.

Namespace-style shortcuts

Once exactly one DataFrame is loaded, you can also call chart types directly, without repeating the DataFrame each time:

c = load("data.csv")

viz.bar("department", "salary")
viz.scatter("age", "salary")
viz.line("date", "revenue")
viz.box("department", "salary")
viz.violin("department", "salary")
viz.hist("age")              # single-column kinds take just x
viz.kde("salary")
viz.pie("department")
viz.heatmap()                # no columns needed
viz.pairplot(hue="department")   # no columns needed

If more than one DataFrame is loaded, the shortcut can't guess which one you mean — pass it explicitly as the first argument instead: viz.bar(c, "department", "salary").

Usage — API testing (no API key needed)

One function, api.gui(), opens a free Postman-style window in your browser. Build a request, press Send, and read a plain-English answer.

from fyrefly import api

api.gui()                                            # opens the window
api.gui("https://api.example.com/users", method="post",
        send="name=Asha, age=30", token="YOUR_TOKEN")  # opens it already filled in

It covers what you do every day:

  • Request tabs, Params, Authorization, Headers, Body. The body can be JSON, form-data with file upload, a plain web form, or text/XML. Every row has an on/off checkbox. Ctrl+Enter sends, Ctrl+S saves.
  • Collections. Save requests into collections and folders, reopen them from the sidebar, copy, rename, delete, and run a whole collection in order with a pass/fail table.
  • Environments. UAT, SIT, Prod... each a named set of variables, switched from a dropdown. Use them as {{HOST}} anywhere. Built in: {{$guid}}, {{$timestamp}}, {{$isoTimestamp}}, {{$randomInt}}.
  • Secrets stay secret. Mark a variable as secret and it is hidden on screen and stored in a separate secrets.json (owner-only, listed in .gitignore). A token typed straight into a request is not written to the saved file, so collections are safe to share.
  • Save to variable. Log in once, and the token is copied from the answer into {{TOKEN}} for every later request. Click "to var" next to any value in the Preview tab, or set it up in the "Save to variable" tab.
  • Import and export. Import a Postman collection (v2.x), a Postman environment, or a pasted curl command. Export a collection as Postman JSON.
  • The answer. Status, time and size, then: a plain-English Report (when something fails, a HOW TO FIX IT list says what is missing and which tab to fix it in), the Body with colored JSON, a find box and a Download button, a collapsible Preview (JSON tree, HTML in a locked box, or an image), a Table, the Headers with any redirects followed, and the Request as a curl command.
  • Settings. Check SSL certificates on or off (for internal servers), follow redirects, a proxy, a default timeout, cookies that persist between calls, and a history of what you sent (tokens never kept).

Your work lives in one plain folder, ~/fyrefly_api, created for you the first time (choose another with api.gui(folder="..."), or folder=False to save nothing):

~/fyrefly_api/
  collections/Shop API.json      requests, safe to share or commit
  environments/UAT.json          variables; secret values are blank here
  secrets.json                   the secret values (not shared, in .gitignore)
  history.json  settings.json

The window runs only on your computer: it is served from 127.0.0.1, behind a one-time secret in the address, and loads nothing from the internet. Click Quit (or press Ctrl+C) to close it. In a notebook, api.gui() returns at once and window.stop() closes it.

Functions

Function Description Needs API key?
add(*nos) Adds all given numbers No
mul(*nos) Multiplies all given numbers No
div(*nos) Divides left to right: first ÷ second ÷ third ... No
mod(*nos) Finds remainder left to right: first % second % third ... No
diff(*nos) Subtracts left to right: first − second − third ... No
si(p, n, r) Simple Interest No
ci(p, n, r, freq) Compound Interest ("annual" or "semi-annual") No
si_ci_diff(p, r, n) CI − SI, for n = 2 or 3 years No
profit(sp, cp, "%") Profit value, or (value, %) if "%" passed — smart-detects a loss No
loss(sp, cp, "%") Loss value, or (value, %) if "%" passed — smart-detects a profit No
ap/.tn/.sn(a, d, n) Arithmetic Progression: sequence, nth term, sum of n terms No
gp/.tn/.sn(a, r, n) Geometric Progression: sequence, nth term, sum of n terms No
hp/.tn/.sn(a, d, n) Harmonic Progression: sequence, nth term, sum of n terms No
avg(*nos) Plain average of individual numbers No
avgc(*value_count_pairs) Weighted average from (value, count) pairs No
mode(*nos) Most frequent value(s) No
median(*nos) Median No
hyp(a, b) Hypotenuse of a right triangle No
slope(point1, point2) Slope between two (x, y) points No
centroid(p1, p2, p3) Centroid of a triangle from three (x, y) points No
dist(point1, point2) Distance between two (x, y) points No
circle.area/.perimeter(r) Area and circumference of a circle No
semicircle.area/.perimeter(r) Area and perimeter of a semicircle No
square.area/.perimeter(s) Area and perimeter of a square No
rectangle.area/.perimeter(l, w) Area and perimeter of a rectangle No
triangle.area(base,h) / .area_sides(a,b,c) / .perimeter(a,b,c) Area (from base/height or Heron's formula) and perimeter No
equilateral_triangle.area/.perimeter(s) Area and perimeter of an equilateral triangle No
parallelogram.area(base,h) / .perimeter(a,b) Area and perimeter of a parallelogram No
rhombus.area(d1,d2) / .perimeter(s) Area (from diagonals) and perimeter of a rhombus No
kite.area(d1,d2) / .perimeter(a,b) Area (from diagonals) and perimeter of a kite No
trapezoid.area(a,b,h) / .perimeter(a,b,c,d) Area and perimeter of a trapezoid No
ellipse.area/.perimeter(a,b) Area (exact) and perimeter (Ramanujan's approximation) of an ellipse No
polygon.area/.perimeter(n_sides, length) Area and perimeter of any regular polygon No
sector.area(r,angle) / .arc_length(r,angle) Area and arc length of a circular sector No
annulus.area(outer_r, inner_r) Area of a ring shape No
cube.volume(s) / .lsa(s) / .tsa(s) Volume, lateral and total surface area of a cube No
cuboid.volume(l,w,h) / .lsa(...) / .tsa(...) Volume, lateral and total surface area of a cuboid No
sphere.volume(r) / .surface_area(r) Volume and surface area of a sphere No
hemisphere.volume(r) / .csa(r) / .tsa(r) Volume, curved and total surface area of a hemisphere No
cylinder.volume(r,h) / .csa(r,h) / .tsa(r,h) Volume, curved and total surface area of a cylinder No
cone.volume(r,h) / .csa(r,h) / .tsa(r,h) Volume, curved and total surface area of a cone No
frustum.volume(r1,r2,h) / .csa(...) / .tsa(...) Volume, curved and total surface area of a frustum No
pyramid.volume(s,h) / .lsa(s,h) / .tsa(s,h) Volume, lateral and total surface area of a square pyramid No
prism.volume(base_area,h) / .lsa(...) / .tsa(...) Volume, lateral and total surface area of a general prism No
torus.volume(R,r) / .surface_area(R,r) Volume and surface area of a torus No
eqn.l(*equations) Solves a system of n linear equations in n unknowns No
eqn.q(*coeffs) Roots of a polynomial of any degree No
eqn.q.sum(*coeffs) / eqn.q.mul(*coeffs) Sum / product of all roots (Vieta's formulas), any degree No
log(x, base=e) Logarithm, natural by default No
exp(a, b) a raised to the power b (positive or negative) No
sqrt(no) / curt(no) / nroot(no, n) Square root / cube root / generic nth root No
sin/cos/tan/cosec/sec/cot(angle, mode="deg") Trigonometric functions, degrees by default No
convert(value, from_unit, to_unit) Converts between units within the same category No
cast(value, target) Casts a value or DataFrame column to another type No
round(value, places=0) Rounds using standard round-half-up, not banker's rounding No
load(path) Loads a CSV/Excel/Google Sheet into a DataFrame and previews it No
loadh(df) Previews just the column headers No
loadc(df) Previews the record count No
loads(df) Previews the schema (columns + datatypes) No
sql(query) Runs any SQL query against a loaded DataFrame, by variable name No
xtract(df, filename=None) Exports a DataFrame to CSV in the current directory No
clean(df) Dedupes, strips whitespace, standardizes column names No
vlook(value, return_col, df=None, default=...) Searches the first column — like Excel's VLOOKUP No
xlook(value, lookup_col, return_col, df=None, default=...) Searches any column — like Excel's XLOOKUP No
countif(col, value, df=None) Counts rows matching a condition No
sumif(col, value, sum_col, df=None) Sums a column for rows matching a condition No
avgif(col, value, avg_col, df=None) Averages a column for rows matching a condition No
ask(data, question, api_key=...) Converts a plain-English question into SQL and runs it Yes
insights(df, api_key=...) Generates a plain-English summary of a dataset Yes
viz(df, x=None, y=None, kind="auto", ...) Visualizes a DataFrame — 12+ chart types No
viz.bar/.scatter/.line/.box/.violin/.hist/.kde/.pie/.heatmap/.pairplot Namespace shortcuts for each chart type — auto-detect the loaded DataFrame No
api.gui(url=None, method="get", send=None, headers=None, token=None, ...) Opens a free Postman-style window in your browser: collections, environments, secrets, import/export No

Development

pip install -e ".[dev]"
pytest          # includes the API tests, which use a local test server

License

MIT

Metadata

Release files for fyrefly 0.10.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fyrefly 0.10.0
File Size Uploaded Provenance Actions
fyrefly-0.10.0.tar.gz 885.0 kB With provenance Details for fyrefly-0.10.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fyrefly 0.10.0
File Interpreter ABI Platform Actions
fyrefly-0.10.0-py3-none-any.whl Python 3 none any Details for fyrefly-0.10.0-py3-none-any.whl

Total release size: 973.8 kB

Release files / fyrefly-0.10.0.tar.gz

Download URL fyrefly-0.10.0.tar.gz
Size 885.0 kB
Tags Source
SHA-256 checksum
How to use checksums
aaf644080ab59f8e7b799c58f0f3b17ce6e8b2f60b7cbaffda65042f713e35f4
BLAKE2b-256 checksum
How to use checksums
6a98423988f5405ac11adc28bb4b7aac02a7713230a89d071b564bf9431964a7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / fyrefly-0.10.0-py3-none-any.whl

Download URL fyrefly-0.10.0-py3-none-any.whl
Size 88.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f02bbd469caae6942663f0ca7f1f720962b1f605d87309ca3d240309e569e855
BLAKE2b-256 checksum
How to use checksums
e938dee60e8de69f692cb365bc3dbf3f004e6f9258e5d0044c9ffe1ae8cbfe4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Security for fyrefly 0.10.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for fyrefly-0.10.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page