Skip to main content

gridcalc

PyPI Python License: MIT

A programmable terminal spreadsheet for developers and technical users, with Excel-ish formulas, Python escape hatches, XLSX interop, goal seek, and LP/MIP solving.

Inspired by Serge Zaitsev's kalk.

pip install gridcalc
gridcalc budget.json

What it gives you

  • Excel-compatible formulas (=IF(A1>=B1, A1*0.05, 0)) and arrays (=SUM(A1:A10 * B1:B10)) without leaving the terminal.
  • Multi-sheet workbooks with cross-sheet refs (=Sheet2!A1) and a proper dep graph.
  • Three formula modes per file: strict Excel, Excel-plus-py.*, or full Python eval with numpy/pandas.
  • xlsx interop via OpenXLSX C++ -- read every sheet's formulas + values; export with cached values.
  • Linear, mixed-integer & quadratic programming built in via HiGHS -- :opt max B4 vars A4:A5 st D4:D6 solves from cells in the sheet, with shadow prices, infeasibility diagnosis, and RHS sweeps. Models persist in the workbook.
  • Goal-seek -- :goal B10 = 100 by A1 adjusts a variable so a formula hits a target value.
  • Vim-style command line (:w, :e, :q, /search, y/p, visual selection, undo), with system-clipboard copy/paste -- yank pushes values as TSV, paste pulls TSV in from other apps.

Try it on the provided examples:

gridcalc example_excel.json          # sales report, named ranges, IF/MATCH
gridcalc example_hybrid.json         # progressive tax via py.* + aggregations
gridcalc example.json                # PYTHON: numpy/pandas, list-comprehensions
gridcalc example_multisheet.json     # 3-sheet budget, cross-sheet formulas
gridcalc example_lp.json             # LP/MIP demo -- type :opt to solve
gridcalc example_goal.json           # goal-seek demo -- :goal B1 = 11 by A1

Install

Two options:

pip install gridcalc            # core: zero third-party runtime deps
pip install 'gridcalc[extras]'  # adds numpy, pandas, pygments

Or with uv: uv tool install 'gridcalc[extras]'.

The core install has zero third-party runtime dependencies on Linux and macOS -- the full 300+ Excel function library (statistical distributions, financial functions, LINEST/TREND regression, ...) works on stdlib alone. (The 3.10 wheel pulls tomli for config-file parsing; 3.11+ uses stdlib tomllib. On Windows only, windows-curses is pulled in because curses is not in the Windows stdlib.)

The [extras] bundle enables, all at once:

  • np.array(...) in formulas; LAPACK-backed solvers; faster LINEST.
  • pd.DataFrame(...), :pd load/save, DataFrame cell display.
  • Pygments syntax-highlight in the load-time trust prompt.

Quick tour

Cells hold a number, a label (any non-=-prefixed string), or a formula (prefixed with =). Arrow keys move; Enter commits and moves down; Tab commits and moves right.

        A          B          C
1  Revenue   Cost       Margin
2  1000      600        =(A2-B2)/A2*100      <- formula
3  1200      700        =(A3-B3)/A3*100
4  Total     =SUM(B2:B3) =AVG(C2:C3)

Press : for the command line. The basics:

Command Purpose
:w [file] save (extension .json or .xlsx)
:o file open
:q, :q! quit, force-quit
:e edit the workbook's Python code block in $EDITOR
u, Ctrl-R undo / redo
v enter visual selection mode (then y yanks, p pastes)
/text search (n/N to cycle matches)
> go to a named cell (e.g. > AA10)

A full command reference lives in the Reference section below.

Modes

Each workbook has one of three evaluation modes, controlling which formulas parse and what's reachable from them:

Mode Grammar Python escape hatch Sandbox Use case
EXCEL strict Excel none not needed (no eval) xlsx interop, untrusted files
HYBRID Excel + py.* code-block functions reachable as py.foo(...) code blocks only most new sheets
PYTHON Python eval() full Python expressions full AST sandbox numpy/pandas-heavy work

Switch with :mode <name> -- the change is refused if any current formula doesn't parse in the target mode. Files without an explicit mode field load as PYTHON (back-compat). :xlsx load switches to EXCEL automatically.

Formulas

=A1 + B1 * 2                          arithmetic, Excel precedence
=(A1 + A2) / 2                        grouping
=2^10                                 exponent (PYTHON: ** also works)
=50%                                  percent postfix -> 0.5
="hello " & A1                        string concat
=IF(A1 > 0, "pos", "neg")             conditionals
=IFERROR(B1/C1, 0)                    error catch -- #DIV/0!, #VALUE!, #N/A, ...
=SUM(A1:A10)                          range -> 1D array
=SUM(A1:A3 * B1:B3)                   element-wise array arithmetic
=LET(x, SUM(A1:A9), x/COUNT(A1:A9))   local bindings -- compute once, reuse
=FILTER(A1:A9, B1:B9 > 0)             dynamic arrays: FILTER/SORT/UNIQUE
=SUM(revenue)                         named range
=py.margin(A1, B1)                    HYBRID: call a code-block function

Excel error values (#DIV/0!, #N/A, #NAME?, #REF!, #VALUE!, #NUM!, #NULL!) propagate through arithmetic and are catchable with IFERROR/IFNA.

Built-in functions (always available): SUM, AVG, MIN, MAX, COUNT, ABS, SQRT, INT, plus everything in math (sin, cos, log, pi, e, ...).

Excel-compatible library (auto-loaded in EXCEL/HYBRID): IF, IFERROR, AND, OR, NOT, ROUND, AVERAGE, MEDIAN, SUMIF, COUNTIF, AVERAGEIF, LET, VLOOKUP, HLOOKUP, XLOOKUP, XMATCH, INDEX, MATCH, FILTER, SORT, UNIQUE, SEQUENCE, CONCATENATE, LEFT, RIGHT, MID, LEN, TRIM, UPPER, LOWER, SUBSTITUTE, and 280+ others. Dynamic-array functions return whole rows/columns and compose (=INDEX(SORT(A1:B9), 1, 2)).

PYTHON-only extras: the math module, Python builtins (sum, min, max, abs, len), list comprehensions, and -- when the relevant extras are installed -- np.array(...), np.linalg, matrix multiply (@), and pd.DataFrame(...).

Named ranges & custom functions

:name revenue A1:A12       Define a named range (workbook-global)
:names                     List
:unname revenue            Remove

Used directly in formulas: =SUM(revenue), =MAX(revenue - costs).

Open the per-workbook Python code block with :e. Anything defined there becomes callable from formulas:

def margin(rev, cost):
    return (rev - cost) / rev * 100

In HYBRID: =py.margin(A1, B1). In PYTHON: =margin(A1, B1). EXCEL mode forbids code blocks entirely.

Cell references

$A$1 fixes both; $A1 fixes the column; A$1 fixes the row. References adjust automatically on insert/delete/replicate.

Multi-sheet workbooks

:sheet                     List sheets (active marked *)
:sheet Inputs              Switch by name
:sheet 1                   Switch by zero-based index
:sheet add Outputs         Append (does not switch)
:sheet del Tmp             Remove (refused if last sheet)
:sheet rename Old New      Rename, rewriting `Old!` prefixes in formulas
:sheet move Inputs 0       Reorder

Reference cells on other sheets with Sheet!cell:

=Sheet2!A1
=SUM(Sheet2!A1:A10)
=Sheet1!A1 + Sheet2!B1

The dep graph is keyed on (sheet, col, row) so cross-sheet recalc works transparently. Cross-sheet ranges (Sheet1!A1:Sheet2!B5) are not supported (Excel doesn't either).

Optimization

:opt solves linear and mixed-integer programs defined by cells in the active sheet, via a vendored copy of HiGHS (MIT). Models are workbook-persistent: define once, save the file, re-run on reopen.

:opt                                                                       Run the saved 'default' model
:opt max|min            (with a visual selection)                          Infer the model from the selected block
:opt max|min <cell> vars <cells> st <cells> [bounds <spec>] [int <cells>] [bin <cells>]
                                                                           Solve inline AND save as 'default'
:opt def <name> max|min <cell> ...                                         Save under <name>; does not execute
:opt run [<name>]                                                          Execute a saved model
:opt sens [<name>] [into[!] <cell>]                                        Sensitivity report -- paged, or written into cells
:opt sweep <cell> <lo>:<hi> [steps] [<name>]                               Re-solve across a range of RHS values
:opt list                                                                  List saved models
:opt undef <name>                                                          Remove a saved model

The model is sheet-resident: an objective formula in one cell, decision-variable cells holding values, and constraint cells holding comparison formulas like =A1+A2<=10. The constraint cells keep evaluating during recalc, so the sheet shows live feasibility (TRUE/FALSE) before and after the solve.

A worked example (also at examples/example_lp.json):

A B C D
3 Decision Objective Constraints
4 0 =3*A4+5*A5 =A4<=4
5 0 =2*A5<=12
6 =3*A4+2*A5<=18
:opt max B4 vars A4:A5 st D4:D6

Status bar shows opt: OPTIMAL obj=36; A4 and A5 become 2.0 and 6.0; u rolls back.

Quadratic objectives

Objectives may contain squared decision variables and cross terms -- =(A1-3)*(A1-3), =A1^2 + A2^2, =A1*A2, =2*A1^2 + 3*A1 -- which covers least-squares fitting, quadratic cost curves, target tracking, and covariance-style objectives.

:opt min C1 vars A1:A2 st D1
opt: OPTIMAL  obj=0  (quadratic)

Solved exactly as a QP; there is no approximation and no accuracy knob.

The objective must be convex for a minimisation (or concave for a maximisation). Otherwise the optimum sits at a corner of the feasible region, which is a different and much harder problem, and gridcalc refuses it rather than returning a plausible wrong answer:

opt: objective is not convex, so it has no interior minimum -- ...

Convexity is checked directly on the Hessian (symmetric elimination, no numpy required), so the message names the real problem rather than surfacing a solver failure.

Sensitivity analysis and infeasibility diagnosis are withheld for quadratic models: their duals do not carry the shadow-price reading the report describes. Same call as for MIPs. Integer variables cannot be combined with a quadratic objective.

Inferring the model from a selection

The layout above already says what the model is. Select the block with v, then type :opt max (or min) and the components are read off it:

Cell contents Read as
formula rooted in a comparison (=A4<=4) a constraint
any other formula (=3*A4+5*A5) the objective
a plain number a decision variable
labels, blanks ignored

For the sheet above, selecting A3:D6 and typing :opt max is equivalent to :opt max B4 vars A4:A5 st D4:D6.

Exactly one non-comparison formula must be in the selection; more than one is ambiguous and reports the candidates so you can narrow it. Blanks are deliberately not treated as decision variables -- a selected rectangle is mostly whitespace, and promoting every gap to a variable would build a model you never described.

The inferred model is saved as default, so the block only has to be selected once: plain :opt re-runs it afterwards, and :w persists it.

Clauses (any order after st):

  • bounds A1=lo:hi, B2=lo:hi -- per-variable bounds. lo/hi accept inf, +inf, -inf. Default is [0, +inf).
  • int <cells> -- decision variables are integer-valued (branch-and-bound).
  • bin <cells> -- decision variables are binary ({0,1}); bounds clamped to [0,1].

Cell lists everywhere accept ranges (A1:A5), comma-separated refs (A1,A3,B5), or a mix.

Saved models live under "models": {<name>: ...} in the JSON file and round-trip verbatim (the spec strings the user typed are stored, not pre-resolved coords).

Sensitivity analysis

:opt sens [<name>] solves the model and then opens a report answering the question a bare optimum does not: what would change the answer?

Variable cells
   cell      value   reduced  obj coef coef from coef till
   A4            2         0         3         0       7.5
   A5            6         0         5         2       inf

Constraints   (* = binding)
   cell     shadow       rhs  activity     slack  rhs from  rhs till
   D4            0         4         2         2      -inf       inf
 * D5          1.5        12        12         0         6        18
 * D6            1        18        18         0        12        24
  • shadow price -- objective gain per extra unit of right-hand side. D5 is worth 1.5 per unit and D6 is worth 1, so buying more of the D5 resource pays better. D4 has slack and is worth nothing.
  • rhs from/till -- the range over which that shadow price holds. Past it the optimal basis changes and the price no longer applies.
  • reduced cost -- for a variable stuck at a bound, how much the objective would move per unit if it were forced in. Zero for any variable already active.
  • coef from/till -- how far an objective coefficient can move before the optimal mix changes.
  • * -- the constraint is binding (zero slack). Derived from slack rather than from a non-zero shadow price, since a degenerate optimum can bind at a price of zero.

Sensitivity is not reported for integer or binary models: a branch-and-bound dual describes one LP relaxation rather than the integer problem, so there is no valid shadow-price reading. :opt sens on such a model still solves it and says why the report is absent.

Writing the report into cells

:opt sens into <cell> writes the report into the sheet instead of paging it, anchored at the given cell:

:opt sens into F1

The numbers land as values, not text, so downstream formulas can reference them:

F13:  =G7*100        -> 150     (G7 holds a shadow price of 1.5)

That is the reason to write into cells rather than read a report: the results become part of the sheet's own computation. Re-running the command refreshes the block in place.

Layout, anchored at the target cell -- a blank row separates the two tables, and positions are stable so formulas keep working across re-runs:

Variables    value  reduced  obj coef  coef from  coef till
<one row per decision variable>

Constraints  shadow  rhs  activity  slack  rhs from  rhs till
<one row per constraint>

The write refuses to overwrite non-empty cells and names the first one blocking it; use into! to overwrite anyway. The whole rectangle belongs to the report, including the separator row, so stray values cannot end up sitting inside it. The write is a single undo step.

Unbounded ranging values are written as infinities and display as inf / -inf.

Parametric sweep

A shadow price answers what is the next unit worth. It cannot answer how much more should I buy, because it stops being valid at the edge of its rhs from/till range. :opt sweep re-solves across a range and shows where the value changes:

:opt sweep D5 6:24 9
D5 right-hand side from 6 to 24   (* = marginal value changed)
            rhs objective     delta    shadow  status
              6        27        --       2.5
   *          8        30         3       1.5
             12        36         3       1.5
             18        45         3       1.5
   *         20        45         0         0
             24        45         0         0

Read that as: capacity is worth 1.5 per unit up to 18, and nothing at all beyond it. Buy up to 18.

steps is the number of intervals (default 10), so the report has steps + 1 rows spanning the range inclusive. The optional trailing name selects a saved model other than default.

The sweep is read-only -- each point substitutes the right-hand side internally rather than editing the constraint formula, so the sheet is untouched and there is nothing to undo. Points where the model becomes infeasible or unbounded are kept in the series with their status, since learning that a level is unattainable answers the question too.

Available programmatically as opt.sweep(...), and the underlying substitution as solve(rhs_override={cell: value}) for one-off what-if questions.

Infeasibility diagnosis

An infeasible model reports which constraints contradict each other, not just that the model failed:

opt: INFEASIBLE  conflict: D1, D2 (2 of 5 constraints)

The named cells are an irreducible conflicting set: together they are still infeasible, and dropping any one of them makes the model solvable again. Constraints that merely happen to be present are not listed, which is the whole point -- narrowing 30 constraints to the 2 that actually fight is the difference between a dead end and a fix.

Found by a deletion filter (one solve per constraint, on the failure path only), so a three-way conflict with no contradictory pair is reported correctly where a pairwise check would miss it. Variable bounds are held fixed rather than dropped, so a constraint that contradicts its variable's bounds is reported as the conflict.

This runs automatically on every infeasible :opt; there is no separate command.

Unboundedness diagnosis

The mirror case. An unbounded model names the variable that can run away, rather than only reporting that no optimum exists:

opt: UNBOUNDED  unbounded: A5 -- add an upper bound or a constraint

A variable is reported when the constraints permit it to move without limit in the direction that improves the objective -- established by re-solving over the same feasible region with that variable as the objective, so it is an exact answer rather than a large-number heuristic. Variables with no objective coefficient are never blamed: moving them cannot change the objective, so they are not the cause even when they are themselves unbounded.

Like the infeasibility case, this runs automatically.

Programmatic access:

from gridcalc.engine import Grid
from gridcalc.opt import solve

g = Grid()
g.jsonload("examples/example_lp.json")
g.recalc()
r = solve(g, objective_cell=(1, 3), decision_vars=[(0, 3), (0, 4)],
          constraint_cells=[(3, 3), (3, 4), (3, 5)], maximize=True)
print(r.status_name, r.objective, r.values)

Goal-seek

For 1-D what-if ("what input makes this output equal X?"), use :goal:

:goal <formula_cell> = <target> by <var_cell> [in <lo>:<hi>]
:goal B10 = 100 by A1                 auto-bracket from A1's current value
:goal B10 = 0 by A1 in -50:50         explicit search bracket

Uses bisection over Grid.recalc(); converges in milliseconds at spreadsheet scale. The variable cell must hold a value (not a formula). On success the variable cell is overwritten; u rolls back. Unlike :opt, goal-seek isn't persisted -- the three args fit on one line, so retyping is faster than naming.

Formatting

:f b                Toggle bold (also Ctrl-B)
:f u                Toggle underline (also Ctrl-U)
:f i                Toggle italic
:f bi               Combine: bold + italic

:f $                Dollar (2 decimal places)
:f %                Percentage (value*100, 2 decimals)
:f I                Integer (truncate)
:f *                Bar chart (asterisks proportional to value)
:f L | R | G | D    Left / right / general / use-global-format

:f ,.2f             Any Python format spec: 1,234.50
:f .1%              15.7%
:f .2e              1.23e+04

:gf <fmt> sets the workbook-wide default format. :width <n> sets column width (4-40). Labels longer than the column width spill into adjacent empty cells, Excel-style.

Import / export

Command Reads Writes Notes
:csv save/load CSV CSV Plain text, fast
:xlsx save/load .xlsx formulas + values EXCEL-mode: formulas + cached values; other modes: values only :xlsx load switches to EXCEL
:pd save/load CSV/TSV/Excel/JSON/Parquet same Uses pandas; row 1 as headers

:xlsx load translates Excel formulas into gridcalc's EXCEL grammar and reads every sheet. INDIRECT and 3D ranges (Sheet1:Sheet3!A1:B2) are deliberately unsupported -- they'd defeat the static dep graph. Functions outside the auto-loaded library produce #NAME?.

File format

JSON, v2. v1 (single sheet, top-level cells) still loads.

{
  "version": 2,
  "mode": "HYBRID",
  "active": "Inputs",
  "code": "def margin(rev, cost):\n    return (rev - cost) / rev * 100\n",
  "names":  { "revenue": "A1:A12", "costs": "B1:B12" },
  "models": { "default": { "sense": "max", "objective": "B4",
                           "vars": "A4:A5", "constraints": "D4:D6" } },
  "sheets": [
    { "name": "Inputs", "cells": [["Rev","Cost"],[1000,600],[1200,700]] },
    { "name": "Summary","cells": [["Total","=SUM(Inputs!A2:A3)"]] }
  ],
  "format": { "width": 10 }
}
  • mode: "EXCEL" | "HYBRID" | "PYTHON". Absent → PYTHON.
  • sheets (v2): each is {name, cells} with a 2D cells array.
  • active (v2): name of the sheet to focus on load.
  • names: workbook-global named ranges (sheet-relative when used).
  • models: persisted LP/MIP definitions (see Optimization).
  • code: per-workbook Python module string, editable via :e.

Configuration

Optional gridcalc.toml (lookup: $PWD then $XDG_CONFIG_HOME/gridcalc/):

sandbox = true             # AST validation of formulas + code blocks
width   = 12               # default column width
format  = "G"              # default cell format

[keys.grid]
next_sheet  = ["Tab", "F4"]
prev_sheet  = ["S-Tab", "F3"]
cursor_left = ["Left", "h"]
cursor_down = ["Down", "j"]
cursor_up   = ["Up", "k"]
cursor_right= ["Right", "l"]

Every TUI context (grid, entry, visual, cmdline, search) is rebindable. User bindings fire before the hardcoded fallback chain, so Tab → next_sheet replaces the default cursor-right meaning. See docs/keybindings.md for the keyspec grammar (Tab, S-Tab, C-x, C-Right, F3, ...) and rejected combinations.

Command reference

File          :w [file]   :wq   :q   :q!   :o file   :e
Edit          :b   :clear   :dr   :dc   :ir   :ic   :m   :r
              :sort [col] [desc]   yank/paste: y/p (syncs system clipboard)
              undo/redo: u / Ctrl-R   (aliases: Ctrl-Z / Ctrl-Y)
Format        :f <spec>   :gf <spec>   :width <n>   Ctrl-B / Ctrl-U
Search        /pattern   n   N
Sheets        :sheet [name|N|add|del|rename|move]
Names         :name <n> [range]   :names   :unname <n>
Modes         :mode [excel|hybrid|python]
Import/export :csv save/load   :xlsx save/load   :pd save/load
Optimization  :opt   :opt def   :opt run   :opt sens   :opt sweep
              :opt list   :opt undef
              :goal <cell> = <target> by <cell> [in <lo>:<hi>]
View          :view   E   :tv/:th/:tb/:tn (lock title rows/cols)

Limitations

  • INDIRECT is unsupported (would defeat the static dep graph).
  • LAMBDA and its higher-order helpers (MAP, REDUCE, BYROW, ...) are unsupported; LET is supported. Dynamic-array results are packed into their origin cell rather than spilling into neighbours.
  • xlsx export of formulas is EXCEL-mode only -- PYTHON/HYBRID syntax (**, list comprehensions, py.*) isn't strict Excel.
  • 3D range refs (Sheet1:Sheet3!A1:B2) are unsupported (returns nan). Workaround: expand manually with +.
  • Cross-sheet ranges (Sheet1!A1:Sheet2!B5) are rejected at parse time -- Excel doesn't support them either.
  • xlsx dates and styles aren't read or written; date serials arrive as floats.

Development

make build      # rebuild the C++ extensions (_core, _opt)
make test       # unit tests
make test-tty   # PTY-driven curses integration tests (slow, requires xterm-256color)
make lint       # ruff check
make typecheck  # mypy
make qa         # lint + typecheck + test + format

make wheel       # cpXX-cpXX wheel for current Python
make wheel-abi3  # single cp312-abi3 wheel (Python>=3.12)
make sdist       # source distribution
make publish     # upload to PyPI (after make check)

The abi3 build is gated on GRIDCALC_STABLE_ABI=ON (CMake) + wheel.py-api=cp312 (scikit-build-core). Per-version wheels and the abi3 wheel have separate CI workflows under .github/workflows/.

Prior Art

  • sc-im: A ncurses spreadsheet program for terminal
  • sheets: A terminal based spreadsheet tool
  • rustxl: A fast, keyboard-driven spreadsheet with vim-style navigation and Excel-compatible formulas.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gridcalc-0.3.0.tar.gz (2.4 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

gridcalc-0.3.0-cp313-cp313-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.13Windows x86-64

gridcalc-0.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (3.4 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

gridcalc-0.3.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (3.1 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

gridcalc-0.3.0-cp313-cp313-macosx_11_0_arm64.whl (2.3 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

gridcalc-0.3.0-cp313-cp313-macosx_10_15_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.13macOS 10.15+ x86-64

gridcalc-0.3.0-cp312-cp312-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.12Windows x86-64

gridcalc-0.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (3.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

gridcalc-0.3.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (3.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

gridcalc-0.3.0-cp312-cp312-macosx_11_0_arm64.whl (2.3 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

gridcalc-0.3.0-cp312-cp312-macosx_10_15_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.12macOS 10.15+ x86-64

gridcalc-0.3.0-cp312-abi3-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.12+Windows x86-64

gridcalc-0.3.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (3.4 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

gridcalc-0.3.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (3.1 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

gridcalc-0.3.0-cp312-abi3-macosx_11_0_arm64.whl (2.3 MB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

gridcalc-0.3.0-cp312-abi3-macosx_10_15_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.12+macOS 10.15+ x86-64

gridcalc-0.3.0-cp311-cp311-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.11Windows x86-64

gridcalc-0.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (3.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

gridcalc-0.3.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (3.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

gridcalc-0.3.0-cp311-cp311-macosx_11_0_arm64.whl (2.3 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

gridcalc-0.3.0-cp311-cp311-macosx_10_15_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.11macOS 10.15+ x86-64

gridcalc-0.3.0-cp310-cp310-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.10Windows x86-64

gridcalc-0.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (3.4 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

gridcalc-0.3.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (3.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

gridcalc-0.3.0-cp310-cp310-macosx_11_0_arm64.whl (2.3 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

gridcalc-0.3.0-cp310-cp310-macosx_10_15_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.10macOS 10.15+ x86-64

File details

Details for the file gridcalc-0.3.0.tar.gz.

File metadata

  • Download URL: gridcalc-0.3.0.tar.gz
  • Upload date:
  • Size: 2.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for gridcalc-0.3.0.tar.gz
Algorithm Hash digest
SHA256 3d0e7eb55fe096c88d2cd030bfe62c0f3c484e6af25c3af1f2edfbeea6770bee
MD5 bef3bfd2973f03674d58af91053bbc96
BLAKE2b-256 2ebf9dc644a5f269a8abebc48b2d108b75dd64bc8d58f2717fdab4396997676d

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: gridcalc-0.3.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for gridcalc-0.3.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 3bdab7f01c32e17cdc366adeaf062c6a67c6cd32ae7f51931855f6c4ee544edc
MD5 94ddcb15df88d5b26f7d348b127734c1
BLAKE2b-256 c31cd899268428963e90804c07e6c1e9e04db93814815d4923bbabdaf5950ac6

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 81609bd46ca97531dd330a58b02e13e6737d87ba2d1fdbf031154b21f2f987e1
MD5 417780f2795b9dc361db8b0c0fe63c8a
BLAKE2b-256 2ad0a1d1f865d07212e5def987d25506e8d8425e8c1c9afb0de19fd5f09eff9b

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c513029d20f65d867e80200cb96a50bc1c2c5d6deef5aebeb3dd28fff78b3fc7
MD5 c523745bb8139a7ed879533f63a7f20b
BLAKE2b-256 e9dad27cd441582ff08fa4fa604599deedb7fbd28a3acc558accdbb557025a4d

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2f2fbd7417398c3e571f417f778c1fa5a2491c86a3915c38e76120e546a9be04
MD5 64140b4dd21aeb344f2602831250223f
BLAKE2b-256 ae83226640fe7411b268c3af0d8b186b44700d1951cd7845b87e355a2efba0ce

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp313-cp313-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp313-cp313-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 d50389fb76a693a9fbde1a817f056826c5f577f1f2c57f1f164da4359c54652b
MD5 4aa7c5d0041ff401a171583c7baabe39
BLAKE2b-256 4787a56e7cb6072bd2573e63b79ba73f891213b6eac5816bd96b77765ec01f9e

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: gridcalc-0.3.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for gridcalc-0.3.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 3137a8db552ea30960d9ea486f50adb91ef2cee56bd0321a6d1bb1bc188f4864
MD5 b89a01b4c85e16811de1839ad09f9aa2
BLAKE2b-256 f7e77263cdc4a4e2a08d8fbf1e67ce58f6bb45b54dcec016480ffb8e14d12016

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ef1c1fb0a0cb27b345bc3d92aa292e2c07e9e9ae21b0d715badbe2ef76bb074f
MD5 d6111b93b9234b70184206d2599eac19
BLAKE2b-256 77ab900b635ac427f5fd65e002c50023477a6380317e96dbff6e1ac994db11c4

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 15a9cc28cb66e31b548e672ef1d177eea87fa508ad11b93d67bdf6af7ba5c39b
MD5 c07901be5a6859ac447654905a4968de
BLAKE2b-256 bd85a8d1b1bf6f93efd1db651f6abd4ab66c34f95d8cc290432d6b5a4a9384c6

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d51561820cafca68cb93b6d786d8944098cf5d385e5b01d3202562fad5a2ab7c
MD5 eb50c904fd0c5044feb66b369a56e682
BLAKE2b-256 c8ec4f863d929de021f0e3cef453fb77511e1b1c2dbb24c6e0bb1a4086bb3e5b

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-cp312-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-cp312-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 ec786161f363d46f472c39517960f1d87d605c933fa81c290ec37818fba02aa1
MD5 698499bdbf845730c7bd17bf87ec94c0
BLAKE2b-256 2a1431887eae20045c8f892e34b500b0dcde25fbd0338536a45da5da1c1d3e61

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: gridcalc-0.3.0-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for gridcalc-0.3.0-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 5492a8a129a381fd6f94075400cfad7ef23adf6214d6218e75cc9a64bd5f429b
MD5 0ca125f3cfa695cf03707478a8066f13
BLAKE2b-256 c0dbbd10964a9baeb80840c027105a76a04949dd9fc0d87d6a91b163215290c1

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 03d98ee6f079eb4669bab0b574394d9e6cd26789d0c5478909815202c85b0fa4
MD5 aed9e50b528468f4aa0dd2a982618f40
BLAKE2b-256 4af6d929e6d326d2ee063eeb97804b024ee2421b6ad9f932d918a0e22f7098fb

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e7e25a238e58d70a3eaa3fb241e01f668719e5d27c7ea4df2649389ad509277f
MD5 64c9ade8a11ad221d516683158e731e9
BLAKE2b-256 8f55b87301e722ac1823927dd0794204cf0960a4d80adf57034fed2f719b3aa0

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 73fb4d99b3fd468d7fbf4ffc8987052c79f7b25a98e87c3d1e7e5653fca3be2e
MD5 4fd15df633326bd8c80e609fc4b38428
BLAKE2b-256 cb8e8ccc7dedb2df050195067bf32247babff9448bcc13c70a22c4ace9549067

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp312-abi3-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp312-abi3-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 133780421b1c8df75f4cc70933729fcb362127c42ef00e65256865346ab8b88d
MD5 9b69591aa4b601981727289cd4bbac5f
BLAKE2b-256 953a668b82b32d380131948ca8f81bdb0920af6cc13e20d1a689de7ecc3514a6

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: gridcalc-0.3.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for gridcalc-0.3.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 e3d76cf7b90c427d7b662d510559fbbcea1d6da3efd0b51ce8c544c3e4ffc306
MD5 522d22bbee6f2fa1eac21a9a5a3f6887
BLAKE2b-256 0bd9d58b639d6c03728fee0bcf45c3f5d0d3fb54c847f56a4e091a375a4b5fa8

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 59cf6a69baa4b960db0b634201c9feba0c3ec1dcea93612ee1bba83710a26924
MD5 10cb560c38e824e26423db29ec392d56
BLAKE2b-256 c28011f6b94b1ac524e30a74a229274f656d18e2cb84180929949d265bc4db5c

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 cde6a8593efa274f7a70ad136a2e5b68138e491dee690394420e2eea45cd9849
MD5 88590b9dc2743d6709e0664e8d6c467a
BLAKE2b-256 0b46baa511cfb5973036ae5116bafc87ab1912e8cffa534b5f5055d65099a912

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 469d3090b71612cbdcc3d3eadcfc12ce791ee66a8a1a0e1c7b25db3e32ee21f6
MD5 725e9aba1dbf1bb4fc632edfd0818a55
BLAKE2b-256 2c22cea5864d42a6fb08df559b267da20860a4576a378c6be0d841f0400c53c8

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp311-cp311-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp311-cp311-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 cce3215d355f9d19dae3ee35bd9a53ea817ea987fee5816468babf0c9524b03e
MD5 e48a2645090f2bea0ae7c57a238a19de
BLAKE2b-256 369edf557603145f1f5fa236f827e9dc85e2da7e77958284278a887f2695bc0d

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: gridcalc-0.3.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for gridcalc-0.3.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 79e2945ec9fdae70197f1277f955d7e5ce136336b8fc1989d9b3374be3393b44
MD5 79a42a101a05d819d22732315dd91dba
BLAKE2b-256 1961bef11e807a6b1c5be9c999c86e204aecd04a38423bcbd113b3e43af04724

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 87c9c7fc7e920e2bc3918b4ff6a1043a8f4d63c3e27d94417aa1b815bb946109
MD5 b234eca6e9a80098ca0facac50bd6e5c
BLAKE2b-256 83098f77f5a997524d8acb92cff617f2c0d8d3c22a7aea165c0f56d655eefc09

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 5427d49b4e74704153d726cf87d2610436729d7d669e97e80d55358d150a1455
MD5 1eb733f1c88487c33975173da2d937d4
BLAKE2b-256 e71ca9bafc8859c18c2b5274c8026ed819047fce718a3e4d1c3c12f36c8cccfd

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d1e959d72ce7bb7295caec0a1660f850345259db2195a688f2129d5176738810
MD5 36c4605920de47692ae6c667c3701183
BLAKE2b-256 ece95547cc2f5ecc2a8fbf30a6a13607b804a57ef89932f918819c60fe2b00f4

See more details on using hashes here.

File details

Details for the file gridcalc-0.3.0-cp310-cp310-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for gridcalc-0.3.0-cp310-cp310-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 0763a1464d41e503fa3330249d2a3e62919e418db31071e53bf6935d07f31fa6
MD5 85ba2bbfdc7409dc4fac9485f8199007
BLAKE2b-256 71c9f1b4ad490b68d5721c306e9fd8c02b9fa09992319258c02db910efaed6fd

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.1

26 files

0.5.0

26 files

0.4.0

26 files

0.3.3

25 files

0.3.2

26 files

This release

0.3.0 This release

26 files

0.2.0

26 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

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