Full Code of AlanCristhian/statically for AI

master 01ea9e5cbe04 cached
8 files
13.8 KB
3.7k tokens
24 symbols
1 requests
Download .txt
Repository: AlanCristhian/statically
Branch: master
Commit: 01ea9e5cbe04
Files: 8
Total size: 13.8 KB

Directory structure:
gitextract_et97gfi1/

├── .gitignore
├── LICENSE
├── README.md
├── README.rst
├── setup.py
├── statically.py
├── test_statically.py
└── test_statically_async.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# dotenv
.env

# virtualenv
.venv
venv/
ENV/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2017 Alan Cristhian

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# statically

Compiles a function or class with [Cython](http://www.cython.org). Use annotations for static type
declarations.

Python 3 is required.

To compile, you must decorate the function or class with `typed`. Example:

```python
import cython
import statically

@statically.typed
def func():
    # Cython types are evaluated as for cdef declarations
    x: cython.int               # cdef int x
    y: cython.double = 0.57721  # cdef double y = 0.57721
    z: cython.float  = 0.57721  # cdef float z  = 0.57721

    # Python types shadow Cython types for compatibility reasons
    a: float = 0.54321          # cdef double a = 0.54321
    b: int = 5                  # cdef object b = 5
    c: long = 6                 # cdef object c = 6

@statically.typed
class A:
    a: cython.int
    b: cython.int
    def __init__(self, b=0):
        self.a = 3
        self.b = b
```

Python 3.5 or less supports type hints in the parameters but not in the body
of the code. Read the next case:

```python
@statically.typed
def sum_powers(x: cython.int):
    return sum([x**n for n in range(1, x + 1)])
```

Works, but provides just a 5% increase in speed over the Python equivalent
because the `n` variable is not annotated. In this case you can declare
the type of the variable in the parameter with a default value.

```python
@statically.typed
def sum_powers(x: cython.int, n: cython.int = 0):
    return sum([x**n for n in range(1, x + 1)])
```

For this function I got more than 1,400% speed increase.

## Installation

```shell
$ pip install git+https://github.com/AlanCristhian/statically.git
```

## Caveats

- Async generators are not supported.
- In contexts that doesn't have file - IDLE or REPL - will fallback to normal Python code. Works fine with [IPython shell](http://ipython.readthedocs.io/en/stable/).

## Contribute

I am not a native english speaker, so you can help me with the documentation.
Also I am not convinced about the module name. The `typed` decorator can
compile functions or classes without type declarations.

Feel free to send me a pull request or open an issue.


================================================
FILE: README.rst
================================================
statically
==========

Compiles a function or class with `Cython <http://www.cython.org>`_. Use annotations for static type declarations.

Python 3.5+ is required.

To compile, you must decorate the function or class with ``typed``. Example: ::

    import cython
    import statically

    @statically.typed
    def func():
        # Cython types are evaluated as for cdef declarations
        x: cython.int               # cdef int x
        y: cython.double = 0.57721  # cdef double y = 0.57721
        z: cython.float  = 0.57721  # cdef float z  = 0.57721

        # Python types shadow Cython types for compatibility reasons
        a: float = 0.54321          # cdef double a = 0.54321
        b: int = 5                  # cdef object b = 5
        c: long = 6                 # cdef object c = 6

    @statically.typed
    class A:
        a: cython.int
        b: cython.int
        def __init__(self, b=0):
            self.a = 3
            self.b = b

Python 3.5 or less supports type hints in the parameters but not in the body
of the code. Read the next case: ::

    @statically.typed
    def sum_powers(x: cython.int):
        return sum([x**n for n in range(1, x + 1)])


Works, but provides just a 5% increase in speed over the Python equivalent
because the `n` variable is not annotated. In this case you can declare
the type of the variable in the parameter with a default value. ::

    @statically.typed
    def sum_powers(x: cython.int, n: cython.int = 0):
        return sum([x**n for n in range(1, x + 1)])

For this function I got more than 1,400% speed increase.

Installation
------------

    $ pip install git+https://github.com/AlanCristhian/statically.git

Caveats
-------

- Async generators are not supported.
- In contexts that doesn't have file - IDLE or REPL - will fallback to normal Python code. Works fine with `IPython shell <http://ipython.readthedocs.io/en/stable/>`_.

Contribute
----------

I am not a native english speaker, so you can help me with the documentation.
Also I am not convinced about the module name. The `typed` decorator can
compile functions or classes without type declarations.

Feel free to send me a pull request or open an issue.


================================================
FILE: setup.py
================================================
"""Installation script."""

from setuptools import setup
from sys import version_info

assert version_info >= (3,), \
"Python 3 is required. Got %s.%s" % (version_info.major, version_info.minor)

setup(
    name="statically",
    version="1.0a2",
    py_modules=["statically"],
    zip_safe=True,
    author="Alan Cristhian",
    author_email="alan.cristh@gmail.com",
    description="Compiles a python function with cython using only a decorator.",
    license="MIT",
    keywords="cython decorator compilation",
    url="https://github.com/AlanCristhian/statically",
    install_requires=["cython"],
)


================================================
FILE: statically.py
================================================
import inspect
import sys
import warnings

import cython


__all__ = ["typed"]
__version__ = "1.0a2"


# async generators only present in Python 3.6+
has_async_gen_fun = (3, 6) <= sys.version_info[:2]


def _can_cython_inline():
    """Checks whether we are in a context which makes it possible to compile code inline with Cython.

    Currently it is known that standard REPL and IDLE can't do that.
    """
    import __main__ as main

    # statically works with IPython
    if hasattr(main, 'get_ipython'):
        return True

    # standard REPL doesn't have __file__
    return hasattr(main, '__file__')


def _get_source_code(obj):
    if inspect.isclass(obj):
        lines = inspect.getsourcelines(obj)[0]
        extra_spaces = lines[0].find("class")
        return "".join(l[extra_spaces:] for l in lines)
    elif callable(obj):
        lines = inspect.getsourcelines(obj)[0]
        extra_spaces = lines[0].find("@")
        return "".join(l[extra_spaces:] for l in lines[1:])
    else:
        message = "Function or class expected, got {}.".format(type(obj).__name__)
        raise TypeError(message)


def _get_non_local_scopes(frame):
    while frame:
        yield frame.f_locals
        frame = frame.f_back


def _get_outer_variables(obj):
    frame = inspect.currentframe().f_back
    non_local_scopes = _get_non_local_scopes(frame)
    non_local_variables = list(obj.__code__.co_freevars)
    variables = {}
    for scope in non_local_scopes:
        for name in non_local_variables:
            if name in scope:
                variables[name] = scope[name]
                non_local_variables.remove(name)
        if not non_local_variables:
            break
    return variables


def typed(obj):
    """Compiles a function or class with cython.

    Use annotations for static type declarations. Example:

        import statically

        @statically.typed
        def add_two(x: int) -> int:
            two: int = 2
            return x + two
    """
    if not _can_cython_inline():
        return obj
    elif has_async_gen_fun and inspect.isasyncgenfunction(obj):
        raise TypeError("Async generator funcions are not supported.")

    source = _get_source_code(obj)
    frame = inspect.currentframe().f_back
    if inspect.isclass(obj):
        locals_ = frame.f_locals
    else:
        locals_ = _get_outer_variables(obj)
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        compiled = cython.inline(source, locals=locals_,
                                 globals=frame.f_globals, quiet=True)
        return compiled[obj.__name__]


if not _can_cython_inline():
    warnings.warn(
        "Current code isn't launched from a file so statically.typed isn't able to cythonize stuff."
        "Falling back to normal Python code.",
        RuntimeWarning
    )


================================================
FILE: test_statically.py
================================================
import unittest
import asyncio
import subprocess
import sys
import os.path

import cython
try:
    import IPython
except ImportError:
    ipython_installed = False
else:
    ipython_installed = True

import statically


ONE_HUNDRED = 100
execute = asyncio.get_event_loop().run_until_complete


def is_cython_function(obj):
    return 'cython_function_or_method' in str(type(obj))


def anext(agen):
    gen = agen.asend(None)
    try:
        gen.send(None)
    except StopIteration as error:
        return error.args[0]


class CompilationSuite(unittest.TestCase):
    def test_function(self):
        @statically.typed
        def identity(x: cython.int):
            return x
        self.assertEqual(identity(14), 14)

    def test_is_compiled(self):
        @statically.typed
        def compiled(x: cython.int):
            return x
        self.assertTrue(is_cython_function(compiled))

    def test_non_local_var_in_class(self):
        one = 1
        @statically.typed
        class Class:
            number = 100 + one
        self.assertEqual(Class.number, 101)

    def test_non_local_var_in_method(self):
        two = 2
        class Class:
            @statically.typed
            def add_two(self, x):
                return x + two
        obj = Class()
        self.assertEqual(obj.add_two(100), 102)

    def test_non_local_var_in_function(self):
        tree = 3
        @statically.typed
        def add_tree(x):
            return x + tree
        self.assertEqual(add_tree(100), 103)

    def test_non_local_var_in_generator_function(self):
        four = 4
        @statically.typed
        def add_four(x):
            yield x + four
        self.assertEqual(next(add_four(100)), 104)

    def test_non_local_var_in_coroutine_function(self):
        five = 5
        @statically.typed
        async def add_five(x):
            return x + five
        self.assertEqual(execute(add_five(100)), 105)

    def test_global_var_in_class(self):
        @statically.typed
        class Class_:
            number = 1 + ONE_HUNDRED
        self.assertEqual(Class_.number, 101)

    def test_global_var_in_method(self):
        class Class:
            @statically.typed
            def add_one_hundred(self, x):
                return ONE_HUNDRED + x
        obj = Class()
        self.assertEqual(obj.add_one_hundred(2), 102)

    def test_global_var_in_function(self):
        @statically.typed
        def add_one_hundred(x):
            return ONE_HUNDRED + x
        self.assertEqual(add_one_hundred(3), 103)

    def test_global_var_in_generator_function(self):
        @statically.typed
        def add_one_hundred(x):
            yield ONE_HUNDRED + x
        self.assertEqual(next(add_one_hundred(4)), 104)

    def test_global_var_in_coroutine_function(self):
        @statically.typed
        async def add_one_hundred(x):
            return ONE_HUNDRED + x
        self.assertEqual(execute(add_one_hundred(5)), 105)

    @unittest.skipUnless(statically.has_async_gen_fun, "Test does not apply for this version of Python")
    def test_async_generator(self):
        message = r"Async generator funcions are not supported."
        with self.assertRaisesRegex(TypeError, message):
             from test_statically_async import generator


@unittest.skipUnless(ipython_installed, "IPython not installed")
class IPythonSuite(unittest.TestCase):
    def test_ipython(self):
        base_dir = os.path.dirname(sys.executable)
        executable = os.path.join(base_dir, "ipython")
        process = subprocess.Popen([executable], stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE)
        script = "import statically\n" \
                 "@statically.typed\n" \
                 "def add(a: int, b: int): return a + b\n\n" \
                 "'cython_function_or_method' in str(type(add))\n".encode()
        stdout, _ = process.communicate(script)
        lines = stdout.decode().split("\n")
        process.terminate()
        self.assertEqual(lines[-4], "In [3]: Out[3]: True")


if __name__ == '__main__':
    unittest.main()


================================================
FILE: test_statically_async.py
================================================
import statically

@statically.typed
async def generator():
    yield
Download .txt
gitextract_et97gfi1/

├── .gitignore
├── LICENSE
├── README.md
├── README.rst
├── setup.py
├── statically.py
├── test_statically.py
└── test_statically_async.py
Download .txt
SYMBOL INDEX (24 symbols across 3 files)

FILE: statically.py
  function _can_cython_inline (line 16) | def _can_cython_inline():
  function _get_source_code (line 31) | def _get_source_code(obj):
  function _get_non_local_scopes (line 45) | def _get_non_local_scopes(frame):
  function _get_outer_variables (line 51) | def _get_outer_variables(obj):
  function typed (line 66) | def typed(obj):

FILE: test_statically.py
  function is_cython_function (line 22) | def is_cython_function(obj):
  function anext (line 26) | def anext(agen):
  class CompilationSuite (line 34) | class CompilationSuite(unittest.TestCase):
    method test_function (line 35) | def test_function(self):
    method test_is_compiled (line 41) | def test_is_compiled(self):
    method test_non_local_var_in_class (line 47) | def test_non_local_var_in_class(self):
    method test_non_local_var_in_method (line 54) | def test_non_local_var_in_method(self):
    method test_non_local_var_in_function (line 63) | def test_non_local_var_in_function(self):
    method test_non_local_var_in_generator_function (line 70) | def test_non_local_var_in_generator_function(self):
    method test_non_local_var_in_coroutine_function (line 77) | def test_non_local_var_in_coroutine_function(self):
    method test_global_var_in_class (line 84) | def test_global_var_in_class(self):
    method test_global_var_in_method (line 90) | def test_global_var_in_method(self):
    method test_global_var_in_function (line 98) | def test_global_var_in_function(self):
    method test_global_var_in_generator_function (line 104) | def test_global_var_in_generator_function(self):
    method test_global_var_in_coroutine_function (line 110) | def test_global_var_in_coroutine_function(self):
    method test_async_generator (line 117) | def test_async_generator(self):
  class IPythonSuite (line 124) | class IPythonSuite(unittest.TestCase):
    method test_ipython (line 125) | def test_ipython(self):

FILE: test_statically_async.py
  function generator (line 4) | async def generator():
Condensed preview — 8 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (15K chars).
[
  {
    "path": ".gitignore",
    "chars": 1157,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
  },
  {
    "path": "LICENSE",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2017 Alan Cristhian\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "README.md",
    "chars": 2098,
    "preview": "# statically\n\nCompiles a function or class with [Cython](http://www.cython.org). Use annotations for static type\ndeclara"
  },
  {
    "path": "README.rst",
    "chars": 2198,
    "preview": "statically\n==========\n\nCompiles a function or class with `Cython <http://www.cython.org>`_. Use annotations for static t"
  },
  {
    "path": "setup.py",
    "chars": 604,
    "preview": "\"\"\"Installation script.\"\"\"\n\nfrom setuptools import setup\nfrom sys import version_info\n\nassert version_info >= (3,), \\\n\"P"
  },
  {
    "path": "statically.py",
    "chars": 2833,
    "preview": "import inspect\nimport sys\nimport warnings\n\nimport cython\n\n\n__all__ = [\"typed\"]\n__version__ = \"1.0a2\"\n\n\n# async generator"
  },
  {
    "path": "test_statically.py",
    "chars": 4091,
    "preview": "import unittest\nimport asyncio\nimport subprocess\nimport sys\nimport os.path\n\nimport cython\ntry:\n    import IPython\nexcept"
  },
  {
    "path": "test_statically_async.py",
    "chars": 70,
    "preview": "import statically\n\n@statically.typed\nasync def generator():\n    yield\n"
  }
]

About this extraction

This page contains the full source code of the AlanCristhian/statically GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 8 files (13.8 KB), approximately 3.7k tokens, and a symbol index with 24 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!