Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
- name: Tox tests
run: |
tox -v

ruff:
runs-on: ubuntu-latest
name: ruff
Expand All @@ -45,8 +46,25 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install ruff

- name: Run ruff check
run: |
ruff check
ruff format --check
ruff format --check

pyright:
runs-on: ubuntu-latest
name: pyright
steps:
- uses: actions/checkout@v7
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: "3" # latest Python 3.x
architecture: x64
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pyright
pip install -e .
- name: Run pyright
run: pyright
8 changes: 4 additions & 4 deletions jdatetime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from typing import ClassVar as _ClassVar, overload as _overload

try:
from greenlet import getcurrent as get_ident
from greenlet import getcurrent as get_ident # type: ignore
except ImportError:
from _thread import get_ident

Expand Down Expand Up @@ -354,8 +354,8 @@ def fromtimestamp(timestamp) -> date:
(y, m, d) = GregorianToJalali(d.year, d.month, d.day).getJalaliList()
return date(y, m, d)

@staticmethod
def fromisoformat(date_string: str) -> date:
@classmethod
def fromisoformat(cls, date_string: str) -> date:
"""
Convert an ISO 8601 formatted string to a jdatetime.date
"""
Expand Down Expand Up @@ -943,7 +943,7 @@ def replace(
minute: int | None = None,
second: int | None = None,
microsecond: int | None = None,
tzinfo: py_datetime.tzinfo | None = True,
tzinfo: py_datetime.tzinfo | None | typing.Literal[True] = True,
fold: int | None = None,
) -> datetime:
"""Return datetime with new specified fields."""
Expand Down
24 changes: 12 additions & 12 deletions tests/test_jdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ def test_init_locale_is_effective_only_if_not_empty(self):
def test_locale_property_is_read_only(self):
date = jdatetime.date(1397, 4, 22)
with self.assertRaises(AttributeError):
date.locale = jdatetime.FA_LOCALE
date.locale = jdatetime.FA_LOCALE # type: ignore

def test_locale_property_returns_locale(self):
date = jdatetime.date(1397, 4, 22, locale='nl_NL')
self.assertEqual(date.locale, 'nl_NL')

def test_init_locale_is_named_argument_only(self):
with self.assertRaises(TypeError):
datetime.date(1397, 4, 22, 'nl_NL')
datetime.date(1397, 4, 22, 'nl_NL') # type: ignore

def test_init_accepts_instance_locale(self):
date = jdatetime.date(1397, 4, 23, locale=jdatetime.FA_LOCALE)
Expand Down Expand Up @@ -93,23 +93,23 @@ def test_unknown_type_operations(self):
date = jdatetime.date(1402, 1, 9)
unknown_type = object()
assert (
date.__sub__(unknown_type)
is date.__rsub__(unknown_type)
is date.__add__(unknown_type)
is date.__radd__(unknown_type)
date.__sub__(unknown_type) # type: ignore
is date.__rsub__(unknown_type) # type: ignore
is date.__add__(unknown_type) # type: ignore
is date.__radd__(unknown_type) # type: ignore
is date.__eq__(unknown_type)
is date.__ne__(unknown_type)
is date.__lt__(unknown_type)
is date.__le__(unknown_type)
is date.__gt__(unknown_type)
is date.__ge__(unknown_type)
is date.__lt__(unknown_type) # type: ignore
is date.__le__(unknown_type) # type: ignore
is date.__gt__(unknown_type) # type: ignore
is date.__ge__(unknown_type) # type: ignore
is NotImplemented
)
with self.assertRaisesRegex(
TypeError,
r"unsupported operand type\(s\) for \+=: 'date' and 'object'",
):
date += unknown_type
date += unknown_type # type: ignore

def test_reverse_add_time_delta(self):
date = jdatetime.date(1397, 4, 22, locale='nl_NL')
Expand Down Expand Up @@ -183,7 +183,7 @@ def test_fromisoformat(self):
jdatetime.date.fromisoformat('some-invalid-format')

with self.assertRaises(TypeError, msg='fromisoformat: argument must be str'):
jdatetime.date.fromisoformat(1)
jdatetime.date.fromisoformat(1) # type: ignore

def test_resolution(self):
assert jdatetime.date.resolution == jdatetime.timedelta(days=1)
68 changes: 33 additions & 35 deletions tests/test_jdatetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@
import sys
import threading
import time
from typing import Any
from unittest import TestCase, skipIf, skipUnless
from zoneinfo import ZoneInfo

import jdatetime

try:
import greenlet

greenlet_installed = True
import greenlet # type: ignore
except ImportError:
greenlet_installed = False
greenlet: Any = None

from tests import load_pickle

Expand Down Expand Up @@ -65,7 +64,7 @@ def test_init_locale_is_effective_only_if_not_empty(self):
def test_locale_property_is_read_only(self):
datetime = jdatetime.datetime(1397, 4, 22)
with self.assertRaises(AttributeError):
datetime.locale = jdatetime.FA_LOCALE
datetime.locale = jdatetime.FA_LOCALE # type: ignore

def test_fold(self):
# Test default value
Expand Down Expand Up @@ -101,7 +100,7 @@ def test_locale_property_returns_locale(self):

def test_init_locale_is_named_argument_only(self):
with self.assertRaises(TypeError):
datetime.datetime(1397, 4, 22, 'nl_NL')
datetime.datetime(1397, 4, 22, 'nl_NL') # type: ignore

def test_init_accepts_instance_locale(self):
datetime = jdatetime.datetime(1397, 4, 23, locale=jdatetime.FA_LOCALE)
Expand Down Expand Up @@ -295,7 +294,7 @@ def test_combine_keeps_date_locale(self):

def test_replace(self):
dt = jdatetime.datetime.today()
args = {
args: dict = {
'year': 1390,
'month': 12,
'day': 1,
Expand All @@ -311,7 +310,7 @@ def test_replace(self):

def test_replace_keeps_date_locale(self):
dt = jdatetime.datetime(1397, 4, 24, locale='nl_NL')
args = {'year': 1390, 'month': 12, 'hour': 13}
args: dict = {'year': 1390, 'month': 12, 'hour': 13}
self.assertEqual(dt.replace(**args).locale, 'nl_NL')

def test_astimezone_keeps_locale(self):
Expand Down Expand Up @@ -524,16 +523,16 @@ def test_datetime_raise_exception_on_invalid_calculation(self):
date_1395 = jdatetime.datetime(1395, 1, 1)

with self.assertRaises(TypeError):
date_1395 - 1
date_1395 - 1 # type: ignore

with self.assertRaises(TypeError):
date_1395 + 1
date_1395 + 1 # type: ignore

with self.assertRaises(TypeError):
jdatetime.timedelta(days=1) - date_1395
jdatetime.timedelta(days=1) - date_1395 # type: ignore

with self.assertRaises(TypeError):
date_1395 + date_1395
date_1395 + date_1395 # type: ignore

def test_datetime_calculation_on_timedelta(self):
date_1395 = jdatetime.datetime(1395, 1, 1)
Expand Down Expand Up @@ -564,16 +563,16 @@ def test_date_raise_exception_on_invalid_calculation(self):
date_1395 = jdatetime.date(1395, 1, 1)

with self.assertRaises(TypeError):
date_1395 - 1
date_1395 - 1 # type: ignore

with self.assertRaises(TypeError):
date_1395 + 1
date_1395 + 1 # type: ignore

with self.assertRaises(TypeError):
jdatetime.timedelta(days=1) - date_1395
jdatetime.timedelta(days=1) - date_1395 # type: ignore

with self.assertRaises(TypeError):
date_1395 + date_1395
date_1395 + date_1395 # type: ignore

def test_date_calculation_on_timedelta(self):
date_1395 = jdatetime.date(1395, 1, 1)
Expand Down Expand Up @@ -646,11 +645,10 @@ def test_datetime_to_str(self):

def test_with_pytz(self):
try:
import pytz
from pytz import timezone
from pytz import timezone # type: ignore
except ImportError:
pytz = None
if pytz:
timezone = None
if timezone is not None:
tehran = timezone('Asia/Tehran')
date = jdatetime.datetime(1394, 1, 1, 0, 0, 0, tzinfo=tehran)
self.assertEqual(str(date), '1394-01-01 00:00:00+0326')
Expand Down Expand Up @@ -697,13 +695,13 @@ def test_isoformat_default_args(self):
jdt = jdatetime.datetime(1398, 4, 11)
jiso = jdt.isoformat()

self.assertAlmostEqual(jiso, '1398-04-11T00:00:00')
self.assertEqual(jiso, '1398-04-11T00:00:00')

def test_isoformat_custom_sep(self):
jdt = jdatetime.datetime(1398, 4, 11)
jiso = jdt.isoformat('M')

self.assertAlmostEqual(jiso, '1398-04-11M00:00:00')
self.assertEqual(jiso, '1398-04-11M00:00:00')

def test_isoformat_unicode_arg_python2(self):
jdt = jdatetime.datetime(1398, 4, 11)
Expand Down Expand Up @@ -955,7 +953,7 @@ def record_thread_locale(record, event, locale):
def test_get_locale_returns_none_if_no_locale_set_yet(self):
self.assertIsNone(jdatetime.get_locale())

@skipIf(greenlet_installed, 'thread ident is used when greenlet is not installed')
@skipIf(greenlet, 'thread ident is used when greenlet is not installed')
def test_set_locale_is_per_thread_with_no_effect_on_other_threads(self):
event = threading.Event()
fa_record = []
Expand All @@ -975,7 +973,7 @@ def test_set_locale_is_per_thread_with_no_effect_on_other_threads(self):
self.assertEqual('nl_NL', nl_record[0])
self.assertIsNone(jdatetime.get_locale()) # MainThread is not affected neither

@skipUnless(greenlet_installed, 'greenelts ident is used when greenlet module is installed')
@skipUnless(greenlet, 'greenelts ident is used when greenlet module is installed')
def test_set_locale_is_per_greenlet_with_no_effect_on_other_greenlets(self):
fa_record = []

Expand All @@ -1002,7 +1000,7 @@ def record_greenlet_locale_nl():
self.assertEqual(1, len(nl_record))
self.assertEqual('nl_NL', nl_record[0])

@skipIf(greenlet_installed, 'thread ident is used when greenlet is not installed')
@skipIf(greenlet, 'thread ident is used when greenlet is not installed')
def test_set_locale_sets_default_locale_for_date_objects(self):
def record_locale_formatted_date(record, locale):
jdatetime.set_locale(locale)
Expand All @@ -1017,7 +1015,7 @@ def record_locale_formatted_date(record, locale):

self.assertEqual(['یک‌شنبه', 'خرداد'], fa_record)

@skipUnless(greenlet_installed, 'greenlets ident is used when greenlet module is installed')
@skipUnless(greenlet, 'greenlets ident is used when greenlet module is installed')
def test_set_locale_sets_default_locale_for_date_objects_with_greenlets(self):
def record_locale_formatted_date(record, locale):
jdatetime.set_locale(locale)
Expand Down Expand Up @@ -1076,23 +1074,23 @@ def test_unknown_type_operations(self):
dt = jdatetime.datetime(1402, 1, 9)
unknown_type = object()
self.assertTrue(
dt.__sub__(unknown_type)
is dt.__rsub__(unknown_type)
is dt.__add__(unknown_type)
is dt.__radd__(unknown_type)
dt.__sub__(unknown_type) # type: ignore
is dt.__rsub__(unknown_type) # type: ignore
is dt.__add__(unknown_type) # type: ignore
is dt.__radd__(unknown_type) # type: ignore
is dt.__eq__(unknown_type)
is dt.__ne__(unknown_type)
is dt.__lt__(unknown_type)
is dt.__le__(unknown_type)
is dt.__gt__(unknown_type)
is dt.__ge__(unknown_type)
is dt.__lt__(unknown_type) # type: ignore
is dt.__le__(unknown_type) # type: ignore
is dt.__gt__(unknown_type) # type: ignore
is dt.__ge__(unknown_type) # type: ignore
is NotImplemented
)
with self.assertRaisesRegex(
TypeError,
r"unsupported operand type\(s\) for \-=: 'datetime' and 'object'",
):
dt -= unknown_type
dt -= unknown_type # type: ignore

def test_resolution(self):
assert jdatetime.datetime.resolution == jdatetime.timedelta(microseconds=1)
Expand Down