nepkit 0.2.0__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nepkit
3
- Version: 0.2.0
3
+ Version: 0.4.0
4
4
  Summary: Typed Bikram Sambat ↔ Gregorian date conversion, as a library and a CLI.
5
5
  Keywords: nepal,bikram-sambat,nepali-date,calendar,cli
6
6
  Author: Kritagya
@@ -17,7 +17,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
17
  Classifier: Topic :: Utilities
18
18
  Classifier: Typing :: Typed
19
19
  Requires-Dist: typer>=0.15,<0.28
20
+ Requires-Dist: rich>=13,<16
20
21
  Requires-Dist: pyreadline3>=3.5 ; sys_platform == 'win32'
22
+ Requires-Dist: tzdata>=2024.1 ; sys_platform == 'win32'
21
23
  Requires-Python: >=3.12
22
24
  Project-URL: Homepage, https://github.com/akakritagya/nepkit
23
25
  Project-URL: Issues, https://github.com/akakritagya/nepkit/issues
@@ -43,8 +45,11 @@ command-line tool.
43
45
  [![Python](https://img.shields.io/pypi/pyversions/nepkit)](https://pypi.org/project/nepkit/)
44
46
  [![License](https://img.shields.io/pypi/l/nepkit)](https://github.com/akakritagya/nepkit/blob/main/LICENSE)
45
47
 
46
- > **Status:** first release. The library and CLI both work and are tested; the
47
- > API may still change before 1.0.
48
+ > **Status:** published, pre-1.0. The library and CLI both work and are
49
+ > tested, but the API and the CLI's output shapes may still change before
50
+ > 1.0. Pin a version if you script against stdout, or use `--json` instead.
51
+ > See [STATUS.md](https://github.com/akakritagya/nepkit/blob/main/STATUS.md)
52
+ > for what's changed release to release.
48
53
 
49
54
  [**DEMO.md**](https://github.com/akakritagya/nepkit/blob/main/DEMO.md) walks
50
55
  through every command, option, and failure mode with real captured output.
@@ -119,10 +124,11 @@ works as written.
119
124
  ```python
120
125
  from datetime import date
121
126
 
122
- from nepkit import BSDate, ad_to_bs, bs_to_ad
127
+ from nepkit import BSDate, __version__, ad_to_bs, bs_to_ad
123
128
 
124
129
  bs_to_ad(BSDate(2081, 4, 15)) # date(2024, 7, 30)
125
130
  ad_to_bs(date(2024, 7, 30)) # BSDate(year=2081, month=4, day=15)
131
+ __version__ # "0.4.0"
126
132
  ```
127
133
 
128
134
  `BSDate` validates on construction, so if you are holding one it is a real date
@@ -142,6 +148,33 @@ BSDate(2095, 1, 1) # raises DateOutOfRangeError
142
148
  `ad_to_bs` takes a `datetime.date`, so a malformed Gregorian date is impossible
143
149
  by construction — Python's own constructor rejects it before nepkit is involved.
144
150
 
151
+ `BSDate` mirrors `datetime.date`'s string handling, and `parse_bs_date`/
152
+ `format_bs_date` (with Gregorian counterparts `parse_ad_date`/`format_ad_date`)
153
+ cover the human-readable forms the CLI accepts and prints — the CLI is a thin
154
+ layer over these, not a separate implementation:
155
+
156
+ ```python
157
+ from nepkit import BSDate, format_bs_date, parse_ad_date, parse_bs_date
158
+
159
+ bs = BSDate(2081, 4, 15)
160
+ str(bs) # "2081-04-15"
161
+ BSDate.fromisoformat("2081-04-15") # BSDate(year=2081, month=4, day=15)
162
+
163
+ # "D Month YYYY", the month matched case-insensitively against a common
164
+ # romanisation variant or Devnagari, not just BS_MONTH_NAMES's one spelling
165
+ parse_bs_date("15 Baishakh 2081") # BSDate(year=2081, month=1, day=15)
166
+
167
+ format_bs_date(bs, named=True) # "15 Shrawan 2081"
168
+ format_bs_date(bs, named=True, devnagari=True) # "१५ साउन २०८१"
169
+
170
+ parse_ad_date("30 Jul 2024") # date(2024, 7, 30)
171
+ ```
172
+
173
+ `BSDate.isoformat()`'s result is not an ISO 8601 date — `datetime.date.fromisoformat`
174
+ will accept it and silently return a different, wrong Gregorian day. It is
175
+ only ever meaningful alongside something that says it is Bikram Sambat, the
176
+ same way nepkit's CLI always prints a `BS`/`AD` label alongside it.
177
+
145
178
  ### Errors
146
179
 
147
180
  ```text
@@ -165,15 +198,18 @@ add` installs into the project's `.venv` without activating it, so reach the
165
198
  command with `uv run nepkit` — or activate the venv first.
166
199
 
167
200
  ```console
201
+ $ nepkit --version
202
+ nepkit 0.4.0
203
+
168
204
  $ nepkit bs2ad 2081-04-15
169
- 2024-07-30 Tue
205
+ AD 30 Jul 2024 (2024-07-30) Tue
170
206
 
171
- $ nepkit ad2bs 2024-07-30
172
- 2081-04-15 Tue
207
+ $ nepkit ad2bs "30 July 2024"
208
+ BS 15 Shrawan 2081 (2081-04-15) Tue
173
209
 
174
210
  $ nepkit today
175
- BS 2083-04-27 Wed
176
- AD 2026-08-12 Wed
211
+ BS २७ साउन २०८३ १४:३२ बुध
212
+ AD 12 Aug 2026 14:32 Wed
177
213
 
178
214
  $ nepkit range
179
215
  BS 2000-01-01 .. 2090-12-30 (years 2000-2090)
@@ -184,6 +220,19 @@ Direction is always explicit, and has to be: the BS and AD year numbers overlap
184
220
  from 2000 to 2034, so `2024` is a valid year in both calendars and nothing
185
221
  could reliably guess which one you meant.
186
222
 
223
+ `bs2ad`/`ad2bs` accept the date either as `YYYY-MM-DD` or as `"D Month YYYY"`
224
+ (e.g. `"1 Baisakh 2083"`, `"1 Jan 2000"` or `"1 January 2000"`) — the month
225
+ name matched case-insensitively either way, so `Shrawan`, `shrawan`, and
226
+ `SHRAWAN` all work. The BS side also accepts common romanisation variants
227
+ (`Baishakh` alongside `Baisakh`, `Sawan` alongside `Shrawan`, ...) and
228
+ Devnagari month names (`साउन`), not just the one spelling `BS_MONTH_NAMES`
229
+ prints — `calbs`'s month argument does the same.
230
+
231
+ `today` defaults to `--script devnagari`, so its BS line reads Devnagari
232
+ without any flag; pass `--script latin` for the romanised form instead. The
233
+ AD line is always Latin. `bs2ad`/`ad2bs`/`range` default to `latin` and need
234
+ `--script devnagari` explicitly.
235
+
187
236
  ### Interactive
188
237
 
189
238
  Run `nepkit` with no arguments in a terminal and it clears the screen and opens
@@ -197,17 +246,17 @@ $ nepkit
197
246
  | | | || __/ | |_) || < | || |_
198
247
  |_| |_| \___| | .__/ |_|\_\|_| \__|
199
248
  |_|
200
- nepkit v0.2.0 - Bikram Sambat (BS) <-> Gregorian (AD) date conversion
201
- Today BS 2083-04-27 AD 2026-08-12 Wed
249
+ nepkit v0.4.0 - Bikram Sambat (BS) <-> Gregorian (AD) date conversion
250
+ Today 14:32 NPT BS 27 Shrawan 2083 AD 12 Aug 2026 14:32 Wed
202
251
 
203
252
  Type a command, 'help', 'clear', or 'quit'. Up/Down recalls history.
204
253
 
205
254
  nepkit> today
206
- BS 2083-04-27 Wed
207
- AD 2026-08-12 Wed
255
+ BS २७ साउन २०८३ १४:३२ बुध
256
+ AD 12 Aug 2026 14:32 Wed
208
257
 
209
258
  nepkit> bs2ad 2081-04-15
210
- 2024-07-30 Tue
259
+ AD 30 Jul 2024 (2024-07-30) Tue
211
260
 
212
261
  nepkit> quit
213
262
  ```
@@ -256,13 +305,28 @@ Sun Mon Tue Wed Thu Fri Sat
256
305
  28 29 30 31
257
306
  ```
258
307
 
308
+ Shown here without a box: grids are boxed and coloured only on a real
309
+ terminal, and plain like this when redirected — piped, or captured for this
310
+ README — the same convention `ls` and `git` follow. See
311
+ [DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#colour) for
312
+ what it looks like on a terminal. Force it either way with
313
+ `--color always|never|auto`.
314
+
259
315
  Both default to the current month. A Gregorian month never lines up with a BS
260
316
  month, so the subtitle names both ends of the span rather than pretending a
261
317
  single corresponding month exists.
262
318
 
263
- Grids are boxed and coloured on a terminal and plain when redirected, following
264
- the same convention as `ls` and `git`. Force it either way with
265
- `--color always|never|auto`.
319
+ The month argument accepts a name too, case-insensitively — `calbs` matches
320
+ BS names (`Shrawan`/`shrawan`, a romanisation variant like `Sawan`, or a
321
+ Devnagari name like `साउन`), `calad` matches English names or 3-letter
322
+ abbreviations (`July`/`Jul`/`jul`) — alongside the numeric `1`-`12` form:
323
+
324
+ ```bash
325
+ nepkit calbs 2081 Shrawan
326
+ nepkit calad 2024 Jul
327
+ ```
328
+
329
+ Neither command takes `--script` — see [Limitations](#limitations) below.
266
330
 
267
331
  On a terminal, today's date is picked out in bold bright cyan — the bright form
268
332
  of the box's own border colour, so the highlight belongs to the grid containing
@@ -333,19 +397,47 @@ the standard library.
333
397
  `datetime.date` rather than three integers, which removes an entire error class
334
398
  from its contract at no cost.
335
399
 
400
+ **Human-text parsing and formatting are library code, not CLI code.** The CLI
401
+ used to own `parse_bs_date`/`format_bs_date` and friends as private helpers,
402
+ which meant a library caller could not parse `"1 Baisakh 2083"` into a
403
+ `BSDate`, or format one back into that form, at all -- only the CLI process
404
+ could. They moved into the library so the CLI is provably a thin layer over
405
+ it rather than a second implementation that has to be kept in sync by hand.
406
+
336
407
  ## Limitations
337
408
 
338
- - **Dates only.** No time of day, no timezones, no Nepali-language month names
339
- or numeral formatting.
409
+ - **Time of day works only in Nepal Standard Time (UTC+05:45).** `BSDateTime`
410
+ and `bs_datetime_to_ad_datetime`/`ad_datetime_to_bs_datetime` carry a
411
+ naive time-of-day through the date conversion; nepkit does not convert
412
+ between timezones. A tz-aware `datetime` is rejected outright rather than
413
+ silently treated as NPT — convert it yourself with `astimezone` first. In
414
+ the CLI, only `today` and the interactive banner show the time; there is
415
+ no `--time` flag on `bs2ad`/`ad2bs`.
416
+ - **Devnagari formatting stops at the calendar grid.** `--script devnagari`
417
+ covers `bs2ad`/`ad2bs`/`today`/`range` and the library
418
+ (`nepkit.BS_MONTH_NAMES_NE`, `nepkit.format_bs_date`/`nepkit.bs_month_name`'s
419
+ `devnagari` flag, and `nepkit.render`'s grid functions); `calbs` and `calad`
420
+ render Latin only. `today` defaults to `--script devnagari` (the
421
+ others default to `latin`), and its AD line is Latin regardless of
422
+ `--script` -- there is no Devnagari table for Gregorian month names, so the
423
+ option only ever touches its BS line. See
424
+ [DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#script).
340
425
  - **The range is hard-bounded** at BS 2000–2090 and will not extrapolate.
341
- - **Correctness rests on the data, and the tests cannot prove it.** The test
342
- suite verifies self-consistency exhaustively — every one of the 33,238 days
343
- round-trips, and consecutive day counts produce consecutive dates. But both
344
- directions read the same table, so a wrong month length cancels out exactly
345
- and every property still passes. This was verified by deliberately corrupting
346
- the table: all properties passed while conversions were silently wrong. Only
347
- the sourcing described in [`src/nepkit/data/DATA.md`](https://github.com/akakritagya/nepkit/blob/main/src/nepkit/data/DATA.md)
348
- stands behind the numbers themselves.
426
+ - **Correctness rests on the data, and round-trip tests alone cannot prove
427
+ it.** The property suite verifies self-consistency exhaustively — every one
428
+ of the 33,238 days round-trips, and consecutive day counts produce
429
+ consecutive dates. But both directions read the same table, so a wrong
430
+ month length cancels out exactly and every property still passes. This was
431
+ verified by deliberately corrupting the table: all properties passed while
432
+ conversions were silently wrong. Two things stand behind the numbers
433
+ themselves instead: the independent sourcing in
434
+ [`src/nepkit/data/DATA.md`](https://github.com/akakritagya/nepkit/blob/main/src/nepkit/data/DATA.md),
435
+ and [`tests/test_oracle.py`](https://github.com/akakritagya/nepkit/blob/main/tests/test_oracle.py),
436
+ which checks conversions against a handful of BS↔AD dates attested by
437
+ sources with no connection to nepkit or to either source table. Both are a
438
+ sample, not a proof — the oracle pairs cover select decades, and nothing
439
+ past today can ever be externally attested, since the table's later years
440
+ (toward BS 2090) haven't happened yet.
349
441
 
350
442
  ## Data provenance
351
443
 
@@ -17,8 +17,11 @@ command-line tool.
17
17
  [![Python](https://img.shields.io/pypi/pyversions/nepkit)](https://pypi.org/project/nepkit/)
18
18
  [![License](https://img.shields.io/pypi/l/nepkit)](https://github.com/akakritagya/nepkit/blob/main/LICENSE)
19
19
 
20
- > **Status:** first release. The library and CLI both work and are tested; the
21
- > API may still change before 1.0.
20
+ > **Status:** published, pre-1.0. The library and CLI both work and are
21
+ > tested, but the API and the CLI's output shapes may still change before
22
+ > 1.0. Pin a version if you script against stdout, or use `--json` instead.
23
+ > See [STATUS.md](https://github.com/akakritagya/nepkit/blob/main/STATUS.md)
24
+ > for what's changed release to release.
22
25
 
23
26
  [**DEMO.md**](https://github.com/akakritagya/nepkit/blob/main/DEMO.md) walks
24
27
  through every command, option, and failure mode with real captured output.
@@ -93,10 +96,11 @@ works as written.
93
96
  ```python
94
97
  from datetime import date
95
98
 
96
- from nepkit import BSDate, ad_to_bs, bs_to_ad
99
+ from nepkit import BSDate, __version__, ad_to_bs, bs_to_ad
97
100
 
98
101
  bs_to_ad(BSDate(2081, 4, 15)) # date(2024, 7, 30)
99
102
  ad_to_bs(date(2024, 7, 30)) # BSDate(year=2081, month=4, day=15)
103
+ __version__ # "0.4.0"
100
104
  ```
101
105
 
102
106
  `BSDate` validates on construction, so if you are holding one it is a real date
@@ -116,6 +120,33 @@ BSDate(2095, 1, 1) # raises DateOutOfRangeError
116
120
  `ad_to_bs` takes a `datetime.date`, so a malformed Gregorian date is impossible
117
121
  by construction — Python's own constructor rejects it before nepkit is involved.
118
122
 
123
+ `BSDate` mirrors `datetime.date`'s string handling, and `parse_bs_date`/
124
+ `format_bs_date` (with Gregorian counterparts `parse_ad_date`/`format_ad_date`)
125
+ cover the human-readable forms the CLI accepts and prints — the CLI is a thin
126
+ layer over these, not a separate implementation:
127
+
128
+ ```python
129
+ from nepkit import BSDate, format_bs_date, parse_ad_date, parse_bs_date
130
+
131
+ bs = BSDate(2081, 4, 15)
132
+ str(bs) # "2081-04-15"
133
+ BSDate.fromisoformat("2081-04-15") # BSDate(year=2081, month=4, day=15)
134
+
135
+ # "D Month YYYY", the month matched case-insensitively against a common
136
+ # romanisation variant or Devnagari, not just BS_MONTH_NAMES's one spelling
137
+ parse_bs_date("15 Baishakh 2081") # BSDate(year=2081, month=1, day=15)
138
+
139
+ format_bs_date(bs, named=True) # "15 Shrawan 2081"
140
+ format_bs_date(bs, named=True, devnagari=True) # "१५ साउन २०८१"
141
+
142
+ parse_ad_date("30 Jul 2024") # date(2024, 7, 30)
143
+ ```
144
+
145
+ `BSDate.isoformat()`'s result is not an ISO 8601 date — `datetime.date.fromisoformat`
146
+ will accept it and silently return a different, wrong Gregorian day. It is
147
+ only ever meaningful alongside something that says it is Bikram Sambat, the
148
+ same way nepkit's CLI always prints a `BS`/`AD` label alongside it.
149
+
119
150
  ### Errors
120
151
 
121
152
  ```text
@@ -139,15 +170,18 @@ add` installs into the project's `.venv` without activating it, so reach the
139
170
  command with `uv run nepkit` — or activate the venv first.
140
171
 
141
172
  ```console
173
+ $ nepkit --version
174
+ nepkit 0.4.0
175
+
142
176
  $ nepkit bs2ad 2081-04-15
143
- 2024-07-30 Tue
177
+ AD 30 Jul 2024 (2024-07-30) Tue
144
178
 
145
- $ nepkit ad2bs 2024-07-30
146
- 2081-04-15 Tue
179
+ $ nepkit ad2bs "30 July 2024"
180
+ BS 15 Shrawan 2081 (2081-04-15) Tue
147
181
 
148
182
  $ nepkit today
149
- BS 2083-04-27 Wed
150
- AD 2026-08-12 Wed
183
+ BS २७ साउन २०८३ १४:३२ बुध
184
+ AD 12 Aug 2026 14:32 Wed
151
185
 
152
186
  $ nepkit range
153
187
  BS 2000-01-01 .. 2090-12-30 (years 2000-2090)
@@ -158,6 +192,19 @@ Direction is always explicit, and has to be: the BS and AD year numbers overlap
158
192
  from 2000 to 2034, so `2024` is a valid year in both calendars and nothing
159
193
  could reliably guess which one you meant.
160
194
 
195
+ `bs2ad`/`ad2bs` accept the date either as `YYYY-MM-DD` or as `"D Month YYYY"`
196
+ (e.g. `"1 Baisakh 2083"`, `"1 Jan 2000"` or `"1 January 2000"`) — the month
197
+ name matched case-insensitively either way, so `Shrawan`, `shrawan`, and
198
+ `SHRAWAN` all work. The BS side also accepts common romanisation variants
199
+ (`Baishakh` alongside `Baisakh`, `Sawan` alongside `Shrawan`, ...) and
200
+ Devnagari month names (`साउन`), not just the one spelling `BS_MONTH_NAMES`
201
+ prints — `calbs`'s month argument does the same.
202
+
203
+ `today` defaults to `--script devnagari`, so its BS line reads Devnagari
204
+ without any flag; pass `--script latin` for the romanised form instead. The
205
+ AD line is always Latin. `bs2ad`/`ad2bs`/`range` default to `latin` and need
206
+ `--script devnagari` explicitly.
207
+
161
208
  ### Interactive
162
209
 
163
210
  Run `nepkit` with no arguments in a terminal and it clears the screen and opens
@@ -171,17 +218,17 @@ $ nepkit
171
218
  | | | || __/ | |_) || < | || |_
172
219
  |_| |_| \___| | .__/ |_|\_\|_| \__|
173
220
  |_|
174
- nepkit v0.2.0 - Bikram Sambat (BS) <-> Gregorian (AD) date conversion
175
- Today BS 2083-04-27 AD 2026-08-12 Wed
221
+ nepkit v0.4.0 - Bikram Sambat (BS) <-> Gregorian (AD) date conversion
222
+ Today 14:32 NPT BS 27 Shrawan 2083 AD 12 Aug 2026 14:32 Wed
176
223
 
177
224
  Type a command, 'help', 'clear', or 'quit'. Up/Down recalls history.
178
225
 
179
226
  nepkit> today
180
- BS 2083-04-27 Wed
181
- AD 2026-08-12 Wed
227
+ BS २७ साउन २०८३ १४:३२ बुध
228
+ AD 12 Aug 2026 14:32 Wed
182
229
 
183
230
  nepkit> bs2ad 2081-04-15
184
- 2024-07-30 Tue
231
+ AD 30 Jul 2024 (2024-07-30) Tue
185
232
 
186
233
  nepkit> quit
187
234
  ```
@@ -230,13 +277,28 @@ Sun Mon Tue Wed Thu Fri Sat
230
277
  28 29 30 31
231
278
  ```
232
279
 
280
+ Shown here without a box: grids are boxed and coloured only on a real
281
+ terminal, and plain like this when redirected — piped, or captured for this
282
+ README — the same convention `ls` and `git` follow. See
283
+ [DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#colour) for
284
+ what it looks like on a terminal. Force it either way with
285
+ `--color always|never|auto`.
286
+
233
287
  Both default to the current month. A Gregorian month never lines up with a BS
234
288
  month, so the subtitle names both ends of the span rather than pretending a
235
289
  single corresponding month exists.
236
290
 
237
- Grids are boxed and coloured on a terminal and plain when redirected, following
238
- the same convention as `ls` and `git`. Force it either way with
239
- `--color always|never|auto`.
291
+ The month argument accepts a name too, case-insensitively — `calbs` matches
292
+ BS names (`Shrawan`/`shrawan`, a romanisation variant like `Sawan`, or a
293
+ Devnagari name like `साउन`), `calad` matches English names or 3-letter
294
+ abbreviations (`July`/`Jul`/`jul`) — alongside the numeric `1`-`12` form:
295
+
296
+ ```bash
297
+ nepkit calbs 2081 Shrawan
298
+ nepkit calad 2024 Jul
299
+ ```
300
+
301
+ Neither command takes `--script` — see [Limitations](#limitations) below.
240
302
 
241
303
  On a terminal, today's date is picked out in bold bright cyan — the bright form
242
304
  of the box's own border colour, so the highlight belongs to the grid containing
@@ -307,19 +369,47 @@ the standard library.
307
369
  `datetime.date` rather than three integers, which removes an entire error class
308
370
  from its contract at no cost.
309
371
 
372
+ **Human-text parsing and formatting are library code, not CLI code.** The CLI
373
+ used to own `parse_bs_date`/`format_bs_date` and friends as private helpers,
374
+ which meant a library caller could not parse `"1 Baisakh 2083"` into a
375
+ `BSDate`, or format one back into that form, at all -- only the CLI process
376
+ could. They moved into the library so the CLI is provably a thin layer over
377
+ it rather than a second implementation that has to be kept in sync by hand.
378
+
310
379
  ## Limitations
311
380
 
312
- - **Dates only.** No time of day, no timezones, no Nepali-language month names
313
- or numeral formatting.
381
+ - **Time of day works only in Nepal Standard Time (UTC+05:45).** `BSDateTime`
382
+ and `bs_datetime_to_ad_datetime`/`ad_datetime_to_bs_datetime` carry a
383
+ naive time-of-day through the date conversion; nepkit does not convert
384
+ between timezones. A tz-aware `datetime` is rejected outright rather than
385
+ silently treated as NPT — convert it yourself with `astimezone` first. In
386
+ the CLI, only `today` and the interactive banner show the time; there is
387
+ no `--time` flag on `bs2ad`/`ad2bs`.
388
+ - **Devnagari formatting stops at the calendar grid.** `--script devnagari`
389
+ covers `bs2ad`/`ad2bs`/`today`/`range` and the library
390
+ (`nepkit.BS_MONTH_NAMES_NE`, `nepkit.format_bs_date`/`nepkit.bs_month_name`'s
391
+ `devnagari` flag, and `nepkit.render`'s grid functions); `calbs` and `calad`
392
+ render Latin only. `today` defaults to `--script devnagari` (the
393
+ others default to `latin`), and its AD line is Latin regardless of
394
+ `--script` -- there is no Devnagari table for Gregorian month names, so the
395
+ option only ever touches its BS line. See
396
+ [DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#script).
314
397
  - **The range is hard-bounded** at BS 2000–2090 and will not extrapolate.
315
- - **Correctness rests on the data, and the tests cannot prove it.** The test
316
- suite verifies self-consistency exhaustively — every one of the 33,238 days
317
- round-trips, and consecutive day counts produce consecutive dates. But both
318
- directions read the same table, so a wrong month length cancels out exactly
319
- and every property still passes. This was verified by deliberately corrupting
320
- the table: all properties passed while conversions were silently wrong. Only
321
- the sourcing described in [`src/nepkit/data/DATA.md`](https://github.com/akakritagya/nepkit/blob/main/src/nepkit/data/DATA.md)
322
- stands behind the numbers themselves.
398
+ - **Correctness rests on the data, and round-trip tests alone cannot prove
399
+ it.** The property suite verifies self-consistency exhaustively — every one
400
+ of the 33,238 days round-trips, and consecutive day counts produce
401
+ consecutive dates. But both directions read the same table, so a wrong
402
+ month length cancels out exactly and every property still passes. This was
403
+ verified by deliberately corrupting the table: all properties passed while
404
+ conversions were silently wrong. Two things stand behind the numbers
405
+ themselves instead: the independent sourcing in
406
+ [`src/nepkit/data/DATA.md`](https://github.com/akakritagya/nepkit/blob/main/src/nepkit/data/DATA.md),
407
+ and [`tests/test_oracle.py`](https://github.com/akakritagya/nepkit/blob/main/tests/test_oracle.py),
408
+ which checks conversions against a handful of BS↔AD dates attested by
409
+ sources with no connection to nepkit or to either source table. Both are a
410
+ sample, not a proof — the oracle pairs cover select decades, and nothing
411
+ past today can ever be externally attested, since the table's later years
412
+ (toward BS 2090) haven't happened yet.
323
413
 
324
414
  ## Data provenance
325
415
 
@@ -13,7 +13,9 @@ classifiers = [
13
13
  ]
14
14
  dependencies = [
15
15
  "typer>=0.15,<0.28",
16
+ "rich>=13,<16",
16
17
  "pyreadline3>=3.5; sys_platform == 'win32'",
18
+ "tzdata>=2024.1; sys_platform == 'win32'",
17
19
  ]
18
20
  description = "Typed Bikram Sambat ↔ Gregorian date conversion, as a library and a CLI."
19
21
  keywords = [
@@ -28,7 +30,7 @@ license-files = ["LICENSE"]
28
30
  name = "nepkit"
29
31
  readme = "README.md"
30
32
  requires-python = ">=3.12"
31
- version = "0.2.0"
33
+ version = "0.4.0"
32
34
 
33
35
  [[project.authors]]
34
36
  name = "Kritagya"
@@ -57,9 +59,12 @@ requires = ["uv_build>=0.12.1,<0.13.0"]
57
59
  [tool.ruff]
58
60
  indent-width = 4
59
61
  line-length = 100
62
+ required-version = ">=0.16,<0.17"
63
+ show-fixes = true
60
64
  target-version = "py312"
61
65
 
62
66
  [tool.ruff.lint]
67
+ dummy-variable-rgx = "^_.*$"
63
68
  select = [
64
69
  "E",
65
70
  "F",
@@ -69,22 +74,60 @@ select = [
69
74
  "SIM",
70
75
  "ANN",
71
76
  "RUF",
77
+ "D",
78
+ "S",
79
+ "PTH",
80
+ "C901",
81
+ "PLR0913",
72
82
  ]
83
+ unfixable = [
84
+ "F401",
85
+ "F841",
86
+ ]
87
+
88
+ [tool.ruff.lint.isort]
89
+ known-first-party = ["nepkit"]
90
+
91
+ [tool.ruff.lint.mccabe]
92
+ max-complexity = 10
93
+
94
+ [tool.ruff.lint.pylint]
95
+ max-args = 7
96
+
97
+ [tool.ruff.lint.pydocstyle]
98
+ convention = "numpy"
99
+
100
+ [tool.ruff.lint.per-file-ignores]
101
+ "tests/**/*.py" = [
102
+ "D",
103
+ "S101",
104
+ ]
105
+ "scripts/*.py" = ["S310"]
73
106
 
74
107
  [tool.ruff.format]
75
108
  docstring-code-format = true
76
109
  line-ending = "lf"
77
110
 
78
111
  [tool.pytest.ini_options]
79
- addopts = "-q --strict-markers --strict-config"
112
+ addopts = [
113
+ "-q",
114
+ "--strict-markers",
115
+ "--strict-config",
116
+ "--import-mode=importlib",
117
+ "--cov=nepkit",
118
+ "--cov-report=term-missing",
119
+ ]
80
120
  testpaths = ["tests"]
121
+ pythonpath = ["scripts"]
122
+ xfail_strict = true
123
+ filterwarnings = ["error"]
81
124
 
82
125
  [tool.coverage.run]
83
126
  branch = true
84
127
  source = ["nepkit"]
85
128
 
86
129
  [tool.coverage.report]
87
- exclude_lines = [
130
+ exclude_also = [
88
131
  "if TYPE_CHECKING:",
89
132
  "raise NotImplementedError",
90
133
  ]
@@ -94,7 +137,10 @@ show_missing = true
94
137
  files = [
95
138
  "src",
96
139
  "tests",
140
+ "scripts",
97
141
  ]
98
142
  python_executable = ".venv/bin/python"
99
143
  python_version = "3.12"
100
144
  strict = true
145
+ warn_unreachable = true
146
+ pretty = true