Skip to content

Commit 1ee3fea

Browse files
committed
feat(pypi): Remove isort and use ruff to handle all styling
feat(tests): Make formatting tests more robust to API changes feat(formatter): Fix formatter to remove unecessary list closing tag delete(requirements): Keep requirements only in pyproject.toml feat(workflows): Add publishing workflow
1 parent 9d422e6 commit 1ee3fea

13 files changed

+210
-63
lines changed

.github/workflows/check-style.yml

+5-8
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@ jobs:
2323
python-version: ${{ matrix.python-version }}
2424
- name: Install dependencies
2525
run: |
26-
python -m pip install --upgrade pip
27-
pip install -r requirements.txt
28-
- name: Examine formatting with black
26+
python -m pip install -e ".[dev]"
27+
- name: Examine formatting with ruff
2928
run: |
30-
pip install ruff
31-
ruff check .
32-
- name: Examine import ordering with isort
29+
python -m ruff check ./leetcode_study_tool
30+
- name: Check formatting
3331
run: |
34-
pip install isort
35-
isort . --check --profile black
32+
python -m ruff format ./leetcode_study_tool --check

.github/workflows/publish.yml

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: Publish to PyPi
2+
on:
3+
push:
4+
branches: [ "main" ]
5+
6+
jobs:
7+
build:
8+
name: Build distribution 📦
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- uses: actions/checkout@v4
13+
with:
14+
persist-credentials: false
15+
- name: Set up Python
16+
uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.x"
19+
- name: Install pypa/build
20+
run: >-
21+
python3 -m
22+
pip install
23+
build
24+
--user
25+
- name: Build a binary wheel and a source tarball
26+
run: python3 -m build
27+
- name: Store the distribution packages
28+
uses: actions/upload-artifact@v4
29+
with:
30+
name: python-package-distributions
31+
path: dist/
32+
33+
publish-to-pypi:
34+
name: >-
35+
Publish to PyPI
36+
if: startsWith(github.ref, 'refs/tags/')
37+
needs:
38+
- build
39+
runs-on: ubuntu-latest
40+
environment:
41+
name: pypi
42+
url: https://pypi.org/p/leetcode-study-tool
43+
permissions:
44+
id-token: write
45+
46+
steps:
47+
- name: Download all the dists
48+
uses: actions/download-artifact@v4
49+
with:
50+
name: python-package-distributions
51+
path: dist/
52+
- name: Publish to PyPI
53+
uses: pypa/gh-action-pypi-publish@release/v1
54+
55+
github-release:
56+
name: >-
57+
Sign with Sigstore
58+
and upload them to GitHub Release
59+
needs:
60+
- publish-to-pypi
61+
runs-on: ubuntu-latest
62+
63+
permissions:
64+
contents: write
65+
id-token: write
66+
67+
steps:
68+
- name: Download all the dists
69+
uses: actions/download-artifact@v4
70+
with:
71+
name: python-package-distributions
72+
path: dist/
73+
- name: Sign the dists with Sigstore
74+
uses: sigstore/[email protected]
75+
with:
76+
inputs: >-
77+
./dist/*.tar.gz
78+
./dist/*.whl
79+
- name: Create GitHub Release
80+
env:
81+
GITHUB_TOKEN: ${{ github.token }}
82+
run: >-
83+
gh release create
84+
"$GITHUB_REF_NAME"
85+
--repo "$GITHUB_REPOSITORY"
86+
--notes ""
87+
- name: Upload artifact signatures to GitHub Release
88+
env:
89+
GITHUB_TOKEN: ${{ github.token }}
90+
run: >-
91+
gh release upload
92+
"$GITHUB_REF_NAME" dist/**
93+
--repo "$GITHUB_REPOSITORY"
94+
95+
publish-to-testpypi:
96+
name: Publish Python 🐍 distribution 📦 to TestPyPI
97+
needs:
98+
- build
99+
runs-on: ubuntu-latest
100+
101+
environment:
102+
name: testpypi
103+
url: https://test.pypi.org/p/<package-name>
104+
105+
permissions:
106+
id-token: write
107+
108+
steps:
109+
- name: Download all the dists
110+
uses: actions/download-artifact@v4
111+
with:
112+
name: python-package-distributions
113+
path: dist/
114+
- name: Publish distribution 📦 to TestPyPI
115+
uses: pypa/gh-action-pypi-publish@release/v1
116+
with:
117+
repository-url: https://test.pypi.org/legacy/

.github/workflows/run-tests.yml

+2-11
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,10 @@ jobs:
2424
python-version: ${{ matrix.python-version }}
2525
- name: Install dependencies
2626
run: |
27-
python -m pip install --upgrade pip
28-
pip install -r requirements.txt
29-
- name: Lint with ruff
30-
run: |
31-
pip install ruff
32-
ruff . --ignore E501
27+
python -m pip install -e ".[dev]"
3328
- name: Type check with MyPy
3429
run: |
35-
pip install mypy
36-
mypy . --ignore-missing-imports --exclude /build/
37-
- name: Install package
38-
run: |
39-
pip install -e ".[dev]"
30+
python -m mypy ./leetcode_study_tool
4031
- name: Test with pytest, ensuring 75% coverage
4132
run: |
4233
pip install pytest pytest-cov

Makefile

+4-5
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ all:
99
$(MAKE) type-check
1010

1111
format:
12-
ruff format .
13-
isort --profile black .
12+
python -m ruff format ./leetcode_study_tool
1413

1514
format-check:
16-
ruff check .
17-
isort --check-only --profile black .
15+
python -m ruff check ./leetcode_study_tool
16+
python -m ruff format ./leetcode_study_tool --check
1817

1918
test:
2019
pytest tests/ --cov --cov-fail-under=85
2120

2221
type-check:
23-
mypy src
22+
python -m mypy ./leetcode_study_tool

README.md

+8-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![PyPi](https://img.shields.io/pypi/v/leetcode-study-tool)](https://pypi.org/project/leetcode-study-tool/)
66
![contributions welcome](https://img.shields.io/badge/contributions-welcome-blue.svg?style=flat)
77

8-
![Leetcode Study Tool Diagram](./static/leetcode_study_tool_diagram.png)
8+
![Leetcode Study Tool Diagram](https://github.com/johnsutor/leetcode-study-tool/raw/main/static/leetcode_study_tool_diagram.png)
99

1010
This package lets you get grokking as quickly as possible with Leetcode. It provides a command-line tool for interracting with Leetcode to create either an Excel file or Anki flashcards for study. Currently, this tool supports taking in a list of leetcode question slugs or URLs or popular study sets (including the [Blind 75](https://www.teamblind.com/post/New-Year-Gift---Curated-List-of-Top-75-LeetCode-Questions-to-Save-Your-Time-OaM1orEU), [Grind 75](https://www.techinterviewhandbook.org/grind75), and [Neetcode 150](https://neetcode.io/practice)).
1111

@@ -19,20 +19,16 @@ $ pip install leetcode-study-tool
1919

2020
## 💻 Usage
2121
```shell
22-
usage: leetcode-study-tool [-h]
23-
(--url URL | --file FILE | --preset {blind_75,grind_75,grind_169,neetcode_150,neetcode_all})
24-
[--format {anki,excel}] [--csrf CSRF] [--output OUTPUT]
25-
[--language LANGUAGE]
22+
usage: leetcode-study-tool [-h] (--url URL | --file FILE | --preset {blind_75,grind_75,grind_169,neetcode_150,neetcode_250,neetcode_all}) [--format {anki,excel}]
23+
[--csrf CSRF] [--output OUTPUT] [--language LANGUAGE]
2624

2725
Generates problems from LeetCode questions in a desired format.
2826

2927
options:
3028
-h, --help show this help message and exit
31-
--url URL, -u URL The URL(s) or slug(s) of the LeetCode question(s) to generate
32-
problem(s) for. (default: None)
33-
--file FILE, -f FILE The file containing the URL(s) or slug(s) of the LeetCode question(s)
34-
to generate problem(s) for. (default: None)
35-
--preset {blind_75,grind_75,grind_169,neetcode_150,neetcode_all}, -p {blind_75,grind_75,grind_169,neetcode_150,neetcode_250,neetcode_all}
29+
--url URL, -u URL The URL(s) or slug(s) of the LeetCode question(s) to generate problem(s) for. (default: None)
30+
--file FILE, -f FILE The file containing the URL(s) or slug(s) of the LeetCode question(s) to generate problem(s) for. (default: None)
31+
--preset {blind_75,grind_75,grind_169,neetcode_150,neetcode_250,neetcode_all}, -p {blind_75,grind_75,grind_169,neetcode_150,neetcode_250,neetcode_all}
3632
The preset to use to generate problem(s) for. (default: None)
3733
--format {anki,excel}, -F {anki,excel}
3834
The format to save the Leetcode problem(s) in. (default: anki)
@@ -78,11 +74,12 @@ When generating an Excel output, the resulting questions are saved in an `.xlsx`
7874
- [X] Add support for exporting to an excel sheet
7975
- [X] Add support for showing neetcode solutions on the back of the card as a
8076
- [X] Add support for getting the difficulty of questions
77+
- [ ] Add support for Jinja templating formatters
78+
- [ ] Add NeetCode shorts
8179
- [ ] Add support for fetching premium questions via authentification
8280
- [ ] Add support for importing cards into Quizlet
8381
- [ ] Add support for fetching questions by topic or tag
8482
link
85-
- [ ] Allow for the definition of custom formatters and outputs (including which fields are included or excluded)
8683
- [ ] Reach 90% test coverage
8784

8885
## 🔎 Other Usefull Stuff

leetcode_study_tool/creator.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,4 @@ def _generate_problem(self, url: str) -> Union[str, None]:
124124

125125
data = {k: self._sanitize(v) for k, v in data.items()}
126126

127-
return FORMAT_MAP[self.format](url, slug, data)
127+
return FORMAT_MAP[self.format](url, slug, data) # type: ignore

leetcode_study_tool/formatters.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def format_anki(url: str, slug: str, data: dict):
9999
if str(data["id"]) in LEETCODE_TO_NEETCODE:
100100
neetcode = LEETCODE_TO_NEETCODE[str(data["id"])]
101101
problem += "<strong>NeetCode Solution:</strong><br>"
102-
problem += f"<a href=\"{neetcode['url']}\">{neetcode['title']}</a></li><br><br>"
102+
problem += f"<a href=\"{neetcode['url']}\">{neetcode['title']}</a><br><br>"
103103

104104
if data["solutions"]:
105105
problem += format_list_element(

leetcode_study_tool/queries.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def query(
134134
requests.exceptions.HTTPError
135135
If the response from the LeetCode GraphQL API is not 200.
136136
"""
137-
assert content in MAPPINGS.keys(), f"Invalid query content: {content}"
137+
assert content in MAPPINGS, f"Invalid query content: {content}"
138138
if not session:
139139
session = generate_session()
140140

@@ -146,7 +146,7 @@ def query(
146146
},
147147
)
148148
if response.status_code == 200:
149-
return json.loads(response.content.decode("utf-8")).get("data")
149+
return dict(json.loads(response.content.decode("utf-8")).get("data"))
150150
else:
151151
raise requests.exceptions.HTTPError(
152152
f"LeetCode GraphQL API returned {response.status_code}"

pyproject.toml

+19-14
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
[build-system]
2-
requires = ["setuptools", "wheel"]
2+
requires = ["setuptools>=62.6.0", "wheel"]
33
build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "leetcode-study-tool"
7-
version = "1.3.3"
7+
version = "1.3.4"
88
description = "A tool for studying Leetcode with Python"
99
authors = [{name="John Sutor", email="[email protected]" }]
1010
license = {file = "LICENSE.txt"}
1111
readme = "README.md"
12-
13-
dependencies = ["requests", "XlsxWriter", "p_tqdm"]
1412
keywords = ["leetcode", "leet", "study", "Anki"]
1513
classifiers=[
1614
# Development status
@@ -36,15 +34,20 @@ classifiers=[
3634
'Topic :: Software Development',
3735
'Topic :: Education',
3836
]
37+
dependencies = [
38+
"requests==2.32.3",
39+
"XlsxWriter==3.2.0",
40+
"p-tqdm==1.4.2"
41+
]
3942

4043
[project.optional-dependencies]
4144
dev = [
42-
"ruff",
43-
"types-requests",
44-
"google-api-python-client",
45-
"isort",
46-
"pytest",
47-
"pytest-cov"
45+
"ruff==0.8.6",
46+
"mypy==1.14.1",
47+
"types-requests>=2.32.0",
48+
"google-api-python-client==2.157.0",
49+
"pytest==8.3.4",
50+
"pytest-cov>=5.0.0"
4851
]
4952

5053
[tool.black]
@@ -62,15 +65,17 @@ homepage = "https://github.com/johnsutor/leetcode-study-tool"
6265
repository = "https://github.com/johnsutor/leetcode-study-tool"
6366
changelog = "https://github.com/johnsutor/leetcode-study-tool/blob/main/CHANGELOG.md"
6467

68+
[tool.ruff.lint]
69+
select = ["E4", "E7", "E9", "F", "I", "B", "SIM"]
70+
6571
[tool.mypy]
6672
exclude = [
6773
"build",
6874
"scripts"
6975
]
76+
warn_return_any = true
77+
warn_unused_configs = true
7078
ignore_missing_imports = true
7179

7280
[tool.setuptools.packages.find]
73-
include = ["leetcode_study_tool"]
74-
75-
# [project.optional_dependencies]
76-
# scripts = ["google-api-python-client", "google-auth-oauthlib", "google-auth-httplib2"]
81+
include = ["leetcode_study_tool"]

requirements.txt

-6
This file was deleted.

requirements/base.txt

Whitespace-only changes.

requirements/dev.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)