Skip to content

Commit 323257a

Browse files
committed
chore: add support for Python 3.13 in CI and testing configurations
1 parent 464dbd7 commit 323257a

File tree

4 files changed

+110
-5
lines changed

4 files changed

+110
-5
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
matrix:
1818
os: [ubuntu-latest, macos-latest, windows-latest]
19-
python-version: ["3.10", "3.11", "3.12"]
19+
python-version: ["3.10", "3.11", "3.12", "3.13"]
2020

2121
steps:
2222
- name: Check out the code
@@ -56,10 +56,10 @@ jobs:
5656
- name: Check out the code
5757
uses: actions/checkout@v4
5858

59-
- name: Set up Python 3.12
59+
- name: Set up Python 3.13
6060
uses: actions/setup-python@v5
6161
with:
62-
python-version: 3.12
62+
python-version: 3.13
6363

6464
- name: Install dependencies
6565
run: python3 -m pip install -U pip tox
@@ -73,10 +73,10 @@ jobs:
7373
- name: Check out the code
7474
uses: actions/checkout@v4
7575

76-
- name: Set up Python 3.12
76+
- name: Set up Python 3.13
7777
uses: actions/setup-python@v5
7878
with:
79-
python-version: 3.12
79+
python-version: 3.13
8080

8181
- name: Install dependencies
8282
run: python3 -m pip install -U pip tox

fakernaija/tests/providers/test_state_provider.py

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

88
import unittest
9+
from unittest.mock import patch
910

1011
from fakernaija.providers import StateProvider
1112

@@ -67,3 +68,102 @@ def test_get_state_error(self) -> None:
6768
"Invalid state: InvalidState.",
6869
str(context.exception),
6970
)
71+
72+
73+
class TestStateProviderExtended(unittest.TestCase):
74+
"""Extended tests for the StateProvider class to cover additional code paths."""
75+
76+
def setUp(self) -> None:
77+
"""Sample states data for testing."""
78+
self.sample_states = [
79+
{
80+
"name": "Lagos",
81+
"code": "LA",
82+
"capital": "Ikeja",
83+
"slogan": "Power of the Sea",
84+
"lgas": [
85+
{"name": "Ikeja", "code": "001"},
86+
{"name": "Epe", "code": "002"},
87+
],
88+
"region": "South West",
89+
"postal_code": "100001",
90+
},
91+
{
92+
"name": "Kaduna",
93+
"code": "KD",
94+
"capital": "Kaduna",
95+
"slogan": "Centre of Learning",
96+
"lgas": [
97+
{"name": "Kaduna North", "code": "003"},
98+
{"name": "Kaduna South", "code": "004"},
99+
],
100+
"region": "North West",
101+
"postal_code": "200001",
102+
},
103+
]
104+
# Patch load_json in the state provider module so that our sample data is used.
105+
patcher = patch(
106+
"fakernaija.providers.state.load_json", return_value=self.sample_states
107+
)
108+
self.mock_load_json = patcher.start()
109+
self.addCleanup(patcher.stop)
110+
self.state_provider = (
111+
StateProvider()
112+
) # Uses patched data and runs _generate_region_abbrs()
113+
114+
def test_get_lgas(self) -> None:
115+
"""Test that get_lgas returns all LGAs from all states."""
116+
lgas = self.state_provider.get_lgas()
117+
expected = [
118+
{"name": "Ikeja", "code": "001"},
119+
{"name": "Epe", "code": "002"},
120+
{"name": "Kaduna North", "code": "003"},
121+
{"name": "Kaduna South", "code": "004"},
122+
]
123+
self.assertEqual(lgas, expected)
124+
125+
def test_get_state_lgas_valid(self) -> None:
126+
"""Test that get_state_lgas returns LGAs for a valid state."""
127+
lgas = self.state_provider.get_state_lgas("Lagos")
128+
expected = [{"name": "Ikeja", "code": "001"}, {"name": "Epe", "code": "002"}]
129+
self.assertEqual(lgas, expected)
130+
131+
def test_get_state_lgas_invalid(self) -> None:
132+
"""Test that get_state_lgas raises a ValueError for an invalid state."""
133+
with self.assertRaises(ValueError) as context:
134+
self.state_provider.get_state_lgas("InvalidState")
135+
# Verify that the error message mentions the invalid state.
136+
self.assertIn("Invalid state: InvalidState.", str(context.exception))
137+
138+
def test_get_lga_codes_all(self) -> None:
139+
"""Test that get_lga_codes returns LGA codes for all states when no state is specified."""
140+
lga_codes = self.state_provider.get_lga_codes()
141+
expected = {
142+
"Lagos": ["001", "002"],
143+
"Kaduna": ["003", "004"],
144+
}
145+
self.assertEqual(lga_codes, expected)
146+
147+
def test_get_lga_codes_specific(self) -> None:
148+
"""Test that get_lga_codes returns LGA codes for a specific state."""
149+
lga_codes = self.state_provider.get_lga_codes("Kaduna")
150+
expected = {"Kaduna": ["003", "004"]}
151+
self.assertEqual(lga_codes, expected)
152+
153+
def test_get_state_suggestions(self) -> None:
154+
"""Test that _get_state returns suggestions when a near-match is provided."""
155+
# Patch difflib.get_close_matches to simulate suggestions.
156+
with patch(
157+
"fakernaija.providers.state.difflib.get_close_matches",
158+
return_value=["Lagos"],
159+
) as mock_get_close_matches:
160+
with self.assertRaises(ValueError) as context:
161+
self.state_provider.get_postal_code_by_state("Lago")
162+
error_message = str(context.exception)
163+
# Verify that the error message contains a suggestion.
164+
self.assertIn("Did you mean: Lagos?", error_message)
165+
# Check that get_close_matches was called with expected arguments.
166+
available_states = ", ".join(self.state_provider.get_state_names())
167+
mock_get_close_matches.assert_called_with(
168+
"Lago", available_states, n=3, cutoff=0.6
169+
)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ classifiers = [
2020
"Programming Language :: Python :: 3.10",
2121
"Programming Language :: Python :: 3.11",
2222
"Programming Language :: Python :: 3.12",
23+
"Programming Language :: Python :: 3.13",
2324
"Programming Language :: Python :: Implementation :: PyPy",
2425
"Operating System :: OS Independent",
2526
"Topic :: Software Development :: Libraries :: Python Modules",

tox.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ basepython = python3.11
2929
[testenv:py312]
3030
description = Test with Python 3.12
3131
basepython = python3.12
32+
33+
[testenv:py313]
34+
description = Test with Python 3.13
35+
basepython = python3.13
3236
commands_pre =
3337
coverage erase
3438
commands_post =

0 commit comments

Comments
 (0)