@@ -18,10 +18,10 @@ def __init__(self, datetime_class: type[DateTime] = DateTime) -> None:
1818 self ._datetime_class : type [DateTime ] = datetime_class
1919
2020 def freeze (self ) -> Self :
21- raise NotImplementedError ()
21+ raise self . _not_implemented ()
2222
2323 def travel_back (self ) -> Self :
24- raise NotImplementedError ()
24+ raise self . _not_implemented ()
2525
2626 def travel (
2727 self ,
@@ -34,10 +34,10 @@ def travel(
3434 seconds : int = 0 ,
3535 microseconds : int = 0 ,
3636 ) -> Self :
37- raise NotImplementedError ()
37+ raise self . _not_implemented ()
3838
3939 def travel_to (self , dt : DateTime , * , freeze : bool = False ) -> Self :
40- raise NotImplementedError ()
40+ raise self . _not_implemented ()
4141
4242 def __enter__ (self ) -> Self :
4343 return self
@@ -50,103 +50,123 @@ def __exit__(
5050 ) -> None :
5151 ...
5252
53+ def _not_implemented (self ) -> NotImplementedError :
54+ return NotImplementedError ()
55+
5356
5457if not PYPY :
55- import time_machine
58+ try :
59+ import time_machine
60+ except ImportError :
61+ time_machine = None # type: ignore[assignment]
5662
57- class Traveller (BaseTraveller ):
58- def __init__ (self , datetime_class : type [DateTime ] = DateTime ) -> None :
59- super ().__init__ (datetime_class )
63+ if time_machine is not None :
6064
61- self . _started : bool = False
62- self . _traveller : time_machine . travel | None = None
63- self . _coordinates : time_machine . Coordinates | None = None
65+ class Traveller ( BaseTraveller ):
66+ def __init__ ( self , datetime_class : type [ DateTime ] = DateTime ) -> None :
67+ super (). __init__ ( datetime_class )
6468
65- def freeze (self ) -> Self :
66- if self ._started :
67- cast (time_machine .Coordinates , self ._coordinates ).move_to (
68- self ._datetime_class .now (), tick = False
69- )
70- else :
71- self ._start (freeze = True )
69+ self ._started : bool = False
70+ self ._traveller : time_machine .travel | None = None
71+ self ._coordinates : time_machine .Coordinates | None = None
7272
73- return self
73+ def freeze (self ) -> Self :
74+ if self ._started :
75+ cast (time_machine .Coordinates , self ._coordinates ).move_to (
76+ self ._datetime_class .now (), tick = False
77+ )
78+ else :
79+ self ._start (freeze = True )
7480
75- def travel_back (self ) -> Self :
76- if not self ._started :
7781 return self
7882
79- cast (time_machine .travel , self ._traveller ).stop ()
80- self ._coordinates = None
81- self ._traveller = None
82- self ._started = False
83-
84- return self
85-
86- def travel (
87- self ,
88- years : int = 0 ,
89- months : int = 0 ,
90- weeks : int = 0 ,
91- days : int = 0 ,
92- hours : int = 0 ,
93- minutes : int = 0 ,
94- seconds : int = 0 ,
95- microseconds : int = 0 ,
96- * ,
97- freeze : bool = False ,
98- ) -> Self :
99- self ._start (freeze = freeze )
100-
101- cast (time_machine .Coordinates , self ._coordinates ).move_to (
102- self ._datetime_class .now ().add (
103- years = years ,
104- months = months ,
105- weeks = weeks ,
106- days = days ,
107- hours = hours ,
108- minutes = minutes ,
109- seconds = seconds ,
110- microseconds = microseconds ,
83+ def travel_back (self ) -> Self :
84+ if not self ._started :
85+ return self
86+
87+ cast (time_machine .travel , self ._traveller ).stop ()
88+ self ._coordinates = None
89+ self ._traveller = None
90+ self ._started = False
91+
92+ return self
93+
94+ def travel (
95+ self ,
96+ years : int = 0 ,
97+ months : int = 0 ,
98+ weeks : int = 0 ,
99+ days : int = 0 ,
100+ hours : int = 0 ,
101+ minutes : int = 0 ,
102+ seconds : int = 0 ,
103+ microseconds : int = 0 ,
104+ * ,
105+ freeze : bool = False ,
106+ ) -> Self :
107+ self ._start (freeze = freeze )
108+
109+ cast (time_machine .Coordinates , self ._coordinates ).move_to (
110+ self ._datetime_class .now ().add (
111+ years = years ,
112+ months = months ,
113+ weeks = weeks ,
114+ days = days ,
115+ hours = hours ,
116+ minutes = minutes ,
117+ seconds = seconds ,
118+ microseconds = microseconds ,
119+ )
111120 )
112- )
113121
114- return self
122+ return self
115123
116- def travel_to (self , dt : DateTime , * , freeze : bool = False ) -> Self :
117- self ._start (freeze = freeze )
124+ def travel_to (self , dt : DateTime , * , freeze : bool = False ) -> Self :
125+ self ._start (freeze = freeze )
118126
119- cast (time_machine .Coordinates , self ._coordinates ).move_to (dt )
127+ cast (time_machine .Coordinates , self ._coordinates ).move_to (dt )
120128
121- return self
129+ return self
122130
123- def _start (self , freeze : bool = False ) -> None :
124- if self ._started :
125- return
131+ def _start (self , freeze : bool = False ) -> None :
132+ if self ._started :
133+ return
126134
127- if not self ._traveller :
128- self ._traveller = time_machine .travel (
129- self ._datetime_class .now (), tick = not freeze
130- )
135+ if not self ._traveller :
136+ self ._traveller = time_machine .travel (
137+ self ._datetime_class .now (), tick = not freeze
138+ )
131139
132- self ._coordinates = self ._traveller .start ()
140+ self ._coordinates = self ._traveller .start ()
133141
134- self ._started = True
142+ self ._started = True
135143
136- def __enter__ (self ) -> Self :
137- self ._start ()
144+ def __enter__ (self ) -> Self :
145+ self ._start ()
138146
139- return self
147+ return self
140148
141- def __exit__ (
142- self ,
143- exc_type : type [BaseException ] | None ,
144- exc_val : BaseException | None ,
145- exc_tb : TracebackType ,
146- ) -> None :
147- self .travel_back ()
149+ def __exit__ (
150+ self ,
151+ exc_type : type [BaseException ] | None ,
152+ exc_val : BaseException | None ,
153+ exc_tb : TracebackType ,
154+ ) -> None :
155+ self .travel_back ()
156+
157+ else :
158+
159+ class Traveller (BaseTraveller ): # type: ignore[no-redef]
160+ def _not_implemented (self ) -> NotImplementedError :
161+ return NotImplementedError (
162+ "Time travelling is an optional feature. "
163+ 'You can add it by installing Pendulum with the "test" extra.'
164+ )
148165
149166else :
150167
151168 class Traveller (BaseTraveller ): # type: ignore[no-redef]
152- ...
169+ def _not_implemented (self ) -> NotImplementedError :
170+ return NotImplementedError (
171+ "Time travelling is not supported on the PyPy Python implementation."
172+ )
0 commit comments