D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
cloudlinux
/
venv
/
lib
/
python3.11
/
site-packages
/
testfixtures
/
Filename :
datetime.py
back
Copy
from calendar import timegm from datetime import datetime, timedelta, date, tzinfo as TZInfo from typing import Optional, Callable, Type, Tuple, Dict, Any, cast, overload class Queue(list): delta: float delta_delta: float delta_type: str def __init__(self, delta: Optional[float], delta_delta: float, delta_type: str): super().__init__() if delta is None: self.delta = 0 self.delta_delta = delta_delta else: self.delta = delta self.delta_delta = 0 self.delta_type = delta_type def advance_next(self, delta: timedelta) -> None: self[-1] += delta def next(self) -> 'MockedCurrent': instance = self.pop(0) if not self: self.delta += self.delta_delta n = instance + timedelta(**{self.delta_type: self.delta}) self.append(n) return instance class MockedCurrent: _mock_queue: Queue _mock_base_class: Type _mock_class: Type _mock_tzinfo: Optional[TZInfo] _mock_date_type: Type[date] _correct_mock_type: Callable = None def __init_subclass__( cls, concrete: bool = False, queue: Queue = None, strict: bool = None, tzinfo: TZInfo = None, date_type: Type[date] = None ): if concrete: cls._mock_queue = queue cls._mock_base_class = cls.__bases__[0].__bases__[1] cls._mock_class = cls if strict else cls._mock_base_class cls._mock_tzinfo = tzinfo cls._mock_date_type = date_type @classmethod def add(cls, *args, **kw): if 'tzinfo' in kw or len(args) > 7: raise TypeError('Cannot add using tzinfo on %s' % cls.__name__) if args and isinstance(args[0], cls._mock_base_class): instance = args[0] instance_tzinfo = getattr(instance, 'tzinfo', None) if instance_tzinfo: if instance_tzinfo != cls._mock_tzinfo: raise ValueError( 'Cannot add %s with tzinfo of %s as configured to use %s' % ( instance.__class__.__name__, instance_tzinfo, cls._mock_tzinfo )) instance = instance.replace(tzinfo=None) if cls._correct_mock_type: instance = cls._correct_mock_type(instance) else: instance = cls(*args, **kw) cls._mock_queue.append(instance) @classmethod def set(cls, *args, **kw) -> None: cls._mock_queue.clear() cls.add(*args, **kw) @classmethod def tick(cls, *args, **kw) -> None: if kw: delta = timedelta(**kw) else: delta, = args cls._mock_queue.advance_next(delta) def __add__(self, other) -> 'MockedCurrent': instance = super().__add__(other) if self._correct_mock_type: instance = self._correct_mock_type(instance) return instance def __new__(cls, *args, **kw): if cls is cls._mock_class: return super().__new__(cls, *args, **kw) else: return cls._mock_class(*args, **kw) def mock_factory( type_name: str, mock_class: Type[MockedCurrent], default: Tuple[int, ...], args: tuple, kw: Dict[str, Any], delta: Optional[float], delta_type: str, delta_delta: float = 1, date_type: Type[date] = None, tzinfo: TZInfo = None, strict: bool = False ): cls = cast(Type[MockedCurrent], type( type_name, (mock_class,), {}, concrete=True, queue=Queue(delta, delta_delta, delta_type), strict=strict, tzinfo=tzinfo, date_type=date_type, )) if args != (None,): if not (args or kw): args = default cls.add(*args, **kw) return cls class MockDateTime(MockedCurrent, datetime): @overload @classmethod def add( cls, year: int, month: int, day: int, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: TZInfo = ..., ) -> None: ... @overload @classmethod def add( cls, instance: datetime, ) -> None: ... @classmethod def add(cls, *args, **kw): """ This will add the :class:`datetime.datetime` created from the supplied parameters to the queue of datetimes to be returned by :meth:`~MockDateTime.now` or :meth:`~MockDateTime.utcnow`. An instance of :class:`~datetime.datetime` may also be passed as a single positional argument. """ return super().add(*args, **kw) @overload @classmethod def set( cls, year: int, month: int, day: int, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: TZInfo = ..., ) -> None: ... @overload @classmethod def set( cls, instance: datetime, ) -> None: ... @classmethod def set(cls, *args, **kw): """ This will set the :class:`datetime.datetime` created from the supplied parameters as the next datetime to be returned by :meth:`~MockDateTime.now` or :meth:`~MockDateTime.utcnow`, clearing out any datetimes in the queue. An instance of :class:`~datetime.datetime` may also be passed as a single positional argument. """ return super().set(*args, **kw) @overload @classmethod def tick( cls, days: float = ..., seconds: float = ..., microseconds: float = ..., milliseconds: float = ..., minutes: float = ..., hours: float = ..., weeks: float = ..., ) -> None: ... @overload @classmethod def tick( cls, delta: timedelta, # can become positional-only when Python 3.8 minimum ) -> None: ... @classmethod def tick(cls, *args, **kw) -> None: """ This method should be called either with a :class:`~datetime.timedelta` as a positional argument, or with keyword parameters that will be used to construct a :class:`~datetime.timedelta`. The :class:`~datetime.timedelta` will be used to advance the next datetime to be returned by :meth:`~MockDateTime.now` or :meth:`~MockDateTime.utcnow`. """ return super().tick(*args, **kw) @classmethod def _correct_mock_type(cls, instance): return cls._mock_class( instance.year, instance.month, instance.day, instance.hour, instance.minute, instance.second, instance.microsecond, instance.tzinfo, ) @classmethod def now(cls, tz: TZInfo = None) -> datetime: """ :param tz: An optional timezone to apply to the returned time. If supplied, it must be an instance of a :class:`~datetime.tzinfo` subclass. This will return the next supplied or calculated datetime from the internal queue, rather than the actual current datetime. If `tz` is supplied, see :ref:`timezones`. """ instance = cast(datetime, cls._mock_queue.next()) if tz is not None: if cls._mock_tzinfo: instance = instance - cls._mock_tzinfo.utcoffset(instance) instance = tz.fromutc(instance.replace(tzinfo=tz)) return cls._correct_mock_type(instance) @classmethod def utcnow(cls) -> datetime: """ This will return the next supplied or calculated datetime from the internal queue, rather than the actual current UTC datetime. If you care about timezones, see :ref:`timezones`. """ instance = cast(datetime, cls._mock_queue.next()) if cls._mock_tzinfo is not None: instance = instance - cls._mock_tzinfo.utcoffset(instance) return instance def date(self) -> date: """ This will return the date component of the current mock instance, but using the date type supplied when the mock class was created. """ return self._mock_date_type( self.year, self.month, self.day ) @overload def mock_datetime( tzinfo: TZInfo = None, delta: float = None, delta_type: str = 'seconds', date_type: Type[date] = date, strict: bool = False ) -> Type[MockDateTime]: ... @overload def mock_datetime( year: int, month: int, day: int, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: TZInfo = None, delta: float = None, delta_type: str = 'seconds', date_type: Type[date] = date, strict: bool = False ) -> Type[MockDateTime]: ... @overload def mock_datetime( default: datetime, tzinfo: TZInfo = None, delta: float = None, delta_type: str = 'seconds', date_type: Type[date] = date, strict: bool = False ) -> Type[MockDateTime]: ... @overload def mock_datetime( default: None, # explicit None positional tzinfo: TZInfo = None, delta: float = None, delta_type: str = 'seconds', date_type: Type[date] = date, strict: bool = False ) -> Type[MockDateTime]: ... def mock_datetime( *args, tzinfo: TZInfo = None, delta: float = None, delta_type: str = 'seconds', date_type: Type[date] = date, strict: bool = False, **kw, ) -> Type[MockDateTime]: """ .. currentmodule:: testfixtures.datetime A function that returns a mock object that can be used in place of the :class:`datetime.datetime` class but where the return value of :meth:`~MockDateTime.now` can be controlled. If a single positional argument of ``None`` is passed, then the queue of datetimes to be returned will be empty and you will need to call :meth:`~MockDateTime.set` or :meth:`~MockDateTime.add` before calling :meth:`~MockDateTime.now` or :meth:`~MockDateTime.utcnow`. If an instance of :class:`~datetime.datetime` is passed as a single positional argument, that will be used as the first date returned by :meth:`~MockDateTime.now` :param year: An optional year used to create the first datetime returned by :meth:`~MockDateTime.now`. :param month: An optional month used to create the first datetime returned by :meth:`~MockDateTime.now`. :param day: An optional day used to create the first datetime returned by :meth:`~MockDateTime.now`. :param hour: An optional hour used to create the first datetime returned by :meth:`~MockDateTime.now`. :param minute: An optional minute used to create the first datetime returned by :meth:`~MockDateTime.now`. :param second: An optional second used to create the first datetime returned by :meth:`~MockDateTime.now`. :param microsecond: An optional microsecond used to create the first datetime returned by :meth:`~MockDateTime.now`. :param tzinfo: An optional :class:`datetime.tzinfo`, see :ref:`timezones`. :param delta: The size of the delta to use between values returned from mocked class methods. If not specified, it will increase by 1 with each call to :meth:`~MockDateTime.now`. :param delta_type: The type of the delta to use between values returned from mocked class methods. This can be any keyword parameter accepted by the :class:`~datetime.timedelta` constructor. :param date_type: The type to use for the return value of the mocked class methods. This can help with gotchas that occur when type checking is performed on values returned by the :meth:`~testfixtures.datetime.MockDateTime.date` method. :param strict: If ``True``, calling the mock class and any of its methods will result in an instance of the mock being returned. If ``False``, the default, an instance of :class:`~datetime.datetime` will be returned instead. The mock returned will behave exactly as the :class:`datetime.datetime` class as well as being a subclass of :class:`~testfixtures.datetime.MockDateTime`. """ if len(args) > 7: tzinfo = args[7] args = args[:7] else: tzinfo = tzinfo or (getattr(args[0], 'tzinfo', None) if args else None) return cast(Type[MockDateTime], mock_factory( 'MockDateTime', MockDateTime, (2001, 1, 1, 0, 0, 0), args, kw, tzinfo=tzinfo, delta=delta, delta_delta=10, delta_type=delta_type, date_type=date_type, strict=strict, )) class MockDate(MockedCurrent, date): @classmethod def _correct_mock_type(cls, instance): return cls._mock_class( instance.year, instance.month, instance.day, ) @overload @classmethod def add( cls, year: int, month: int, day: int, ) -> None: ... @overload @classmethod def add( cls, instance: date, ) -> None: ... @classmethod def add(cls, *args, **kw): """ This will add the :class:`datetime.date` created from the supplied parameters to the queue of dates to be returned by :meth:`~MockDate.today`. An instance of :class:`~datetime.date` may also be passed as a single positional argument. """ return super().add(*args, **kw) @overload @classmethod def set( cls, year: int, month: int, day: int, ) -> None: ... @overload @classmethod def set( cls, instance: date, ) -> None: ... @classmethod def set(cls, *args, **kw) -> None: """ This will set the :class:`datetime.date` created from the supplied parameters as the next date to be returned by :meth:`~MockDate.today`, regardless of any dates in the queue. An instance of :class:`~datetime.date` may also be passed as a single positional argument. """ return super().set(*args, **kw) @overload @classmethod def tick( cls, days: float = ..., weeks: float = ..., ) -> None: ... @overload @classmethod def tick( cls, delta: timedelta, # can become positional-only when Python 3.8 minimum ) -> None: ... @classmethod def tick(cls, *args, **kw) -> None: """ This method should be called either with a :class:`~datetime.timedelta` as a positional argument, or with keyword parameters that will be used to construct a :class:`~datetime.timedelta`. The :class:`~datetime.timedelta` will be used to advance the next date to be returned by :meth:`~MockDate.today`. """ return super().tick(*args, **kw) @classmethod def today(cls) -> date: """ This will return the next supplied or calculated date from the internal queue, rather than the actual current date. """ return cast(date, cls._mock_queue.next()) @overload def mock_date( delta: float = None, delta_type: str = None, date_type: Type[date] = date, strict: bool = False ) -> Type[MockDate]: ... @overload def mock_date( year: int, month: int, day: int, delta: float = None, delta_type: str = 'days', strict: bool = False, ) -> Type[MockDate]: ... @overload def mock_date( default: date, delta: float = None, delta_type: str = 'days', strict: bool = False, ) -> Type[MockDate]: ... @overload def mock_date( default: None, # explicit None positional delta: float = None, delta_type: str = 'days', strict: bool = False, ) -> Type[MockDate]: ... def mock_date( *args, delta: float = None, delta_type: str = 'days', strict: bool = False, **kw ) -> Type[MockDate]: """ .. currentmodule:: testfixtures.datetime A function that returns a mock object that can be used in place of the :class:`datetime.date` class but where the return value of :meth:`~datetime.date.today` can be controlled. If a single positional argument of ``None`` is passed, then the queue of dates to be returned will be empty and you will need to call :meth:`~MockDate.set` or :meth:`~MockDate.add` before calling :meth:`~MockDate.today`. If an instance of :class:`~datetime.date` is passed as a single positional argument, that will be used as the first date returned by :meth:`~datetime.date.today` :param year: An optional year used to create the first date returned by :meth:`~datetime.date.today`. :param month: An optional month used to create the first date returned by :meth:`~datetime.date.today`. :param day: An optional day used to create the first date returned by :meth:`~datetime.date.today`. :param delta: The size of the delta to use between values returned from :meth:`~datetime.date.today`. If not specified, it will increase by 1 with each call to :meth:`~datetime.date.today`. :param delta_type: The type of the delta to use between values returned from :meth:`~datetime.date.today`. This can be any keyword parameter accepted by the :class:`~datetime.timedelta` constructor. :param strict: If ``True``, calling the mock class and any of its methods will result in an instance of the mock being returned. If ``False``, the default, an instance of :class:`~datetime.date` will be returned instead. The mock returned will behave exactly as the :class:`datetime.date` class as well as being a subclass of :class:`~testfixtures.datetime.MockDate`. """ return cast(Type[MockDate], mock_factory( 'MockDate', MockDate, (2001, 1, 1), args, kw, delta=delta, delta_type=delta_type, strict=strict, )) ms = 10**6 class MockTime(MockedCurrent, datetime): @overload @classmethod def add( cls, year: int, month: int, day: int, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., ) -> None: ... @overload @classmethod def add( cls, instance: datetime, ) -> None: ... @classmethod def add(cls, *args, **kw): """ This will add the time specified by the supplied parameters to the queue of times to be returned by calls to the mock. The parameters are the same as the :class:`datetime.datetime` constructor. An instance of :class:`~datetime.datetime` may also be passed as a single positional argument. """ return super().add(*args, **kw) @overload @classmethod def set( cls, year: int, month: int, day: int, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., ) -> None: ... @overload @classmethod def set( cls, instance: datetime, ) -> None: ... @classmethod def set(cls, *args, **kw): """ This will set the time specified by the supplied parameters as the next time to be returned by a call to the mock, regardless of any times in the queue. The parameters are the same as the :class:`datetime.datetime` constructor. An instance of :class:`~datetime.datetime` may also be passed as a single positional argument. """ return super().set(*args, **kw) @overload @classmethod def tick( cls, days: float = ..., seconds: float = ..., microseconds: float = ..., milliseconds: float = ..., minutes: float = ..., hours: float = ..., weeks: float = ..., ) -> None: ... @overload @classmethod def tick( cls, delta: timedelta, # can become positional-only when Python 3.8 minimum ) -> None: ... @classmethod def tick(cls, *args, **kw): """ This method should be called either with a :class:`~datetime.timedelta` as a positional argument, or with keyword parameters that will be used to construct a :class:`~datetime.timedelta`. The :class:`~datetime.timedelta` will be used to advance the next time to be returned by a call to the mock. """ return super().tick(*args, **kw) def __new__(cls, *args, **kw) -> float: """ Return a :class:`float` representing the mocked current time as would normally be returned by :func:`time.time`. """ if args or kw: # Used when adding stuff to the queue return super().__new__(cls, *args, **kw) else: instance = cast(datetime, cls._mock_queue.next()) time = timegm(instance.utctimetuple()) time += (float(instance.microsecond)/ms) return time @overload def mock_time( delta: float = None, delta_type: str = 'seconds', ) -> Type[MockDateTime]: ... @overload def mock_time( year: int, month: int, day: int, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., delta: float = None, delta_type: str = 'seconds', ) -> Type[MockDateTime]: ... @overload def mock_time( default: datetime, delta: float = None, delta_type: str = 'seconds', ) -> Type[MockDateTime]: ... @overload def mock_time( default: None, # explicit None positional delta: float = None, delta_type: str = 'seconds', ) -> Type[MockDateTime]: ... def mock_time(*args, delta: float = None, delta_type: str = 'seconds', **kw) -> Type[MockTime]: """ .. currentmodule:: testfixtures.datetime A function that returns a :class:`mock object <testfixtures.datetime.MockTime>` that can be used in place of the :func:`time.time` function but where the return value can be controlled. If a single positional argument of ``None`` is passed, then the queue of times to be returned will be empty and you will need to call :meth:`~MockTime.set` or :meth:`~MockTime.add` before calling the mock. If an instance of :class:`~datetime.datetime` is passed as a single positional argument, that will be used to create the first time returned. :param year: An optional year used to create the first time returned. :param month: An optional month used to create the first time. :param day: An optional day used to create the first time. :param hour: An optional hour used to create the first time. :param minute: An optional minute used to create the first time. :param second: An optional second used to create the first time. :param microsecond: An optional microsecond used to create the first time. :param delta: The size of the delta to use between values returned. If not specified, it will increase by 1 with each call to the mock. :param delta_type: The type of the delta to use between values returned. This can be any keyword parameter accepted by the :class:`~datetime.timedelta` constructor. The :meth:`~testfixtures.datetime.MockTime.add`, :meth:`~testfixtures.datetime.MockTime.set` and :meth:`~testfixtures.datetime.MockTime.tick` methods on the mock can be used to control the return values. """ if 'tzinfo' in kw or len(args) > 7 or (args and getattr(args[0], 'tzinfo', None)): raise TypeError("You don't want to use tzinfo with test_time") return cast(Type[MockTime], mock_factory( 'MockTime', MockTime, (2001, 1, 1, 0, 0, 0), args, kw, delta=delta, delta_type=delta_type, ))