Skip to content

Commit 37e8eb4

Browse files
authored
Migrate to uv (#153)
* chore: switch poetry to uv * chore: update CI * lint: fix ruff complaints
1 parent 6caf16b commit 37e8eb4

File tree

13 files changed

+1556
-888
lines changed

13 files changed

+1556
-888
lines changed
Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3-
4-
name: Python package
1+
name: Test and lint
52

63
on:
74
push:
@@ -11,34 +8,45 @@ on:
118

129
jobs:
1310
build:
14-
1511
runs-on: ubuntu-latest
1612
strategy:
1713
matrix:
18-
python-version: [3.8, 3.9, '3.10', '3.11']
14+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
1915

2016
steps:
21-
22-
- uses: actions/checkout@v2
23-
24-
- name: Set up Python ${{ matrix.python-version }}
25-
uses: actions/setup-python@v2
26-
with:
27-
python-version: ${{ matrix.python-version }}
28-
29-
- name: Install dependencies
30-
run: |
31-
python -m pip install --upgrade pip
32-
pip install flake8 pytest
33-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
34-
35-
- name: Lint with flake8
36-
run: |
37-
# stop the build if there are Python syntax errors or undefined names
38-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
39-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
40-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
41-
42-
- name: Test with pytest
43-
run: |
44-
pytest
17+
- uses: actions/checkout@v3
18+
19+
- name: Set up Python ${{ matrix.python-version }}
20+
uses: actions/setup-python@v3
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
24+
- name: Install uv
25+
run: |
26+
curl -LsSf https://astral.sh/uv/install.sh | sh
27+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
28+
29+
- name: Cache virtual environment
30+
uses: actions/cache@v3
31+
with:
32+
path: .venv
33+
key: venv-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
34+
restore-keys: |
35+
venv-${{ matrix.python-version }}-
36+
37+
- name: Set up uv venv and install dependencies
38+
run: |
39+
uv venv
40+
source .venv/bin/activate
41+
uv pip install ruff pytest pytest-cov pytest-codspeed
42+
uv pip install -e .
43+
44+
- name: Lint with ruff
45+
run: |
46+
source .venv/bin/activate
47+
ruff check dotmotif
48+
49+
- name: Test with pytest
50+
run: |
51+
source .venv/bin/activate
52+
pytest

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
- **0.16.0** (January 08, 2026)
4+
- Housekeeping:
5+
- Migrated from Poetry to uv for package management
6+
- Updated GitHub Actions workflows to use uv and added testing for Python 3.12 through 3.14
7+
- Upgraded from `lark-parser` to `lark` for parsing
8+
- Updated copyright years
39
- **0.15.0** (August 21 2024)
410
- Backwards-incompatible changes:
511
- Removed the Docker container provisioning functionality from the `Neo4jExecutor` class. To continue using this functionality, please use the `tamarind` package directly, or install `dotmotif==0.14.0`

dotmotif/__init__.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
22
"""
3-
Copyright 2022 The Johns Hopkins University Applied Physics Laboratory.
3+
Copyright 2022-2026 The Johns Hopkins Applied Physics Laboratory.
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.
@@ -170,7 +170,20 @@ def list_automorphisms(self):
170170
return self._automorphisms
171171

172172
g = self.to_nx()
173-
res = isomorphism.GraphMatcher(g, g).subgraph_isomorphisms_iter()
173+
# Choose the appropriate VF2 matcher depending on directedness
174+
# and whether the graph is a multigraph.
175+
if g.is_directed():
176+
if g.is_multigraph():
177+
matcher_cls = isomorphism.MultiDiGraphMatcher
178+
else:
179+
matcher_cls = isomorphism.DiGraphMatcher
180+
else:
181+
if g.is_multigraph():
182+
matcher_cls = isomorphism.MultiGraphMatcher
183+
else:
184+
matcher_cls = isomorphism.GraphMatcher
185+
186+
res = matcher_cls(g, g).subgraph_isomorphisms_iter()
174187
autos = set()
175188
for auto in res:
176189
for k, v in auto.items():
@@ -235,3 +248,6 @@ def load(fname: Union[str, IO[bytes]]) -> "Motif":
235248
result = pickle.load(f)
236249
f.close()
237250
return result
251+
252+
253+
__all__ = ["Motif", "MotifError", "NetworkXExecutor", "GrandIsoExecutor"]

dotmotif/executors/NetworkXExecutor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright 2022 The Johns Hopkins University Applied Physics Laboratory.
2+
Copyright 2022-2026 The Johns Hopkins Applied Physics Laboratory.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.

dotmotif/executors/test_neo4jexecutor.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import dotmotif
22
from dotmotif.executors.Neo4jExecutor import Neo4jExecutor, _quoted_if_necessary
33
import unittest
4-
import networkx as nx
54

65

76
class TestNeo4jExecutor_Automorphisms(unittest.TestCase):

dotmotif/ingest/__init__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ class NetworkXConverter(abc.ABC):
1919

2020
pass
2121

22-
def to_graph(self) -> nx.Graph:
23-
...
22+
def to_graph(self) -> nx.Graph: ...
2423

2524

2625
class EdgelistConverter(NetworkXConverter):
@@ -53,12 +52,12 @@ def __init__(
5352
raise KeyError(f"Dataframe does not contain column {v_id_column}.")
5453
self._graph = nx.DiGraph() if directed else nx.Graph()
5554
for i, row in data.iterrows():
56-
if u_id_column_dtype != str:
55+
if u_id_column_dtype is not str:
5756
u = np.format_float_positional(row[u_id_column])
5857
else:
5958
u = row[u_id_column]
6059

61-
if v_id_column_dtype != str:
60+
if v_id_column_dtype is not str:
6261
v = np.format_float_positional(row[v_id_column])
6362
else:
6463
v = row[v_id_column]

dotmotif/ingest/test_ingest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_ingest(self):
2424

2525
def test_read_csv(self):
2626
converter = EdgelistConverter(
27-
io.StringIO("source,target\n" "A,B\n" "A,C\n"),
27+
io.StringIO("source,target\nA,B\nA,C\n"),
2828
"source",
2929
"target",
3030
)

dotmotif/parsers/v2/test_v2_parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def test_can_create_variables_with_underscores(self):
5151

5252
def test_cannot_create_variables_with_dashes(self):
5353
with self.assertRaises(Exception):
54-
dm = dotmotif.Motif("""A -> B-""")
54+
dotmotif.Motif("""A -> B-""")
5555

5656
def test_can_create_variables_with_numbers(self):
5757
dm = dotmotif.Motif("""A_2 -> B1""")
@@ -503,7 +503,7 @@ def test_failed_node_lookup(self):
503503
C.radius < B.radius
504504
"""
505505
with self.assertRaises(KeyError):
506-
dm = dotmotif.Motif(exp)
506+
dotmotif.Motif(exp)
507507

508508

509509
class TestEdgeAliasConstraints(unittest.TestCase):
@@ -546,7 +546,7 @@ def test_failed_edge_lookup(self):
546546
acb.radius = 3
547547
"""
548548
with self.assertRaises(KeyError):
549-
dm = dotmotif.Motif(exp)
549+
dotmotif.Motif(exp)
550550

551551
def test_quoted_attribute_edge_constraint(self):
552552
exp = """\

dotmotif/tests/test_dm_flags.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,6 @@ def test_dm_parser_limit(self):
7070
dm.from_motif(_DEMO_G_MIN)
7171
self.assertFalse("LIMIT" in Neo4jExecutor.motif_to_cypher(dm).strip())
7272

73-
def test_from_nx_import(self):
74-
G = nx.Graph()
75-
G.add_edge("A", "B")
76-
G.add_edge("B", "C")
77-
78-
g = nx.Graph()
79-
g.add_edge("A", "B")
80-
dm = dotmotif.Motif().from_nx(g)
81-
82-
E = GrandIsoExecutor(graph=G)
83-
self.assertEqual(len(E.find(dm)), 4)
84-
8573
def test_from_nx_import(self):
8674
G = nx.Graph()
8775
G.add_edge("A", "B")

dotmotif/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
Requires nx>=2.0
77
"""
8+
89
import hashlib
910
import json
1011
import networkx as nx
@@ -13,12 +14,12 @@
1314
def untype_string(string):
1415
try:
1516
return eval(string)
16-
except:
17+
except: # noqa
1718
try:
1819
if int(string) == float(string):
1920
return int(string)
2021
return float(string)
21-
except:
22+
except: # noqa
2223
return str(string)
2324

2425

0 commit comments

Comments
 (0)