Skip to content

Commit dd749cf

Browse files
authored
🔀 Merge pull request #30 from davep/sortable
Make various items in the API sortable
2 parents 0bf66c0 + 4b8967f commit dd749cf

9 files changed

Lines changed: 159 additions & 10 deletions

File tree

.github/workflows/style-and-lint.yaml renamed to .github/workflows/style-lint-and-test.yaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ on:
88

99
jobs:
1010

11-
style-and-lint:
11+
style-lint-and-test:
1212

13-
name: Style and lint
13+
name: Style, lint, test
1414
runs-on: ubuntu-latest
1515
strategy:
1616
matrix:
@@ -50,4 +50,7 @@ jobs:
5050
- name: Type check the code
5151
run: make stricttypecheck
5252

53-
### style-and-lint.yaml ends here
53+
- name: Run unit tests
54+
run: make test
55+
56+
### style-lint-and-test.yaml ends here

ChangeLog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# OldAS ChangeLog
22

3+
## Unrelased
4+
5+
**Released: WiP**
6+
7+
- Make `Folders` sortable by `Folder.name` by default.
8+
([#30](https://github.com/davep/oldas/pull/30))
9+
- Make `Subscriptons` sortable by `Subscription.title` by default.
10+
([#30](https://github.com/davep/oldas/pull/30))
11+
312
## v0.6.0
413

514
**Released: 2026-01-25**

Makefile

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
lib := oldas
22
src := src/
3+
tests := tests/
34
docs := docs/
45
run := uv run --env-file .env
56
sync := uv sync
67
build := uv build
78
publish := uv publish --username=__token__ --keyring-provider=subprocess
9+
test := $(run) pytest
810
python := $(run) python
911
ruff := $(run) ruff
1012
lint := $(ruff) check --select I
@@ -38,26 +40,30 @@ resetup: realclean # Recreate the virtual environment from scratch
3840
# Checking/testing/linting/etc.
3941
.PHONY: lint
4042
lint: # Check the code for linting issues
41-
$(lint) $(src)
43+
$(lint) $(src) $(tests)
4244

4345
.PHONY: codestyle
4446
codestyle: # Is the code formatted correctly?
45-
$(fmt) --check $(src)
47+
$(fmt) --check $(src) $(tests)
4648

4749
.PHONY: typecheck
4850
typecheck: # Perform static type checks with mypy
49-
$(mypy) --scripts-are-modules $(src)
51+
$(mypy) --scripts-are-modules $(src) $(tests)
5052

5153
.PHONY: stricttypecheck
5254
stricttypecheck: # Perform a strict static type checks with mypy
53-
$(mypy) --scripts-are-modules --strict $(src)
55+
$(mypy) --scripts-are-modules --strict $(src) $(tests)
56+
57+
.PHONY: test
58+
test: # Run the unit tests
59+
$(test) -v
5460

5561
.PHONY: spellcheck
5662
spellcheck: # Spell check the code
57-
$(spell) *.md $(src) $(docs)
63+
$(spell) *.md $(src) $(docs) $(tests)
5864

5965
.PHONY: checkall
60-
checkall: spellcheck codestyle lint stricttypecheck # Check all the things
66+
checkall: spellcheck codestyle lint stricttypecheck test # Check all the things
6167

6268
##############################################################################
6369
# Documentation.
@@ -103,7 +109,7 @@ delint: # Fix linting issues.
103109

104110
.PHONY: pep8ify
105111
pep8ify: # Reformat the code to be as PEP8 as possible.
106-
$(fmt) $(src)
112+
$(fmt) $(src) $(tests)
107113

108114
.PHONY: tidy
109115
tidy: delint pep8ify # Tidy up the code, fixing lint and format issues.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ dev = [
6060
"mkdocstrings[python]>=1.0.0",
6161
"mypy>=1.18.2",
6262
"pre-commit>=4.3.0",
63+
"pytest>=9.0.2",
6364
"ruff>=0.14.0",
6465
]
6566

src/oldas/folders.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
##############################################################################
88
# Python imports.
9+
from functools import total_ordering
910
from typing import NamedTuple
1011

1112
##############################################################################
@@ -16,6 +17,7 @@
1617

1718

1819
##############################################################################
20+
@total_ordering
1921
class Folder(NamedTuple):
2022
"""Folder information class."""
2123

@@ -47,6 +49,16 @@ def from_json(cls, data: RawData) -> Folder:
4749
sort_id=data["sortid"],
4850
)
4951

52+
def __gt__(self, value: object, /) -> bool:
53+
if isinstance(value, Folder):
54+
return self.name > value.name
55+
raise NotImplementedError
56+
57+
def __eq__(self, value: object, /) -> bool:
58+
if isinstance(value, Folder):
59+
return self.name == value.name
60+
raise NotImplementedError
61+
5062

5163
##############################################################################
5264
class Folders(OldList[Folder]):

src/oldas/subscriptions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
##############################################################################
88
# Python imports.
99
from datetime import datetime, timezone
10+
from functools import total_ordering
1011
from typing import NamedTuple
1112

1213
##############################################################################
@@ -51,6 +52,7 @@ class Categories(OldList[Category]):
5152

5253

5354
##############################################################################
55+
@total_ordering
5456
class Subscription(NamedTuple):
5557
"""Holds a subscription."""
5658

@@ -116,6 +118,16 @@ def folder_id(self) -> str | None:
116118
None,
117119
)
118120

121+
def __gt__(self, value: object, /) -> bool:
122+
if isinstance(value, Subscription):
123+
return self.title > value.title
124+
raise NotImplementedError
125+
126+
def __eq__(self, value: object, /) -> bool:
127+
if isinstance(value, Subscription):
128+
return self.title == value.title
129+
raise NotImplementedError
130+
119131

120132
##############################################################################
121133
class SubscribeResult(NamedTuple):

tests/unit/test_folders.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Tests for the code relating to folders."""
2+
3+
##############################################################################
4+
# Local imports.
5+
from oldas import Folder, Folders
6+
from oldas.prefixes import Prefix
7+
8+
##############################################################################
9+
TEST_FOLDERS = Folders(
10+
[
11+
Folder.from_json({"id": f"{Prefix.FOLDER}z", "sortid": ""}),
12+
Folder.from_json({"id": f"{Prefix.FOLDER}a", "sortid": ""}),
13+
]
14+
)
15+
16+
17+
##############################################################################
18+
def test_sort_folders() -> None:
19+
"""Folders should sort by name."""
20+
assert [folder.name for folder in TEST_FOLDERS] == ["z", "a"]
21+
assert [folder.name for folder in sorted(TEST_FOLDERS)] == ["a", "z"]
22+
23+
24+
### test_folders.py ends here

tests/unit/test_subscriptions.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""Tests for code relating to the subscriptions."""
2+
3+
##############################################################################
4+
# Local imports.
5+
from oldas import Subscription, Subscriptions
6+
7+
##############################################################################
8+
TEST_SUBSCRIPTIONS = Subscriptions(
9+
[
10+
Subscription.from_json(
11+
{
12+
"id": "1",
13+
"title": "z",
14+
"sortid": "",
15+
"firstitemmsec": 0,
16+
"url": "https://example.com/",
17+
"htmlUrl": "https://example.com/",
18+
"categories": [],
19+
}
20+
),
21+
Subscription.from_json(
22+
{
23+
"id": "1",
24+
"title": "a",
25+
"sortid": "",
26+
"firstitemmsec": 0,
27+
"url": "https://example.com/",
28+
"htmlUrl": "https://example.com/",
29+
"categories": [],
30+
}
31+
),
32+
]
33+
)
34+
35+
36+
##############################################################################
37+
def test_sort_subscriptions() -> None:
38+
"""Subscriptions should sort by title."""
39+
assert [subscription.title for subscription in TEST_SUBSCRIPTIONS] == ["z", "a"]
40+
assert [subscription.title for subscription in sorted(TEST_SUBSCRIPTIONS)] == [
41+
"a",
42+
"z",
43+
]
44+
45+
46+
### test_subscriptions.py ends here

uv.lock

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)