Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
.. |ci| image:: https://github.com/alisaifee/hiro/workflows/CI/badge.svg?branch=master :target: https://github.com/alisaifee/hiro/actions?query=branch%3Amaster+workflow%3ACI .. |coveralls| image:: https://img.shields.io/coveralls/alisaifee/hiro/master.svg?style=flat-square :target: https://coveralls.io/r/alisaifee/hiro?branch=master .. |license| image:: https://img.shields.io/pypi/l/hiro.svg?style=flat-square :target: https://pypi.python.org/pypi/hiro .. |pypi| image:: https://img.shields.io/pypi/v/hiro.svg?style=flat-square :target: https://pypi.python.org/pypi/hiro .. |docs| image:: https://readthedocs.org/projects/hiro/badge :target: https://hiro.readthedocs.org
Hiro - time manipulation utilities for testing in python
|ci| |coveralls| |pypi| |docs| |license|
Yatta!
-- Hiro Nakamura
The hiro.Timeline
context manager hijacks a few commonly used time functions
to allow time manipulation within its context. Specifically time.sleep
, time.time
,
time.gmtime
, datetime.now
, datetime.utcnow
and datetime.today
behave according the configuration of the context.
The context provides the following manipulation options:
rewind
: accepts seconds as an integer or a timedelta
object.forward
: accepts seconds as an integer or a timedelta
object.freeze
: accepts a floating point time since epoch or datetime
or date
object 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 = deceleration
reset
: resets all time alterations... code-block:: python
import hiro
from datetime import timedelta, datetime
import time
datetime.now().isoformat()
# OUT: '2013-12-01T06:55:41.706060'
with hiro.Timeline() as timeline:
# forward by an hour
timeline.forward(60*60)
datetime.now().isoformat()
# OUT: '2013-12-01T07:55:41.707383'
# jump forward by 10 minutes
timeline.forward(timedelta(minutes=10))
datetime.now().isoformat()
# OUT: '2013-12-01T08:05:41.707425'
# jump to yesterday and freeze
timeline.freeze(datetime.now() - timedelta(hours=24))
datetime.now().isoformat()
# OUT: '2013-11-30T09:15:41'
timeline.scale(5) # scale time by 5x
time.sleep(5) # this will effectively only sleep for 1 second
# since time is frozen the sleep has no effect
datetime.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.
.. code-block:: python
import hiro
import time
from datetime import timedelta, datetime
start_point = datetime(2012,12,12,0,0,0)
my_timeline = hiro.Timeline(scale=5).forward(60*60).freeze()
with my_timeline as timeline:
print datetime.now()
# OUT: '2012-12-12 01:00:00.000315'
time.sleep(5) # effectively 1 second
# no effect as time is frozen
datetime.now()
# OUT: '2012-12-12 01:00:00.000315'
timeline.unfreeze()
# back to starting point
datetime.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'
Timeline
can additionally be used as a decorator
.. code-block:: python
import hiro
import time, datetime
@hiro.Timeline(scale=50000)
def sleeper():
datetime.datetime.now()
# OUT: '2013-11-30 14:27:43.409291'
time.sleep(60*60) # effectively 72 ms
datetime.datetime.now()
# OUT: '2013-11-30 15:28:36.240675'
@hiro.Timeline()
def sleeper_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'
In order to execute certain callables within a Timeline
context, two
shortcut functions are provided.
run_sync(factor=1, callable, *args, **kwargs)
run_async(factor=1, callable, *args, **kwargs)
Both functions return a ScaledRunner
object which provides the following methods
get_execution_time
: The actual execution time of the callable
get_response
(will either return the actual return value of callable
or raise the exception that was thrown)run_async
returns a derived class of ScaledRunner
that additionally provides the following methods
is_running
: True/False
depending on whether the callable has completed executionjoin
: blocks until the callable
completes execution.. code-block:: python
import hiro
import time
def _slow_function(n):
time.sleep(n)
if n > 10:
raise RuntimeError()
return n
runner = hiro.run_sync(10, _slow_function, 10)
runner.get_response()
# OUT: 10
# due to the scale factor 10 it only took 1s to execute
runner.get_execution_time()
# OUT: 1.1052658557891846
runner = hiro.run_async(10, _slow_function, 11)
runner.is_running()
# OUT: True
runner.join()
runner.get_execution_time()
# OUT: 1.1052658557891846
runner.get_response()
# OUT: Traceback (most recent call last):
# ....
# OUT: File "<input>", line 4, in _slow_function
# OUT: RuntimeError
.. :changelog:
Release Date: 2023-01-11
Chore:
Release Date: 2023-01-11
Features:
Bug Fix:
Deprecation:
run_async
in favor of run_threaded
Release Date: 2023-01-11
Chores:
Release Date: 2023-01-11
Compatibility:
Release Date: 2023-01-10
Compatibility:
Chores:
Release Date: 2019-10-10
Code cleanup
Release Date: 2017-07-26
Bug Fix:
Pull Request 3 <https://github.com/alisaifee/hiro/pull/3>
_)Release Date: 2015-06-07
Release Date: 2014-04-03
Bug Fix:
Release Date: 2014-04-01
Enhanced timeline decorator to pass generated timeline to decorated function
Release Date: 2014-02-20
Release Date: 2013-12-05
Added pypy support
Release Date: 2013-11-30
Allow ScaledTimeline to be used as a decorator
Release Date: 2013-11-30
Initial Release
FAQs
time manipulation utilities for testing in python
We found that hiro demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.