Package: hiro
Yatta!—Hiro NakamuraHiro context managerTimeline contextThehiro.Timelinecontext manager hijacks a few commonly used time functions
to allow time manipulation within its context. Specificallytime.sleep,time.time,time.gmtime,datetime.now,datetime.utcnowanddatetime.todaybehave according the configuration of the context.The context provides the following manipulation options:rewind: accepts seconds as an integer or atimedeltaobject.forward: accepts seconds as an integer or atimedeltaobject.freeze: accepts a floating point time since epoch ordatetimeordateobject to freeze the time at.unfreeze: resumes time from the point it was frozen at.scale: accepts a floating point to accelerate/decelerate time by.> 1 = acceleration,  < 1 = decelerationreset: resets all time alterations.importhirofromdatetimeimporttimedelta,datetimeimporttimedatetime.now().isoformat()# OUT: '2013-12-01T06:55:41.706060'withhiro.Timeline()astimeline:# forward by an hourtimeline.forward(60*60)datetime.now().isoformat()# OUT: '2013-12-01T07:55:41.707383'# jump forward by 10 minutestimeline.forward(timedelta(minutes=10))datetime.now().isoformat()# OUT: '2013-12-01T08:05:41.707425'# jump to yesterday and freezetimeline.freeze(datetime.now()-timedelta(hours=24))datetime.now().isoformat()# OUT: '2013-11-30T09:15:41'timeline.scale(5)# scale time by 5xtime.sleep(5)# this will effectively only sleep for 1 second# since time is frozen the sleep has no effectdatetime.now().isoformat()# OUT: '2013-11-30T09:15:41'timeline.rewind(timedelta(days=365))datetime.now().isoformat()# OUT: '2012-11-30T09:15:41'To reduce the amount of statements inside the context, certain timeline setup
tasks can be done via the constructor and/or by using the fluent interface.importhiroimporttimefromdatetimeimporttimedelta,datetimestart_point=datetime(2012,12,12,0,0,0)my_timeline=hiro.Timeline(scale=5).forward(60*60).freeze()withmy_timelineastimeline:printdatetime.now()# OUT: '2012-12-12 01:00:00.000315'time.sleep(5)# effectively 1 second# no effect as time is frozendatetime.now()# OUT: '2012-12-12 01:00:00.000315'timeline.unfreeze()# back to starting pointdatetime.now()# OUT: '2012-12-12 01:00:00.000317'time.sleep(5)# effectively 1 second# takes effect (+5 seconds)datetime.now()# OUT: '2012-12-12 01:00:05.003100'Timelinecan additionally be used as a decoratorimporthiroimporttime,datetime@hiro.Timeline(scale=50000)defsleeper():datetime.datetime.now()# OUT: '2013-11-30 14:27:43.409291'time.sleep(60*60)# effectively 72 msdatetime.datetime.now()# OUT: '2013-11-30 15:28:36.240675'@hiro.Timeline()defsleeper_aware(timeline):datetime.datetime.now()# OUT: '2013-11-30 14:27:43.409291'timeline.forward(60*60)datetime.datetime.now()# OUT: '2013-11-30 15:28:36.240675'Hiro executorsIn order to execute certain callables within aTimelinecontext, two
shortcut functions are provided.run_sync(factor=1, callable, *args, **kwargs)run_async(factor=1, callable, *args, **kwargs)Both functions return aScaledRunnerobject which provides the following methodsget_execution_time: The actual execution time of thecallableget_response(will either return the actual return value ofcallableor raise the exception that was thrown)run_asyncreturns a derived class ofScaledRunnerthat additionally provides the following methodsis_running:True/Falsedepending on whether the callable has completed executionjoin: blocks until thecallablecompletes executionExampleimporthiroimporttimedef_slow_function(n):time.sleep(n)ifn>10:raiseRuntimeError()returnnrunner=hiro.run_sync(10,_slow_function,10)runner.get_response()# OUT: 10# due to the scale factor 10 it only took 1s to executerunner.get_execution_time()# OUT: 1.1052658557891846runner=hiro.run_async(10,_slow_function,11)runner.is_running()# OUT: Truerunner.join()runner.get_execution_time()# OUT: 1.1052658557891846runner.get_response()# OUT: Traceback (most recent call last):# ....# OUT:   File "<input>", line 4, in _slow_function# OUT: RuntimeErrorChangelogv1.1.1Release Date: 2023-01-11Chore:Fix github release actionv1.1.0Release Date: 2023-01-11Features:Patch time.time_ns, time.monotonic, time.monotonic_ns, time.localtimeBug Fix:Ensure time.gmtime and time.localtime work with 0 valuesEnsure Timeline can be instantiated with start=0 to reflect  time=0Improve naming of threaded classes/functionsDeprecation:Deprecatedrun_asyncin favor ofrun_threadedv1.0.2Release Date: 2023-01-11Chores:Update documentation themev1.0.1Release Date: 2023-01-11Compatibility:Update package classifiers to reflect python version supportv1.0.0Release Date: 2023-01-10Compatibility:Drop support for python < 3.7Update sources to not need six for compatibilityChores:Standardize lintingAdd Asia/Shanghai to CI matrixv0.5.1Release Date: 2019-10-10Code cleanupv0.5Release Date: 2017-07-26Bug Fix:Account for microsecond resolution (Pull Request 3)v0.1.8Release Date: 2015-06-07Add Python 3.x supportv0.1.5Release Date: 2014-04-03Bug Fix:Imports from time weren’t being patched.v0.1.3Release Date: 2014-04-01Enhanced timeline decorator to pass generated timeline
to decorated functionv0.1.2Release Date: 2014-02-20Added blacklist for unpatchable modulesCI improvementsremoved ScaledTimelinev0.1.1Release Date: 2013-12-05Added pypy supportv0.0.3Release Date: 2013-11-30Allow ScaledTimeline to be used as a decoratorv0.0.1Release Date: 2013-11-30Initial Release