# CodeCutter
CodeCutter is a Python library designed to preprocess Python functions and methods by performing compile-time optimizations. Inspired by the behavior of the C preprocessor, CodeCutter enhances execution performance by simplifying code logic before it runs, focusing on optimizing variables and control flow statements.
## Features
- Replace variables with constants or expressions: Automatically replaces variables with constant values or constant expressions when detected. This allows for faster execution as it reduces the need for variable lookups during runtime.
- Simplify boolean if-clauses with constants: If a boolean expression contains constants, CodeCutter simplifies the expression by evaluating it during preprocessing. This can eliminate unnecessary branches in your code.
- Remove dead if-clauses: If certain conditions in if statements are known to always evaluate to True or False, CodeCutter removes or short-circuits these branches. This only includes unreachable code due to constants, not always-true conditions.
## Why CodeCutter?
Unlike regex-based or hacky import-time solutions, CodeCutter operates in a clean and structured way, leveraging Python’s internal structures to perform safe and reliable transformations. The library is built with extensibility in mind, allowing you to easily add custom preprocessing logic to match your specific optimization needs.
## Documentation
[A small documentation](https://github.com/b10011/codecutter/blob/master/documentation.md)
## Installation
You can install CodeCutter using pip:
```bash
pip3 install codecutter
```
## Examples
Here's an example of how CodeCutter can improve your function before runtime.
Original bad function
```python3
def bad_function(
iterations,
feature_a_enabled,
feature_b_enabled,
feature_c_enabled,
):
my_sum = 0
for i in range(iterations):
if feature_a_enabled:
my_sum += 1
if feature_b_enabled:
my_sum += 2
if feature_c_enabled:
my_sum += 3
my_sum += i
bad_function(10000, False, False, False)
```
The same function with preprocessing. Do note that the values of the constants
are given as strings. This is so that the system can replace constants even with
e.g. comparisons such as `"value >= 5"` or function calls. If you utilize
variables outside of the function body (e.g. decorators), pass those to the
preprocessor with `variables` kwarg.
```python3
from codecutter import preprocess
@preprocess(
constants={
"FEATURE_A_ENABLED": "False",
"FEATURE_B_ENABLED": "False",
"FEATURE_C_ENABLED": "False",
}
)
def good_function(iterations):
my_sum = 0
for i in range(iterations):
if FEATURE_A_ENABLED:
my_sum += 1
if FEATURE_B_ENABLED:
my_sum += 2
if FEATURE_C_ENABLED:
my_sum += 3
my_sum += i
good_function(10000)
```
The source code of the preprocessed function
```python3
def good_function(iterations):
my_sum = 0
for i in range(iterations):
my_sum += i
```
Performance difference (best of 5 runs with `%timeit`)
- Original: `267 µs ± 7.32 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)`
- Preprocessed: `196 µs ± 5.57 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)`
Over 26% improvement!
## Footnote
ChatGPT seems to excel at README's.
Raw data
{
"_id": null,
"home_page": "https://github.com/b10011/codecutter",
"name": "codecutter",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "preprocess, preprocessing, preprocessor, optimize, optimizer",
"author": "Niko J\u00e4rvinen",
"author_email": "nbjarvinen@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/e5/9c/408141bb14a041d3bd7db8a35546591334422115fda8e5efa2ac1c636d30/codecutter-0.1.2.tar.gz",
"platform": null,
"description": "# CodeCutter\n\nCodeCutter is a Python library designed to preprocess Python functions and methods by performing compile-time optimizations. Inspired by the behavior of the C preprocessor, CodeCutter enhances execution performance by simplifying code logic before it runs, focusing on optimizing variables and control flow statements.\n\n## Features\n\n- Replace variables with constants or expressions: Automatically replaces variables with constant values or constant expressions when detected. This allows for faster execution as it reduces the need for variable lookups during runtime.\n- Simplify boolean if-clauses with constants: If a boolean expression contains constants, CodeCutter simplifies the expression by evaluating it during preprocessing. This can eliminate unnecessary branches in your code.\n- Remove dead if-clauses: If certain conditions in if statements are known to always evaluate to True or False, CodeCutter removes or short-circuits these branches. This only includes unreachable code due to constants, not always-true conditions.\n\n## Why CodeCutter?\n\nUnlike regex-based or hacky import-time solutions, CodeCutter operates in a clean and structured way, leveraging Python\u2019s internal structures to perform safe and reliable transformations. The library is built with extensibility in mind, allowing you to easily add custom preprocessing logic to match your specific optimization needs.\n\n## Documentation\n\n[A small documentation](https://github.com/b10011/codecutter/blob/master/documentation.md)\n\n## Installation\n\nYou can install CodeCutter using pip:\n\n```bash\npip3 install codecutter\n```\n\n## Examples\n\nHere's an example of how CodeCutter can improve your function before runtime.\n\nOriginal bad function\n\n```python3\ndef bad_function(\n iterations,\n feature_a_enabled,\n feature_b_enabled,\n feature_c_enabled,\n):\n my_sum = 0\n\n for i in range(iterations):\n if feature_a_enabled:\n my_sum += 1\n\n if feature_b_enabled:\n my_sum += 2\n\n if feature_c_enabled:\n my_sum += 3\n\n my_sum += i\n\nbad_function(10000, False, False, False)\n```\n\nThe same function with preprocessing. Do note that the values of the constants\nare given as strings. This is so that the system can replace constants even with\ne.g. comparisons such as `\"value >= 5\"` or function calls. If you utilize\nvariables outside of the function body (e.g. decorators), pass those to the\npreprocessor with `variables` kwarg.\n\n```python3\nfrom codecutter import preprocess\n\n@preprocess(\n constants={\n \"FEATURE_A_ENABLED\": \"False\",\n \"FEATURE_B_ENABLED\": \"False\",\n \"FEATURE_C_ENABLED\": \"False\",\n }\n)\ndef good_function(iterations):\n my_sum = 0\n\n for i in range(iterations):\n if FEATURE_A_ENABLED:\n my_sum += 1\n\n if FEATURE_B_ENABLED:\n my_sum += 2\n\n if FEATURE_C_ENABLED:\n my_sum += 3\n\n my_sum += i\n\ngood_function(10000)\n```\n\nThe source code of the preprocessed function\n\n```python3\ndef good_function(iterations):\n my_sum = 0\n for i in range(iterations):\n my_sum += i\n```\n\nPerformance difference (best of 5 runs with `%timeit`)\n\n- Original: `267 \u00b5s \u00b1 7.32 \u00b5s per loop (mean \u00b1 std. dev. of 7 runs, 1,000 loops each)`\n- Preprocessed: `196 \u00b5s \u00b1 5.57 \u00b5s per loop (mean \u00b1 std. dev. of 7 runs, 1,000 loops each)`\n\nOver 26% improvement!\n\n## Footnote\n\nChatGPT seems to excel at README's.\n",
"bugtrack_url": null,
"license": null,
"summary": "Library for function preprocessing and optimization",
"version": "0.1.2",
"project_urls": {
"Documentation": "https://github.com/b10011/codecutter/blob/master/documentation.md",
"Homepage": "https://github.com/b10011/codecutter",
"Repository": "https://github.com/b10011/codecutter"
},
"split_keywords": [
"preprocess",
" preprocessing",
" preprocessor",
" optimize",
" optimizer"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "5d8738a3f96947f12d091b63826eadb1ed21852d682b753d41453fd3e8b8911f",
"md5": "3f8b145506c619a7f4dd736553737ad5",
"sha256": "a08bacfff4e29ac935ecd62953fcf5142d7ee965ae8ccc8c5bfa14b980268735"
},
"downloads": -1,
"filename": "codecutter-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3f8b145506c619a7f4dd736553737ad5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 6864,
"upload_time": "2024-10-21T17:40:09",
"upload_time_iso_8601": "2024-10-21T17:40:09.764441Z",
"url": "https://files.pythonhosted.org/packages/5d/87/38a3f96947f12d091b63826eadb1ed21852d682b753d41453fd3e8b8911f/codecutter-0.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e59c408141bb14a041d3bd7db8a35546591334422115fda8e5efa2ac1c636d30",
"md5": "17da6bccc15733b27b3270fc7f369ef5",
"sha256": "69df896b869aba75fc4504e8d23443dad7c85b1fda00e94eb9db0adf67cf0f54"
},
"downloads": -1,
"filename": "codecutter-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "17da6bccc15733b27b3270fc7f369ef5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 6031,
"upload_time": "2024-10-21T17:40:11",
"upload_time_iso_8601": "2024-10-21T17:40:11.492568Z",
"url": "https://files.pythonhosted.org/packages/e5/9c/408141bb14a041d3bd7db8a35546591334422115fda8e5efa2ac1c636d30/codecutter-0.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-21 17:40:11",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "b10011",
"github_project": "codecutter",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "codecutter"
}