Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
3aab080
feat(hop): add hop ranges and labeling
lmeyerov Nov 22, 2025
7ad46c7
fix(hop): sync Plottable hop signature
lmeyerov Nov 22, 2025
3c69190
test(hop): add edge cases for ranges/labels
lmeyerov Nov 23, 2025
5ad659d
chore(hop): tighten hop tracking logic
lmeyerov Nov 23, 2025
16eabaa
chore(hop): drop output slicing params
lmeyerov Nov 23, 2025
eaa4e04
docs(gfql): add bounded hop examples
lmeyerov Nov 23, 2025
80c7005
docs(gfql): register hop bounds notebook
lmeyerov Nov 23, 2025
bbcb701
Clarify hop label params and docs
lmeyerov Nov 23, 2025
b1df273
fix(hop): clarify optional labels and docs
lmeyerov Nov 25, 2025
9154d5d
feat(compute): add hop output slice bounds
lmeyerov Nov 29, 2025
ce5c0a5
test(compute): cover hop branch exact-3 and output slice
lmeyerov Nov 29, 2025
93c1628
docs(gfql): refresh hop bounds examples and output slice
lmeyerov Nov 29, 2025
4ec938e
fix(hop): keep traversal path in default output slices
lmeyerov Nov 30, 2025
9287086
docs(gfql): surface hop range and slice params in quick/spec
lmeyerov Nov 30, 2025
548458d
docs(gfql): document hop bounds/slices in wire protocol
lmeyerov Nov 30, 2025
57f62ec
docs(gfql): map cypher hop ranges to min/max/output slice
lmeyerov Nov 30, 2025
8a03151
docs(gfql): align hop params in llm guide and notebook title
lmeyerov Nov 30, 2025
cdb92ca
docs(gfql): add intro and blurbs to hop_bounds notebook
lmeyerov Nov 30, 2025
bbd06b4
docs(gfql): clarify hop_bounds intro and bullets
lmeyerov Nov 30, 2025
71cc5db
docs(gfql): tighten hop_bounds intro text
lmeyerov Nov 30, 2025
3697a4a
docs(gfql): clarify hop_bounds intro bullets (cypher example)
lmeyerov Nov 30, 2025
59e4d6d
docs(gfql): add inline svg graph to hop_bounds
lmeyerov Nov 30, 2025
2ff54d7
docs(gfql): run hop_bounds via gfql hop helper
lmeyerov Nov 30, 2025
06de64e
docs(gfql): add reusable svg renderer and use gfql hop
lmeyerov Nov 30, 2025
cf299f7
docs(gfql): add section headers and clearer blurbs to hop_bounds
lmeyerov Nov 30, 2025
d8232cd
fix(gfql): keep hop slices and labels in edge traversals
lmeyerov Nov 30, 2025
20e77d0
docs(gfql): update hop params and hop_bounds notebook
lmeyerov Nov 30, 2025
584f62d
fix(hop): keep edge endpoints in sliced outputs
lmeyerov Nov 30, 2025
e4047f6
fix(gfql): include edge endpoints in chain outputs
lmeyerov Nov 30, 2025
e9a0258
docs(gfql): show explicit g.gfql usage in hop tutorial
lmeyerov Nov 30, 2025
99204c2
fix(hop): keep hop labels for output slicing in gfql
lmeyerov Nov 30, 2025
a558e5f
test(gfql): assert sliced hop chains drop earlier edges
lmeyerov Nov 30, 2025
443180c
docs(gfql): use n()/e_forward() in hop notebook examples
lmeyerov Nov 30, 2025
3d6927f
fix(gfql): apply edge output slices using forward params
lmeyerov Nov 30, 2025
e02d1e0
fix(gfql): keep reverse wavefronts alive for min/max hops
lmeyerov Nov 30, 2025
85f8a69
docs(gfql): refresh hop notebook outputs after hop fixes
lmeyerov Nov 30, 2025
bfa8ffd
fix: stabilize hop slice labels
lmeyerov Nov 30, 2025
d25fc59
test: add hop slice seed toggles and output caps
lmeyerov Nov 30, 2025
71bf04b
fix: honor wavefront max hops and tidy imports
lmeyerov Nov 30, 2025
2af6e81
fix: keep gfql tags when pruning hops
lmeyerov Nov 30, 2025
edb09c1
Refine lint/type runners
lmeyerov Nov 30, 2025
18d4cf7
test: extend gfql parity cases for labels and reverse hops
lmeyerov Nov 30, 2025
89d35c4
chore: nudge ci
lmeyerov Dec 1, 2025
5ae1019
chore: fix trailing newline for lint
lmeyerov Dec 1, 2025
2195905
fix(hop): keep reached seeds in wavefront outputs
lmeyerov Dec 1, 2025
8999553
fix(hop): fill sliced node hop labels from full traversal
lmeyerov Dec 1, 2025
f2d4a75
fix(hop): backfill hop labels and regen tutorial
lmeyerov Dec 1, 2025
587973f
fix(hop): cast hop labels to nullable ints; refresh hop notebook
lmeyerov Dec 1, 2025
78bf23e
chore(chain): skip empty hop label maps to avoid concat warning
lmeyerov Dec 1, 2025
e7a6dff
chore: quiet hop merge warnings; refresh hop_bounds
lmeyerov Dec 1, 2025
dda13e9
chore: keep warning fixes only (hop untouched)
lmeyerov Dec 1, 2025
a9105c9
chore(hop): silence combine_first warning
lmeyerov Dec 1, 2025
a737956
fix(compute): prune min_hop branches and keep label context
lmeyerov Dec 1, 2025
eda036c
fix(mypy): guard hop seeds and sanitize kusto NA conversion
lmeyerov Dec 1, 2025
eb3e40a
fix(mypy): satisfy pandas where overload in kusto
lmeyerov Dec 1, 2025
9f43375
fix(mypy): avoid set slicing in hop seed filtering
lmeyerov Dec 1, 2025
d1b1656
chore(mypy): use host interpreter version
lmeyerov Dec 1, 2025
52408f5
chore(doc): fix markdownlint in README
lmeyerov Dec 1, 2025
a1dd972
chore(gfql): extend ref enumerator for hop ranges
lmeyerov Dec 2, 2025
0586480
docs: add hop bounds snippet to cheatsheet
lmeyerov Dec 4, 2025
ebe9b8d
chore(predicates): drop type ignores in string helpers
lmeyerov Dec 4, 2025
82589e7
chore(predicates): remove casts while keeping mypy clean
lmeyerov Dec 4, 2025
7082d17
fix(predicates): mask cudf None propagation safely
lmeyerov Dec 4, 2025
05131a4
chore(predicates): use mask instead of chained assignment
lmeyerov Dec 4, 2025
288e8ad
chore(predicates): use where for cudf None preservation
lmeyerov Dec 4, 2025
6f5f333
chore(predicates): type hint cudf mask for mypy 3.8
lmeyerov Dec 4, 2025
f58dcfb
fix(predicates): avoid pandas 2.0.3 mypy bool error with cudf mask he…
lmeyerov Dec 4, 2025
ce2ca69
chore(predicates): tidy imports before cudf helper
lmeyerov Dec 4, 2025
abe70e2
feat(gfql): extend reference enumerator for hop bounds parity testing
lmeyerov Dec 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ jobs:
./bin/lint.sh
- name: Type check
env:
PYTHON_VERSION: ${{ matrix.python-version }}
run: |
source pygraphistry/bin/activate
./bin/typecheck.sh
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pypirc
# Distribution / packaging
.Python
env/
.venv/
.hypothesis/
build/
develop-eggs/
dist/
Expand Down
17 changes: 14 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Development]
<!-- Do Not Erase This Section - Used for tracking unreleased changes -->

### Added
- **Compute / hop**: `hop()` supports `min_hops`/`max_hops` traversal bounds plus optional hop labels for nodes, edges, and seeds, and post-traversal slicing via `output_min_hops`/`output_max_hops` to keep outputs compact while traversing wider ranges.
- **Docs / hop**: Added bounded-hop walkthrough notebook (`docs/source/gfql/hop_bounds.ipynb`), cheatsheet and GFQL spec updates, and examples showing how to combine hop ranges, labels, and output slicing.
- **GFQL / reference**: Extended the pandas reference enumerator and parity tests to cover hop ranges, labeling, and slicing so GFQL correctness checks include the new traversal shapes.
### Fixed
- **GFQL:** `Chain` now validates on construction (matching docs) and rejects invalid hops immediately; pass `validate=False` to defer validation when assembling advanced flows (fixes #860).
- **Compute / hop**: Exact-hop traversals now prune branches that do not reach `min_hops`, avoid reapplying min-hop pruning in reverse passes, keep seeds in wavefront outputs, and reuse forward wavefronts when recomputing labels so edge/node hop labels stay aligned (fixes 3-hop branch inclusion issues and mislabeled slices).
- **GFQL**: `Chain` now validates on construction (matching docs) and rejects invalid hops immediately; pass `validate=False` to defer validation when assembling advanced flows (fixes #860).
- **GFQL / eq:** `eq()` now accepts strings in addition to numeric/temporal values (use `isna()`/`notna()` for nulls); added coverage across validator, schema validation, JSON, and GFQL runtime (fixes #862).

### Docs
- **GFQL validation:** Clarified `Chain` constructor validation defaults, `validate=False` defer option, validation phases, and guidance for large/nested ASTs to reduce redundant validation (issue #860).
- **GFQL validation**: Clarified `Chain` constructor validation defaults, `validate=False` defer option, validation phases, and guidance for large/nested ASTs to reduce redundant validation (issue #860).
### Tests
- **GFQL / hop**: Expanded `test_compute_hops.py` and GFQL parity suites to assert branch pruning, bounded outputs, label collision handling, and forward/reverse slice behavior.
- **Reference enumerator**: Added oracle parity tests for hop ranges and output slices to guard GFQL integrations.
### Infra
- **CI / docs-only**: Skip Python lint/type/test matrices when the tip commit only touches docs/markdown/notebooks, and warm a shared HuggingFace cache with pinned CPU torch for AI jobs to avoid HF throttling.
- **Tooling**: `bin/lint.sh` / `bin/typecheck.sh` resolve interpreters consistently (uv → python -m → bare) without forcing PYTHON_VERSION, keeping developer and CI runs aligned.

## [0.46.0 - 2025-12-01]

Expand All @@ -39,6 +49,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Tests
- **CI / Python**: Expand GitHub Actions coverage to Python 3.13 + 3.13/3.14 for CPU lint/type/test jobs, while pinning RAPIDS-dependent CPU/GPU suites to <=3.13 until NVIDIA publishes 3.14 wheels (ensures lint/mypy/pytest signal on the latest interpreter without breaking RAPIDS installs).
- **CI / Lint & Types**: Split lint/type runners from resolution: `bin/flake8.sh`/`bin/mypy.sh` are now minimal and respect `FLAKE8_CMD`/`MYPY_CMD`; `bin/lint.sh`/`bin/typecheck.sh` resolve `uvx` → `python -m …` → bare tool, relying on `mypy.ini`’s interpreter default instead of forcing 3.8. CI still uses `.[test]` installs and the matrix interpreters.
- **GFQL**: Added deterministic + property-based oracle tests (triangles, alias reuse, cuDF conversions, Hypothesis) plus parity checks ensuring pandas GFQL chains match the oracle outputs.
- **Layouts**: Added comprehensive test coverage for `circle_layout()` and `group_in_a_box_layout()` with partition support (CPU/GPU)

Expand Down
53 changes: 20 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
[![Uptime Robot status](https://img.shields.io/uptimerobot/status/m787548531-e9c7b7508fc76fea927e2313?label=hub.graphistry.com)](https://status.graphistry.com/) [<img src="https://img.shields.io/badge/slack-Graphistry%20chat-orange.svg?logo=slack">](https://join.slack.com/t/graphistry-community/shared_invite/zt-53ik36w2-fpP0Ibjbk7IJuVFIRSnr6g)
[![Twitter Follow](https://img.shields.io/twitter/follow/graphistry)](https://twitter.com/graphistry)


<table style="width:100%;">
<tr valign="top">
<td align="center"><a href="https://hub.graphistry.com/graph/graph.html?dataset=Facebook&splashAfter=true" target="_blank"><img src="https://i.imgur.com/z8SIh2E.png" title="Click to open."></a>
Expand All @@ -34,7 +33,6 @@ PyGraphistry is an open source Python library for data scientists and developers

*[View all connectors →](https://pygraphistry.readthedocs.io/en/latest/notebooks/plugins.connectors.html)*


* [**Prototype locally and deploy remotely:**](https://www.graphistry.com/get-started) Prototype from notebooks like Jupyter and Databricks using local CPUs & GPUs, and then power production dashboards & pipelines with Graphistry Hub and your own self-hosted servers.

* [**Query graphs with GFQL:**](https://pygraphistry.readthedocs.io/en/latest/gfql/index.html) Use GFQL, the first dataframe-native graph query language, to ask relationship questions that are difficult for tabular tools and without requiring a database.
Expand All @@ -45,14 +43,10 @@ PyGraphistry is an open source Python library for data scientists and developers

* [**Columnar & GPU acceleration:**](https://pygraphistry.readthedocs.io/en/latest/performance.html) CPU-mode ingestion and wrangling is fast due to native use of Apache Arrow and columnar analytics, and the optional RAPIDS-based GPU mode delivers 100X+ speedups.


From global 10 banks, manufacturers, news agencies, and government agencies, to startups, game companies, scientists, biotechs, and NGOs, many teams are tackling their graph workloads with Graphistry.



## Gallery


The [notebook demo gallery](https://pygraphistry.readthedocs.io/en/latest/demos/for_analysis.html) shares many more live visualizations, demos, and integration examples

<table>
Expand All @@ -68,8 +62,6 @@ The [notebook demo gallery](https://pygraphistry.readthedocs.io/en/latest/demos/
</tr>
</table>



## Install

Common configurations:
Expand Down Expand Up @@ -98,7 +90,6 @@ Common configurations:

For further options, see the [installation guides](https://pygraphistry.readthedocs.io/en/latest/install/index.html)


## Visualization quickstart

Quickly go from raw data to a styled and interactive Graphistry graph visualization:
Expand Down Expand Up @@ -129,7 +120,6 @@ g1_styled.plot()

Explore [10 Minutes to Graphistry Visualization](https://pygraphistry.readthedocs.io/en/latest/visualization/10min.html) for more visualization examples and options


## PyGraphistry[AI] & GFQL quickstart - CPU & GPU

**CPU graph pipeline** combining graph ML, AI, mining, and visualization:
Expand Down Expand Up @@ -175,45 +165,42 @@ g4.plot()

Explore [10 Minutes to PyGraphistry](https://pygraphistry.readthedocs.io/en/latest/10min.html) for a wider variety of graph processing.


## PyGraphistry documentation

* [Main PyGraphistry documentation](https://pygraphistry.readthedocs.io/en/latest/)
* 10 Minutes to: [PyGraphistry](https://pygraphistry.readthedocs.io/en/latest/10min.html), [Visualization](https://pygraphistry.readthedocs.io/en/latest/visualization/10min.html), [GFQL](https://pygraphistry.readthedocs.io/en/latest/gfql/about.html)
* Get started: [Install](https://pygraphistry.readthedocs.io/en/latest/install/index.html), [UI Guide](https://hub.graphistry.com/docs/ui/index/), [Notebooks](https://pygraphistry.readthedocs.io/en/latest/demos/for_analysis.html)
* Performance: [PyGraphistry CPU+GPU](https://pygraphistry.readthedocs.io/en/latest/performance.html) & [GFQL CPU+GPU](https://pygraphistry.readthedocs.io/en/latest/gfql/performance.html)
* API References
- [PyGraphistry API Reference](https://pygraphistry.readthedocs.io/en/latest/api/index.html): [Visualization & Compute](https://pygraphistry.readthedocs.io/en/latest/visualization/index.html), [PyGraphistry Cheatsheet](https://pygraphistry.readthedocs.io/en/latest/cheatsheet.html)
- [GFQL Documentation](https://pygraphistry.readthedocs.io/en/latest/gfql/index.html): [GFQL Cheatsheet](https://pygraphistry.readthedocs.io/en/latest/gfql/quick.html) and [GFQL Operator Cheatsheet](https://pygraphistry.readthedocs.io/en/latest/gfql/predicates/quick.html)
- [Plugins](https://pygraphistry.readthedocs.io/en/latest/plugins.html): Databricks, Splunk, Neptune, Neo4j, RAPIDS, and more
- Web: [iframe](https://hub.graphistry.com/docs/api/1/rest/url/#urloptions), [JavaScript](https://hub.graphistry.com/static/js-docs/index.html?path=/docs/introduction--docs), [REST](https://hub.graphistry.com/docs/api/1/rest/auth/)
* [PyGraphistry API Reference](https://pygraphistry.readthedocs.io/en/latest/api/index.html): [Visualization & Compute](https://pygraphistry.readthedocs.io/en/latest/visualization/index.html), [PyGraphistry Cheatsheet](https://pygraphistry.readthedocs.io/en/latest/cheatsheet.html)
* [GFQL Documentation](https://pygraphistry.readthedocs.io/en/latest/gfql/index.html): [GFQL Cheatsheet](https://pygraphistry.readthedocs.io/en/latest/gfql/quick.html) and [GFQL Operator Cheatsheet](https://pygraphistry.readthedocs.io/en/latest/gfql/predicates/quick.html)
* [Plugins](https://pygraphistry.readthedocs.io/en/latest/plugins.html): Databricks, Splunk, Neptune, Neo4j, RAPIDS, and more
* Web: [iframe](https://hub.graphistry.com/docs/api/1/rest/url/#urloptions), [JavaScript](https://hub.graphistry.com/static/js-docs/index.html?path=/docs/introduction--docs), [REST](https://hub.graphistry.com/docs/api/1/rest/auth/)

## Graphistry ecosystem

- **Graphistry server:**
- Launch - [Graphistry Hub, Graphistry cloud marketplaces, and self-hosting](https://www.graphistry.com/get-started)
- Self-hosting: [Administration (including Docker)](https://github.com/graphistry/graphistry-cli) & [Kubernetes](https://github.com/graphistry/graphistry-helm)

- **Graphistry client APIs:**
- Web: [iframe](https://hub.graphistry.com/docs/api/1/rest/url/#urloptions), [JavaScript](https://hub.graphistry.com/static/js-docs/index.html?path=/docs/introduction--docs), [REST](https://hub.graphistry.com/docs/api/1/rest/auth/)
- [PyGraphistry](https://pygraphistry.readthedocs.io/en/latest/index.html)
- [Graphistry for Microsoft PowerBI](https://hub.graphistry.com/docs/powerbi/pbi/)
* **Graphistry server:**
* Launch - [Graphistry Hub, Graphistry cloud marketplaces, and self-hosting](https://www.graphistry.com/get-started)
* Self-hosting: [Administration (including Docker)](https://github.com/graphistry/graphistry-cli) & [Kubernetes](https://github.com/graphistry/graphistry-helm)

- **Additional projects**:
- [Louie.ai](https://louie.ai/): GenAI-native notebooks & dashboards to talk to your databases & Graphistry
- [graph-app-kit](https://github.com/graphistry/graph-app-kit): Streamlit Python dashboards with batteries-include graph packages
- [cu-cat](https://chat.openai.com/chat): Automatic GPU feature engineering
* **Graphistry client APIs:**
* Web: [iframe](https://hub.graphistry.com/docs/api/1/rest/url/#urloptions), [JavaScript](https://hub.graphistry.com/static/js-docs/index.html?path=/docs/introduction--docs), [REST](https://hub.graphistry.com/docs/api/1/rest/auth/)
* [PyGraphistry](https://pygraphistry.readthedocs.io/en/latest/index.html)
* [Graphistry for Microsoft PowerBI](https://hub.graphistry.com/docs/powerbi/pbi/)

* **Additional projects**:
* [Louie.ai](https://louie.ai/): GenAI-native notebooks & dashboards to talk to your databases & Graphistry
* [graph-app-kit](https://github.com/graphistry/graph-app-kit): Streamlit Python dashboards with batteries-include graph packages
* [cu-cat](https://chat.openai.com/chat): Automatic GPU feature engineering

## Community and support

- [Blog](https://www.graphistry.com/blog) for tutorials, case studies, and updates
- [Slack](https://join.slack.com/t/graphistry-community/shared_invite/zt-53ik36w2-fpP0Ibjbk7IJuVFIRSnr6g): Join the Graphistry Community Slack for discussions and support
- [Twitter](https://twitter.com/graphistry) & [LinkedIn](https://www.linkedin.com/company/graphistry): Follow for updates
- [GitHub Issues](https://github.com/graphistry/pygraphistry/issues) open source support
- [Graphistry ZenDesk](https://graphistry.zendesk.com/) dedicated enterprise support
* [Blog](https://www.graphistry.com/blog) for tutorials, case studies, and updates
* [Slack](https://join.slack.com/t/graphistry-community/shared_invite/zt-53ik36w2-fpP0Ibjbk7IJuVFIRSnr6g): Join the Graphistry Community Slack for discussions and support
* [Twitter](https://twitter.com/graphistry) & [LinkedIn](https://www.linkedin.com/company/graphistry): Follow for updates
* [GitHub Issues](https://github.com/graphistry/pygraphistry/issues) open source support
* [Graphistry ZenDesk](https://graphistry.zendesk.com/) dedicated enterprise support

## Contribute

See [CONTRIBUTING](https://pygraphistry.readthedocs.io/en/latest/CONTRIBUTING.html) and [DEVELOP](https://pygraphistry.readthedocs.io/en/latest/DEVELOP.html) for participating in PyGraphistry development, or reach out to our team

29 changes: 7 additions & 22 deletions bin/flake8.sh
Original file line number Diff line number Diff line change
@@ -1,29 +1,14 @@
#!/bin/bash
set -e

# Try to find the best Python version available
PYTHON_BIN=""
for ver in 3.14 3.13 3.12 3.11 3.10 3.9 3.8; do
if command -v python$ver &> /dev/null; then
PYTHON_BIN=python$ver
break
fi
done
# Minimal resolution: env override or host flake8
FLAKE8_CMD_ARR=(${FLAKE8_CMD:-flake8})

if [ -z "$PYTHON_BIN" ]; then
echo "No suitable Python version found (3.8-3.14)"
if ! "${FLAKE8_CMD_ARR[@]}" --version &> /dev/null; then
echo "flake8 not found. Set FLAKE8_CMD or install flake8 on PATH."
exit 1
fi

echo "Using Python: $PYTHON_BIN"
$PYTHON_BIN --version

# Install flake8 if not available
if ! $PYTHON_BIN -m flake8 --version &> /dev/null; then
echo "Installing flake8..."
$PYTHON_BIN -m pip install flake8 --user
fi

# Get the script directory and repo root
SCRIPT_DIR="$( cd "$( dirname -- "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
Expand All @@ -44,7 +29,7 @@ echo "Running flake8 on: $TARGET"

# Quick syntax error check
echo "=== Running quick syntax check ==="
$PYTHON_BIN -m flake8 \
"${FLAKE8_CMD_ARR[@]}" \
$TARGET \
--count \
--select=E9,F63,F7,F82 \
Expand All @@ -53,7 +38,7 @@ $PYTHON_BIN -m flake8 \

# Full lint check
echo "=== Running full lint check ==="
$PYTHON_BIN -m flake8 \
"${FLAKE8_CMD_ARR[@]}" \
$TARGET \
--exclude=graphistry/graph_vector_pb2.py,graphistry/_version.py \
--count \
Expand All @@ -62,4 +47,4 @@ $PYTHON_BIN -m flake8 \
--max-line-length=127 \
--statistics

echo "Flake8 check completed successfully!"
echo "Flake8 check completed successfully!"
28 changes: 9 additions & 19 deletions bin/lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,15 @@ set -ex
# Run from project root
# Non-zero exit code on fail

flake8 --version

# Quick syntax errors
flake8 \
graphistry \
--count \
--select=E9,F63,F7,F82 \
--show-source \
--statistics

# Deeper check
flake8 \
graphistry \
--exclude graphistry/graph_vector_pb2.py,graphistry/_version.py \
--count \
--ignore=C901,E121,E122,E123,E124,E125,E128,E131,E144,E201,E202,E203,E231,E251,E265,E301,E302,E303,E401,E501,E722,F401,W291,W293,W503 \
--max-complexity=10 \
--max-line-length=127 \
--statistics
# Resolve flake8 command, then delegate to runner (prefer uvx, then venv)
if command -v uvx >/dev/null 2>&1; then
FLAKE8_CMD="uvx flake8"
elif command -v python >/dev/null 2>&1; then
FLAKE8_CMD="python -m flake8"
else
FLAKE8_CMD="flake8"
fi
FLAKE8_CMD="$FLAKE8_CMD" ./bin/flake8.sh "$@"

# Check for relative imports with '..' using flake8-quotes or custom regex
# This will fail if any relative imports with .. are found
Expand Down
56 changes: 18 additions & 38 deletions bin/mypy.sh
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
#!/bin/bash
set -e

# Try to find the best Python version available
PYTHON_BIN=""
for ver in 3.14 3.13 3.12 3.11 3.10 3.9 3.8; do
if command -v python$ver &> /dev/null; then
PYTHON_BIN=python$ver
break
fi
done
# Minimal resolution: env override or host mypy
MYPY_CMD_ARR=(${MYPY_CMD:-mypy})

if [ -z "$PYTHON_BIN" ]; then
echo "No suitable Python version found (3.8-3.14)"
exit 1
MYPY_EXTRA_ARGS_ARR=()
if [ -n "${MYPY_EXTRA_ARGS:-}" ]; then
read -r -a MYPY_EXTRA_ARGS_ARR <<< "$MYPY_EXTRA_ARGS"
fi

echo "Using Python: $PYTHON_BIN"
$PYTHON_BIN --version

# Install mypy if not available
if ! $PYTHON_BIN -m mypy --version &> /dev/null; then
echo "Installing mypy..."
$PYTHON_BIN -m pip install mypy --user
# Ensure mypy exists rather than installing (works in CI & avoids PEP 668)
if ! "${MYPY_CMD_ARR[@]}" --version &> /dev/null; then
echo "mypy not found. Set MYPY_CMD or install mypy on PATH."
exit 1
fi

# Get the script directory and repo root
Expand All @@ -33,32 +24,21 @@ cd "$REPO_ROOT"

# Check if specific files were passed as arguments
if [ $# -eq 0 ]; then
# No arguments, run on entire graphistry directory using config file
TARGET=""
CONFIG_ARG="--config-file mypy.ini"
TARGET_ARGS=("graphistry")
else
# Use provided arguments
TARGET="$@"
# Still use config file for consistency
CONFIG_ARG="--config-file mypy.ini"
TARGET_ARGS=("$@")
fi
CONFIG_ARGS=(--config-file mypy.ini)

echo "Running mypy..."
if [ -z "$TARGET" ]; then
echo "Checking entire graphistry directory with mypy.ini config"
else
echo "Checking: $TARGET"
fi
echo "Checking: ${TARGET_ARGS[*]}"

# Show mypy version
$PYTHON_BIN -m mypy --version
"${MYPY_CMD_ARR[@]}" --version

# Run mypy with config file
# If no target specified, mypy will use the paths defined in mypy.ini
if [ -z "$TARGET" ]; then
$PYTHON_BIN -m mypy $CONFIG_ARG graphistry
else
$PYTHON_BIN -m mypy $CONFIG_ARG $TARGET
fi
CMD=( "${MYPY_CMD_ARR[@]}" "${MYPY_EXTRA_ARGS_ARR[@]}" "${CONFIG_ARGS[@]}" )
CMD+=( "${TARGET_ARGS[@]}" )
"${CMD[@]}"

echo "Mypy check completed!"
echo "Mypy check completed!"
13 changes: 7 additions & 6 deletions bin/typecheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ set -ex
# Run from project root
# Non-zero exit code on fail

mypy --version

if [ -n "$PYTHON_VERSION" ]; then
SHORT_VERSION=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)
mypy --python-version "$SHORT_VERSION" --config-file mypy.ini graphistry
# Resolve mypy command, then delegate to runner (prefer uvx, then venv)
if command -v uvx >/dev/null 2>&1; then
MYPY_CMD="uvx mypy"
elif command -v python >/dev/null 2>&1; then
MYPY_CMD="python -m mypy"
else
mypy --config-file mypy.ini graphistry
MYPY_CMD="mypy"
fi
MYPY_CMD="$MYPY_CMD" ./bin/mypy.sh "$@"
3 changes: 2 additions & 1 deletion docs/docker/build-docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ esac
NOTEBOOKS_TO_VALIDATE=(
"/docs/test_notebooks/test_graphistry_import.ipynb"
"/docs/source/demos/gfql/temporal_predicates.ipynb"
"/docs/source/gfql/hop_bounds.ipynb"
)

for notebook in "${NOTEBOOKS_TO_VALIDATE[@]}"; do
Expand Down Expand Up @@ -94,4 +95,4 @@ else:
echo "$(basename $notebook) execution completed successfully"
fi
fi
done
done
Loading
Loading