{"id":50556368,"url":"https://github.com/abhijatchaturvedi/timerx","last_synced_at":"2026-06-04T07:08:01.587Z","repository":{"id":360869731,"uuid":"1252060449","full_name":"abhijatchaturvedi/timerx","owner":"abhijatchaturvedi","description":"Tiny dependency-free Python timing utility with decorators, context managers, stopwatches, cumulative stats, and pretty summaries.","archived":false,"fork":false,"pushed_at":"2026-05-28T07:29:47.000Z","size":17,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-28T08:22:08.035Z","etag":null,"topics":["decorator","profiling","python","stopwatch","testing","timer","timing","utility"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abhijatchaturvedi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-28T06:43:06.000Z","updated_at":"2026-05-28T07:29:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/abhijatchaturvedi/timerx","commit_stats":null,"previous_names":["abhijatchaturvedi/timerx"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/abhijatchaturvedi/timerx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhijatchaturvedi%2Ftimerx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhijatchaturvedi%2Ftimerx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhijatchaturvedi%2Ftimerx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhijatchaturvedi%2Ftimerx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abhijatchaturvedi","download_url":"https://codeload.github.com/abhijatchaturvedi/timerx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhijatchaturvedi%2Ftimerx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33893676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decorator","profiling","python","stopwatch","testing","timer","timing","utility"],"created_at":"2026-06-04T07:08:00.996Z","updated_at":"2026-06-04T07:08:01.581Z","avatar_url":"https://github.com/abhijatchaturvedi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# timerx\n\n[![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](pyproject.toml)\n[![Python](https://img.shields.io/badge/python-%3E%3D3.10-blue.svg)](pyproject.toml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Tests](https://img.shields.io/badge/tests-33%20passing-brightgreen.svg)](tests/test_timerx.py)\n[![Dependencies](https://img.shields.io/badge/runtime%20deps-zero-brightgreen.svg)](pyproject.toml)\n\ntimerx is a tiny, dependency-free timing utility for Python. It gives you one\nsimple API for timing functions, code blocks, and named stopwatches, then keeps\ncumulative stats so you can inspect timings programmatically or print a compact\nsummary.\n\nUse it when you want quick timing information without setting up a profiler or\nmanually calling `time.perf_counter()` throughout your code.\n\n## Features\n\n- Works as a decorator, context manager, or manual stopwatch\n- Supports sync and async functions\n- Accumulates count, total, average, min, max, and last duration\n- Records timings even when decorated functions or context blocks raise\n- Supports concurrent named stopwatches\n- Provides isolated `TimerX()` instances for libraries and tests\n- Uses only the Python standard library at runtime\n\n## Install\n\n```bash\npip install timerx\n```\n\nFor local development:\n\n```bash\npip install -e \".[test]\"\npytest\n```\n\n## Quick Example\n\nThis example shows the three main ways to use timerx: decorate a function,\nmeasure a block, and manually start and stop a named timer.\n\n```python\nimport time\nimport timerx\n\n\n@timerx.track\ndef train_model():\n    time.sleep(0.2)\n\n\ntrain_model()\ntrain_model()\n\nwith timerx.lap(\"preprocessing\"):\n    time.sleep(0.05)\n\ntimerx.start(\"postprocess\")\ntime.sleep(0.01)\nelapsed = timerx.stop(\"postprocess\")\n\nprint(f\"postprocess took {elapsed:.4f}s\")\nprint(timerx.summary())\n```\n\nExample summary:\n\n```text\nname           count  total     avg       min       max       last\n-------------  -----  --------  --------  --------  --------  --------\ntrain_model    2      400ms     200ms     200ms     200ms     200ms\npreprocessing  1      50ms      50ms      50ms      50ms      50ms\npostprocess    1      10ms      10ms      10ms      10ms      10ms\n```\n\n## Timing Functions\n\nUse `@timerx.track` when you want to measure every call to a function. It works\nwith or without parentheses. By default, the function name is used as the timing\nlabel, but you can provide a custom name.\n\n```python\n@timerx.track\ndef load_data():\n    return [1, 2, 3]\n\n\n@timerx.track()\ndef preprocess():\n    return \"ready\"\n\n\n@timerx.track(name=\"model.fit\")\ndef train():\n    return \"done\"\n```\n\nStats accumulate across multiple calls:\n\n```python\nload_data()\nload_data()\n\nstats = timerx.get_stats()\nprint(stats[\"load_data\"][\"count\"])  # 2\nprint(stats[\"load_data\"][\"avg\"])    # average duration in seconds\n```\n\nDecorated functions are recorded even if they raise an exception, and the\noriginal exception is still raised normally.\n\n## Timing Async Functions\n\n`track` also supports coroutine functions.\n\n```python\n@timerx.track(name=\"fetch\")\nasync def fetch_rows():\n    return await client.get(\"/rows\")\n```\n\n## Timing Code Blocks\n\nUse `timerx.lap(name)` as a context manager when you want to measure part of a\nfunction. Laps record timings even when the block raises, and nested laps work\nnaturally.\n\n```python\nwith timerx.lap(\"pipeline\"):\n    with timerx.lap(\"load\"):\n        rows = load_rows()\n\n    with timerx.lap(\"transform\"):\n        rows = transform(rows)\n```\n\n## Stopwatches\n\nUse `start(name)` and `stop(name)` when the start and end of the work are in\ndifferent places. Named stopwatches can run concurrently. If you start the same\nname more than once, timerx treats it as a stack, so `stop(name)` closes the most\nrecent start.\n\n```python\ntimerx.start(\"download\")\ntimerx.start(\"parse\")\n\ntimerx.stop(\"parse\")\ntimerx.stop(\"download\")\n```\n\n`stop(name)` returns the elapsed duration in seconds and also records it in the\nsame stats store used by decorators and laps.\n\n## Reading Results\n\nUse `summary()` for human-readable output:\n\n```python\nprint(timerx.summary())\nprint(timerx.summary(unit=\"ms\"))\nprint(timerx.summary(sort_by=\"total\"))  # most expensive first\n```\n\nSupported units are `auto`, `s`, `ms`, `us`, `µs`, and `microseconds`. Auto mode\npicks seconds, milliseconds, or microseconds per value.\n\nPass `sort_by` with any stat column name (`count`, `total`, `avg`, `min`, `max`,\n`last`) to sort rows descending by that column. Default is insertion order.\n\nUse `get_stats()` when you need data for tests, logs, dashboards, or your own\nformatting:\n\n```python\nstats = timerx.get_stats()\n\n{\n    \"preprocessing\": {\n        \"count\": 1,\n        \"total\": 0.00512,\n        \"min\": 0.00512,\n        \"max\": 0.00512,\n        \"last\": 0.00512,\n        \"avg\": 0.00512,\n    }\n}\n```\n\nDurations in `get_stats()` are always stored as seconds.\n\n## Isolated Instances\n\nThe top-level `timerx.track`, `timerx.lap`, `timerx.start`, and `timerx.stop`\nhelpers share one global timer. For libraries, tests, or applications that need\nseparate timing state, create a `TimerX()` instance.\n\n```python\nfrom timerx import TimerX\n\ntx = TimerX()\n\nwith tx.lap(\"local\"):\n    run_work()\n\nprint(tx.get_stats())\n```\n\n## Resetting\n\nUse `reset()` to clear recorded timings and running stopwatches.\n\n```python\ntimerx.reset()\n```\n\n## Development\n\n```bash\npip install -e \".[test]\"\npytest\npython examples/demo.py\n```\n\n## Contributing\n\nContributions are welcome. If you find a bug, have an API idea, or want to add\ncoverage for an edge case, please open an issue or pull request.\n\n## License\n\ntimerx is released under the MIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhijatchaturvedi%2Ftimerx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabhijatchaturvedi%2Ftimerx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhijatchaturvedi%2Ftimerx/lists"}