Developer Interface (API)

Csnake has no user interface or CLI functionality. It’s a code-only package and is meant to be used by developers in their own scripts and programs. The API intended for external use is documented in this file.

File-level code container

This class is intended to be your main way of interacting with csnake. It’s a container allows for easy inclusion of various aspects of C language constructs (i.e. a function’s prototype, a variable’s initialization, …).

Those constructs must previously be declared (instantiated using the provided classes).

Calling the appropriate methods (i.e. CodeWriter.add_variable_initialization()) adds the code to the container sequentially.

class csnake.CodeWriter(lf=None, indent=4)[source]

Bases: CodeWriterLite

Container class for C code, with methods to add C constructs.

CodeWriter (abbreviated CW or cw) is a code container that allows you to add code (both manually written and generated), access it as a str, iterate over the lines of code and output the code to a file.

It also helps you to indent and dedent code, open or close code blocks consistently.

CodeWriter is iterable (iterates over lines of code), and also has methods like __contains__() and __len__().

Here’s an overview of abc’s CodeWriter is a virtual subclass of:

>>> from csnake import CodeWriter
>>> from collections.abc import Container, Iterable, Sized, Collection
>>> cwr = CodeWriter()
>>> assert isinstance(cwr, Container)
>>> assert isinstance(cwr, Iterable)
>>> assert isinstance(cwr, Sized)
>>> assert isinstance(cwr, Collection)
Parameters:
  • lf (Optional[str]) – linefeed character used to separate lines of code when rendering code with str() or code.

  • indent (Union[int, str]) – indentation unit string or int number of spaces, used to indent code.

lf

linefeed character used to separate lines of code when rendering code with str() or code.

Type:

str

lines

lines of code.

Type:

list(str)

__contains__(item)

Return whether a str is a substring of the codewriter.

Parameters:

item (str) – a potential substring of the codewriter.

Return type:

bool

Returns:

Whether or not item is a substring of the str() representation of the codewriter.

__getitem__(key)

Return the nth line of code.

Return type:

str

__iter__()

Return an iterator that iterates over the lines in the codewriter.

Return type:

Iterable[str]

__len__()

Return the number of lines in the codewriter.

__str__()

Return the code joined by lf.

Return type:

str

add(text)

Append text to the end of last line.

Parameters:

text (str) – str to append to the last line.

Raises:

ValueError – if text is not a str.

Return type:

None

add_autogen_comment(source_file_name=None)[source]

Add a comment denoting the code was autogenerated by a script.

File name of the script the file is generated from is optional.

Parameters:

source_file_name (Optional[str]) – name of the script the code was generated from

Return type:

None

Examples

Without a script file name:

>>> from csnake import CodeWriter
>>> cwr1 = CodeWriter()
>>> cwr1.add_autogen_comment()
>>> print(cwr1) 
/*
* This file was automatically generated using csnake v0.2.1.
*
* This file should not be edited directly, any changes will be
* overwritten next time the script is run.
*
* Source code for csnake is available at:
* https://gitlab.com/andrejr/csnake
*/

With a script name:

>>> from csnake import CodeWriter
>>> cwr2 = CodeWriter()
>>> cwr2.add_autogen_comment('test.py')
>>> print(cwr2) 
/*
* This file was automatically generated using csnake v0.2.1.
*
* This file should not be edited directly, any changes will be
* overwritten next time the script is run.
* Make any changes to the file 'test.py', not this file.
*
* Source code for csnake is available at:
* https://gitlab.com/andrejr/csnake
*/
add_define(name, value=None, comment=None)[source]

Add a define directive for macros.

Macros may or may not have a value.

Parameters:
  • name (str) – macro name

  • value (Union[CExtendedLiteral, VariableValue, None]) – literal or variable assigned to the macro (optional)

  • comment (Optional[str]) – comment accompanying macro definition

Return type:

None

Examples

>>> from csnake import CodeWriter, Variable, Subscript
>>> cwr = CodeWriter()
>>> cwr.add_define('PI', 3.14)
>>> cwr.add_define('LOG')
>>> somearr = Variable('some_array', 'int', value=range(0, 5))
>>> cwr.add_define('DEST', Subscript(somearr, 2))
>>> print(cwr)
#define PI 3.14
#define LOG
#define DEST some_array[2]
add_enum(enum)[source]

Add an enumeration definition.

Parameters:

enum (Enum) – enum in question

Return type:

None

See also

Enum for details on the enum class

Examples

>>> from csnake import (
...     CodeWriter, Enum, Variable, Dereference, AddressOf
... )
>>> cw = CodeWriter()
>>> name = "somename"
>>> pfx = "pfx"
>>> typedef = False
>>> enum = Enum(name, prefix=pfx, typedef=typedef)
>>> cval1 = Variable("varname", "int")
>>> enum.add_value("val1", 1)
>>> enum.add_value("val2", Dereference(1000))
>>> enum.add_value("val3", cval1)
>>> enum.add_value("val4", AddressOf(cval1), "some comment")
>>> cw.add_enum(enum)
>>> print(cw)
enum somename
{
    pfxval1 = 1,
    pfxval2 = *1000,
    pfxval3 = varname,
    pfxval4 = &varname /* some comment */
};
add_function_call(func, *arg)[source]

Add a call to a function with listed arguments.

Parameters:
  • func (Function) – function in question

  • *arg – (rest of the args) function’s args in sequence

Return type:

None

See also

Function for details on the Function class

Examples

>>> from csnake import CodeWriter, Variable, Function
>>> cw = CodeWriter()
>>> arg1 = Variable("arg1", "int")
>>> arg2 = Variable("arg2", "int", value=range(10))
>>> arg3 = ("arg3", "int")
>>> arg4 = {"name": "arg4", "primitive": "int"}
>>> fun = Function(
...     "testfunct", "void", arguments=(arg1, arg2, arg3, arg4)
... )
>>> fun.add_code(("code;", "more_code;"))
>>> cw.add_function_call(fun, 1, 2, 3, 4)
>>> print(cw)
testfunct(1, 2, 3, 4);
add_function_definition(func)[source]

Add a functions’s definition / implementation.

Parameters:

func (Function) – function in question

Return type:

None

See also

Function for details on the Function class

Examples

>>> from csnake import CodeWriter, Variable, Function
>>> cw = CodeWriter()
>>> arg1 = Variable("arg1", "int")
>>> arg2 = Variable("arg2", "int", value=range(10))
>>> arg3 = ("arg3", "int")
>>> arg4 = {"name": "arg4", "primitive": "int"}
>>> fun = Function(
...     "testfunct", "void", arguments=(arg1, arg2, arg3, arg4)
... )
>>> fun.add_code(("code;", "more_code;"))
>>> cw.add_function_definition(fun)
>>> print(cw)
void testfunct(int arg1, int arg2[10], int arg3, int arg4)
{
    code;
    more_code;
}
add_function_prototype(func, extern=False, comment=None)[source]

Add a functions’s prototype.

Parameters:
  • func (Function) – function in question

  • extern (bool) – wheter to add the extern qualifier to the

  • prototype (True) or not (False, default)

  • comment (Optional[str]) – accompanying inline comment

Return type:

None

See also

Function for details on the Function class

Examples

>>> from csnake import CodeWriter, Variable, Function
>>> cw = CodeWriter()
>>> arg1 = Variable("arg1", "int")
>>> arg2 = Variable("arg2", "int", value=range(10))
>>> arg3 = ("arg3", "int")
>>> arg4 = {"name": "arg4", "primitive": "int"}
>>> fun = Function(
...     "testfunct", "void", arguments=(arg1, arg2, arg3, arg4)
... )
>>> fun.add_code(("code;", "more_code;"))
>>> cw.add_function_prototype(fun)
>>> print(cw)
void testfunct(int arg1, int arg2[10], int arg3, int arg4);
add_license_comment(license_, authors=None, intro=None, year=None)[source]

Add a comment with the license and authors.

The comment also adds the year to the copyright.

Parameters:
  • license_ (str) – str containing the text of the license

  • authors (Optional[Iterable[Mapping[str, str]]]) – optional iterable containing mappings (dict-likes, one per author) with key-value pairs for keys ‘name’ (author’s name) and email (author’s email, optional)

  • intro (Optional[str]) – introductory text added before the author list, optional

  • year (Optional[int]) – year of the copyright (optional). If it is left out, current year is assumed.

Raises:

ValueError – if any of the arguments is of wrong type

Return type:

None

Examples

Just license:

>>> from csnake import CodeWriter
>>> license_text = 'license\ntext\nlines'
>>> cw1 = CodeWriter()
>>> cw1.add_license_comment(license_text)
>>> print(cw1)
/*
* license
* text
* lines
*/

With introduction:

>>> intro_text = 'intro\ntext'
>>> cw2 = CodeWriter()
>>> cw2.add_license_comment(license_text, intro=intro_text)
>>> print(cw2)
/*
* intro
* text
*
* license
* text
* lines
*/

With authors (and year; year defaults to current year):

>>> authors = [
...     {'name': 'Author Surname'},
...     {'name': 'Other Surname', 'email': 'test@email'},
... ]
>>> cw3 = CodeWriter()
>>> cw3.add_license_comment(
...     license_text, authors=authors, intro=intro_text, year=2019
... )
>>> print(cw3)
/*
* intro
* text
*
* Copyright © 2019 Author Surname
* Copyright © 2019 Other Surname <test@email>
*
* license
* text
* lines
*/
add_line(text=None, comment=None, ignore_indent=False)

Add a line of text to the container after the last line.

Parameters:
  • text (Optional[str]) – str to add

  • comment (Optional[str]) – optional comment

  • ignore_indent (bool) – switch to ignore indentation and insert the code with indentation 0

Raises:

ValueError – if text or comment isn’t a str

Return type:

None

add_lines(lines, ignore_indent=False)

Append code lines from an iterable or a multi-line str.

If lines is an iterable iterating over str objects, adds the lines to the codewriter in order.

If lines is a multi-line string, adds its lines to the codewriter.

Parameters:
  • lines (Union[Iterable[str], str]) – an Iterable of str or a multi-line str to add to codewriter.

  • ignore_indent (bool) – whether to ignore the current indentation level or not. If ignore_indent is true, the lines will be appended without indentation.

Raises:

ValueError – if one of the arguments is of the wrong type

Return type:

None

Examples

Adding a list of lines:

>>> from csnake import CodeWriter
>>> cwr = CodeWriter()
>>> lol = ['list', 'of', 'lines']
>>> cwr.add_lines(lol)
>>> print(cwr)
list
of
lines
add_struct(struct)[source]

Add a struct declaration.

Parameters:

struct (Struct) – struct in question

Return type:

None

See also

Struct for details on the Struct class.

Example

>>> from csnake import CodeWriter, Variable, Struct
>>> cw = CodeWriter()
>>> strct = Struct("strname", typedef=False)
>>> var1 = Variable("var1", "int")
>>> var2 = Variable("var2", "int", value=range(10))
>>> strct.add_variable(var1)
>>> strct.add_variable(var2)
>>> strct.add_variable(("var3", "int"))
>>> strct.add_variable({"name": "var4", "primitive": "int"})
>>> cw.add_struct(strct)
>>> print(cw)
struct strname
{
    int var1;
    int var2[10];
    int var3;
    int var4;
};
add_switch_break()[source]

Break a switch case.

Used with start_switch(), end_switch(), add_switch_case(), add_switch_default(), add_switch_return(), to form C switch statements.

Return type:

None

Examples

See start_switch().

add_switch_case(case=typing.Union[csnake.cconstructs.CExtendedLiteral, csnake.cconstructs.VariableValue], comment=None)[source]

Add a switch case statement.

Used with start_switch(), end_switch(), add_switch_default(), add_switch_break(), add_switch_return(), to form C switch statements.

Parameters:
  • case – literal or variable representing the current case’s value

  • comment (Optional[str]) – accompanying inline comment

Return type:

None

Examples

See start_switch().

add_switch_default(comment=None)[source]

Add a switch default statement.

Used with start_switch(), end_switch(), add_switch_case(), add_switch_break(), add_switch_return(), to form C switch statements.

Switch statements can be nested, so end_switch() closes the innermost switch.

Return type:

None

Examples

See start_switch().

add_switch_return(value=None)[source]

Return inside of a switch statement

Used with start_switch(), end_switch(), add_switch_case(), add_switch_default(), add_switch_break(), to form C switch statements.

Parameters:

value (Union[CExtendedLiteral, VariableValue, None]) – literal or variable representing the value to return

Return type:

None

Examples

See start_switch().

add_variable_declaration(variable, extern=False)[source]

Add a variable’s declaration.

Parameters:
  • variable (Variable) – variable in question

  • extern (bool) – wheter to add the extern qualifier to the

  • declaration (True) or not (False, default)

Return type:

None

See also

Variable for details on the Variable class

Examples

>>> import numpy as np
>>> from csnake import CodeWriter, Variable
>>> cw = CodeWriter()
>>> var = Variable(
...     "test",
...     primitive="int",
...     value=np.arange(24).reshape((2, 3, 4))
... )
>>> cw.add_variable_declaration(var)
>>> print(cw)
int test[2][3][4];
add_variable_initialization(variable)[source]

Add a variable’s initialization.

Parameters:

variable (Variable) – variable in question

Return type:

None

See also

Variable for details on the Variable class

Example

>>> import numpy as np
>>> from csnake import CodeWriter, Variable
>>> cw = CodeWriter()
>>> var = Variable(
...     "test",
...     primitive="int",
...     value=np.arange(24).reshape((2, 3, 4))
... )
>>> cw.add_variable_initialization(var)
>>> print(cw)
int test[2][3][4] = {
    {
        {0, 1, 2, 3},
        {4, 5, 6, 7},
        {8, 9, 10, 11}
    },
    {
        {12, 13, 14, 15},
        {16, 17, 18, 19},
        {20, 21, 22, 23}
    }
};
close_brace()

Add a closed brace and decrease indentation for subsequent lines.

See dedent() for more information on how dedentation is done.

Return type:

None

Examples

See open_brace().

property code: str

The contents of the codewriter rendered to a str, using lf as the linebreak.

Type:

str

cpp_entry()[source]

Start a conditional extern "C" for use CPP compilers.

Return type:

None

Examples

cpp_entry() and cpp_exit() in action:

>>> from csnake import CodeWriter
>>> cwr = CodeWriter()
>>> cwr.cpp_entry()
>>> cwr.add_line('some_code();')
>>> cwr.cpp_exit()
>>> print(cwr)
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
some_code();
#ifdef __cplusplus
}
#endif /* __cplusplus */
cpp_exit()[source]

End a conditional extern "C" for use CPP compilers.

Return type:

None

Examples

See cpp_entry().

dedent()

Decrease the indentation level by 1 unit.

Return type:

None

Examples

See indent().

end_comment(ignore_indent=False)

End a comment block.

A comment block previously started by start_comment() is ended. The following code is not inside a block comment.

Raises:

NoCommentStartError – if you attempt to end a comment block when a comment block hasn’t been started.

Examples

Return type:

None

See start_comment().

end_if_def(ignore_ifdef_stack=False)[source]

Insert an #endif to end a #ifdef (preprocessor) block.

#ifdef (or #ifndef) blocks can be nested. #endif always ends the innermost block. endif statements are added by end_if_def().

Parameters:

ignore_ifdef_stack (bool) – (optional) don’t throw an exception #endif if is unmatched.

Raises:
  • ValueError – if one of the arguments is of the wrong type.

  • DefStackEmptyError – if there isn’t a matching #ifdef and ignore_ifdef_stack isn’t set.

Examples

Return type:

None

See start_if_def().

end_switch(ignore_switch_stack=False)[source]

End a switch statement.

Used with start_switch(), add_switch_case(), add_switch_default(), add_switch_break(), add_switch_return(), to form C switch statements.

Switch statements can be nested, so end_switch() closes the innermost switch.

Parameters:

ignore_switch_stack (bool) – don’t throw an exception if a switch start is missing

Return type:

None

Raises:

SwitchStackEmptyError – if end_switch() is called outside of a

:raises switch statement, and ignore_switch_stack is False.:

Examples

See start_switch().

include(name, comment=None)[source]

Add an #include directive.

System headers should be surrounded with brackets (<>), while local headers may or may not be surrounded with quotation marks (“”) (the resulting code will have quotation marks surrounding the header’s name)

Parameters:
  • name (str) – name of header to include, with or without brackets/quotes. If no brackets/quotes surround the name, quotes are used by default.

  • comment (Optional[str]) – accompanying inline comment

Return type:

None

Examples

All types of includes.

>>> from csnake import CodeWriter
>>> cw = CodeWriter()
>>> cw.include('"some_local_header.h"')
>>> cw.include('other_local_header.h')
>>> cw.include("<string.h>")
>>> print(cw)
#include "some_local_header.h"
#include "other_local_header.h"
#include <string.h>
indent()

Increase the indentation level by 1 unit.

Return type:

None

Examples

indent() and dedent() in action:

>>> from csnake import CodeWriter
>>> cwr = CodeWriter()
>>> cwr.add_line('line_1;')
>>> cwr.indent()
>>> cwr.add_line('line_2;')
>>> cwr.add_line('line_3;')
>>> cwr.dedent()
>>> cwr.add_line('line_4;')
>>> print(cwr)
line_1;
    line_2;
    line_3;
line_4;
open_brace()

Add an open brace and increase indentation for subsequent lines.

See indent() for more information on how indentation is done.

Return type:

None

Examples

Using open_brace() and close_brace().

>>> from csnake import CodeWriter
>>> cwr = CodeWriter()
>>> cwr.add_line('line_1;')
>>> cwr.open_brace()
>>> cwr.add_line('line_2;')
>>> cwr.add_line('line_3;')
>>> cwr.close_brace()
>>> cwr.add_line('line_4;')
>>> print(cwr)
line_1;
{
    line_2;
    line_3;
}
line_4;
start_comment(ignore_indent=False)

Start a comment block.

All of the lines added after this are in a block comment, until the block is finished by end_comment().

Parameters:

ignore_indent (bool) – whether to ignore the indentation and just start the comment from the beginning of the next line.

Raises:

NestedCommentError – if you attempt to start a comment block when a comment block has already been started.

Examples

Return type:

None

Starting and ending a comment block with start_comment() and end_comment():

>>> from csnake import CodeWriter
>>> cwr = CodeWriter()
>>> cwr.add_line('line_1;')
>>> cwr.start_comment()
>>> cwr.add_line('line_2;')
>>> cwr.add_line('line_3;')
>>> cwr.end_comment()
>>> cwr.add_line('line_4;')
>>> print(cwr)
line_1;
/*
* line_2;
* line_3;
*/
line_4;
start_if_def(define, invert=False, comment=None)[source]

Start an #ifdef or #ifndef (preprocessor) block.

#ifdef (or #ifndef) blocks can be nested. #endif always ends the innermost block. endif statements are added by end_if_def().

Parameters:
  • define (str) – name of the macro whose existence we’re checking.

  • invert (bool) – (optional) whether this block is an #ifndef (True) or #ifdef (False, default).

  • comment (Optional[str]) – (optional) comment accompanying the statement.

Raises:

ValueError – if one of the arguments is of the wrong type.

Return type:

None

Examples

start_if_def() and end_if_def() in action, including nested ifdefs:

>>> from csnake import CodeWriter
>>> cwr = CodeWriter()
>>> cwr.start_if_def('DEBUG')
>>> cwr.start_if_def('ARM', invert=True)
>>> cwr.add_define('LOG')
>>> cwr.end_if_def()
>>> cwr.end_if_def()
>>> print(cwr)
#ifdef DEBUG
#ifndef ARM
#define LOG
#endif /* ARM */
#endif /* DEBUG */
start_switch(switch)[source]

Start a switch statement.

Used with end_switch(), add_switch_case(), add_switch_default(), add_switch_break(), add_switch_return(), to form C switch statements.

Switch statements can be nested, so end_switch() closes the innermost switch.

Parameters:

switch (Union[CExtendedLiteral, VariableValue]) – literal or variable the choice depends on.

Return type:

None

Examples

Demonstration of switch-related methods:

>>> from csnake import CodeWriter, Variable
>>> cw = CodeWriter()
>>> var = Variable("somevar", "int")
>>> case_var = Variable("case_var", "int")
>>> cw.start_switch(var)
>>> cw.add_switch_case(2)
>>> cw.add_line('do_something();')
>>> cw.add_switch_break()
>>> cw.add_switch_case(case_var)
>>> cw.add_switch_return(5)
>>> cw.add_switch_default()
>>> cw.add_switch_return(8)
>>> cw.end_switch()
>>> print(cw)
switch (somevar)
{
    case 2:
        do_something();
        break;
    case case_var:
        return 5;
    default:
        return 8;
} /* ~switch (somevar) */
write_to_file(filename)[source]

Write code to filename.

Parameters:

filename (Union[str, Path]) – name of the file to write code into

Return type:

None

zero_indent()

Set indentation level to zero.

Return type:

None

C language constructs

These classes describe C language constructs such as functions, variables, structs, …

They can be used on their own (by instantiating them and using their str() or other functions such as generate_declaration, generate_definition,… ) or via CodeWriter.

class csnake.Enum(name, prefix=None, typedef=False)[source]

Bases: object

Class describing C enum construct.

Parameters:
  • name (str) – name of the enum

  • prefix (Optional[str]) – prefix to add to every enumeration’s name

  • typedef (bool) – whether or not the enum is typedef’d

name

name of the enum

typedef

whether or not the enum is typedef’d

prefix

prefix to add to every enumeration’s name

values

list of Enum.EnumValue

class EnumValue(name, value=None, comment=None)[source]

Bases: object

Singular value of an C-style enumeration.

__str__()[source]

Return the declaration str (with indentation of 4 spaces).

Return type:

str

add_value(name, value=None, comment=None)[source]

Add a single name = value pair (or just name).

Return type:

None

add_values(values)[source]

Add multiple name = value pairs (or just names).

Values can be one of: :rtype: None

  • a dict with name : value entries

  • a collection of:
    • strs denoting names (no value)

    • dicts with keys [name, value, comment], and optional

      keys [value, comment]

    • collections (list-like) of length 1-3 denoting [name,

      value, comment] respectively

property declaration: str

The declaration str (with indentation of 4 spaces).

See also

generate_declaration() for the underlying method.

generate_declaration(indent=4)[source]

Generate enum declaration code.

Generate a CodeWriterLite instance containing the initialization code for this Enum.

Parameters:

indent (Union[int, str]) – indent str or int denoting the number of spaces for indentation

Return type:

CodeWriterLite

Examples

>>> from csnake import (
...     Enum, Variable, Dereference, AddressOf
... )
>>> name = "somename"
>>> pfx = "pfx"
>>> typedef = False
>>> enum = Enum(name, prefix=pfx, typedef=typedef)
>>> cval1 = Variable("varname", "int")
>>> enum.add_value("val1", 1)
>>> enum.add_value("val2", Dereference(1000))
>>> enum.add_value("val3", cval1)
>>> enum.add_value("val4", AddressOf(cval1), "some comment")
>>> print(enum.generate_declaration())
enum somename
{
    pfxval1 = 1,
    pfxval2 = *1000,
    pfxval3 = varname,
    pfxval4 = &varname /* some comment */
};
class csnake.Function(name, return_type='void', qualifiers=None, arguments=None)[source]

Bases: object

Class describing C function.

You can generate a function prototype (declaration), a definition or a call. A function’s body is a CodeWriterLite, so You can add lines of code to it (or a whole new CodeWriter instance).

Parameters:
  • name (str) – name of the function

  • return_type (str) – str containing function’s return type

  • qualifiers (Union[Iterable[str], str, None]) – str or Sequence of str listing the function’s qualifiers (const, volatile, …)

  • arguments (Optional[Iterable]) –

    an iterable which yields one the following types:

    • a Variable

    • a Collection (tuple/list-like) of 2 strings

      (name, primitive)

    • a Mapping (dict-like) with keys (name,

      primitive)

name

name of the function

return_type

str containing function’s return type

qualifiers

str or Sequence of str listing the function’s qualifiers (const, volatile, …)

arguments

an iterable which yields one the following types:

  • a Variable

  • a Collection (tuple/list-like) of 2 strings

    (name, primitive)

  • a Mapping (dict-like) with keys (name,

    primitive)

codewriter

internal instance of CodeWriterLite that contains

the funtion's body code.
add_argument(arg)[source]

Add an argument to function.

Arguments are added sequentially.

arg: an one the following types: :rtype: None

  • a Variable

  • a Collection (tuple/list-like) of 2 strings

    (name, primitive)

  • a Mapping (dict-like) with keys (name,

    primitive)

add_arguments(args)[source]

Add multiple arguments to function.

Arguments are added sequentially.

args: an iterable which yields one the following types: :rtype: None

  • a Variable

  • a Collection (tuple/list-like) of 2 strings

    (name, primitive)

  • a Mapping (dict-like) with keys (name,

    primitive)

add_code(code)[source]

Add a str or Iterable of strs to function’s body

Since a CodeWriter is an iterable of strs, you can simply add its contents to the function by passing it to this method.

Parameters:

code (Union[str, Iterable[str]]) – str or Iterable of strs to be added

Return type:

None

property definition: str

Function definition str.

See also

generate_definition() for the underlying method.

generate_call(*arg)[source]

Return function calling code for specific arguments.

Parameters:

*arg – argument values for call, in order of appearance.

Return type:

str

Doesn’t end with a semicolon (;).

Examples

>>> from csnake import Variable, Function
>>> arg1 = Variable("arg1", "int")
>>> arg2 = Variable("arg2", "int", value=range(10))
>>> arg3 = ("arg3", "int")
>>> arg4 = {"name": "arg4", "primitive": "int"}
>>> fun = Function(
...     "testfunct", "void", arguments=(arg1, arg2, arg3, arg4)
... )
>>> fun.add_code(("code;", "more_code;"))
>>> print(fun.generate_call(1, 2, 3, 4))
testfunct(1, 2, 3, 4)
generate_definition(indent='    ')[source]

Return a CodeWriterLite instance containing the definition code for this Function.

Parameters:

indent (Union[int, str]) – indent str or int denoting the number of spaces for indentation

Return type:

CodeWriterLite

Examples

>>> from csnake import Variable, Function
>>> arg1 = Variable("arg1", "int")
>>> arg2 = Variable("arg2", "int", value=range(10))
>>> arg3 = ("arg3", "int")
>>> arg4 = {"name": "arg4", "primitive": "int"}
>>> fun = Function(
...     "testfunct", "void", arguments=(arg1, arg2, arg3, arg4)
... )
>>> fun.add_code(("code;", "more_code;"))
>>> print(fun.generate_definition())
void testfunct(int arg1, int arg2[10], int arg3, int arg4)
{
    code;
    more_code;
}
generate_prototype(extern=False)[source]

Generate function prototype code.

Parameters:

extern (bool) – whether or not the function is to be declared as extern

Return type:

str

Doesn’t end with a semicolon (;).

Examples

>>> from csnake import Variable, Function
>>> arg1 = Variable("arg1", "int")
>>> arg2 = Variable("arg2", "int", value=range(10))
>>> arg3 = ("arg3", "int")
>>> arg4 = {"name": "arg4", "primitive": "int"}
>>> fun = Function(
...     "testfunct", "void", arguments=(arg1, arg2, arg3, arg4)
... )
>>> fun.add_code(("code;", "more_code;"))
>>> print(fun.generate_prototype())
void testfunct(int arg1, int arg2[10], int arg3, int arg4)
init_target_code(formatters=None)[source]

Return code used for variable initialization, formatted with the supplied formatters.

Parameters:

formatters (Optional[LiteralFormatters]) – collection of formatters used for formatting the initialization str

Return type:

str

property prototype: str

Function prototype (declaration) str.

Ends with a semicolon (;).

See also

generate_prototype() for the underlying method.

class csnake.Struct(name, typedef=False)[source]

Bases: object

Class describing C struct construct.

Parameters:
  • name (str) – name of struct

  • typedef (bool) – whether or not the struct is typedef’d

name

name of struct

typedef

whether or not the struct is typedef’d

variables

list of struct’s variables

__str__()[source]

Generate a str instance containing the declaration code for this Struct.

add_bit_field(bit_field)[source]

Add a bit field to struct.

Bit fields inside of a Struct are ordered (added sequentially). The order is synced with the add_variable() function.

see BitField for more information.

Parameters:

bit_field (BitField) – bit field to add.

add_variable(variable)[source]

Add a variable to struct.

Variables inside of a Struct are ordered (added sequentially). The order is synced with the add_bit_field() function.

Parameters:

variable (Union[Variable, Collection, Mapping]) –

variable to add. It can be defined in multiple ways.

variable can be:

  • a Variable

  • a Collection (tuple/list-like) of 2

    strs (name, primitive)

  • a Mapping (dict-like) with keys [‘name’,

    ’primitive’]

property declaration

CodeWriterLite instance containing the declaration code for this Struct.

See also

generate_declaration() for the underlying method.

generate_declaration(indent=4)[source]

Generate a CodeWriterLite instance containing the initialization code for this Struct.

Parameters:

indent (Union[int, str]) – indent str or int denoting the number of spaces for indentation

Return type:

CodeWriterLite

Example

>>> from csnake import BitField, Variable, Struct
>>> strct = Struct("strname", typedef=False)
>>> var1 = Variable("var1", "int")
>>> var2 = Variable("var2", "int", value=range(10))
>>> strct.add_variable(var1)
>>> strct.add_variable(var2)
>>> strct.add_variable(("var3", "int"))
>>> strct.add_variable({"name": "var4", "primitive": "int"})
>>> var5 = BitField("int", 2, name="var5")
>>> var6 = BitField("int", 3, comment="unused bits")
>>> var7 = BitField("int", 1, name="var7")
>>> strct.add_bit_field(var5)
>>> strct.add_bit_field(var6)
>>> strct.add_bit_field(var7)
>>> print(strct.generate_declaration())
struct strname
{
    int var1;
    int var2[10];
    int var3;
    int var4;
    int var5: 2;
    int : 3;  /* unused bits */
    int var7: 1;
};
class csnake.Variable(name, primitive, qualifiers=None, array=None, comment=None, value=None)[source]

Bases: object

Class describing C variable contruct.

You can generate declarations and initializations for variables, and variables can be initialized to very complex values (you can init an array variable to an array of struct containing arrays that contain structs, …).

The formatting of initialization strs can be altered by encasing some level of the initialization with a FormattedLiteral.

As for function values, the following (Python input → C code) translations are assumed (numpy and scipy ints and floats are considered ints and floats):

  • dictstruct literal

  • list or tuple → array literal

  • intint literal or int literal

  • floatfloat literal or double literal

  • boolbool literal or int literal

  • Variable → name of the variable

There is no type checking for initializations. That’s what your compiler is for, no sense in replicating such functionality here.

Parameters:
  • name (str) – name of the variable

  • primitive (Union[str, FuncPtr]) – str name or FuncPtr defining the variable’s type

  • qualifiers (Union[Iterable[str], str, None]) – str or Sequence of str listing the variable’s qualifiers (const, volatile, …)

  • array (Optional[Iterable]) – Sequence of int defining the dimensions of a (possibly multidimensional) array. If it’s left out, it’s inferred from value.

  • comment (Optional[str]) – accompanying comment

  • value (Optional[CLiteral]) – variable’s value, used for initialization. Explained in detail above

__str__()[source]

Initialization (if value in not None) or declaration str.

Falls back to declaration if value is None.

Ends with a semicolon (;).

See also

generate_initialization() for the initialization method. generate_declaration() for the declaration method.

property declaration: str

Declaration string.

Ends with a semicolon (;).

See also

generate_declaration() for the underlying method.

generate_declaration(extern=False)[source]

Return a declaration str.

Doesn’t end with a semicolon (;).

Parameters:

extern (bool) – whether or not the value is to be declared as extern

Return type:

str

Examples

>>> import numpy as np
>>> from csnake import Variable
>>> var = Variable(
...     "test",
...     primitive="int",
...     value=np.arange(24).reshape((2, 3, 4))
... )
>>> print(var.generate_declaration())
int test[2][3][4]
generate_initialization(indent=4)[source]

Return a CodeWriterLite instance containing the initialization code for this Variable.

Ends with a semicolon (;).

Parameters:

indent (Union[int, str]) – indent str or int denoting the number of spaces for indentation

Return type:

CodeWriterLite

Example

>>> import numpy as np
>>> from csnake import Variable
>>> var = Variable(
...     "test",
...     primitive="int",
...     value=np.arange(24).reshape((2, 3, 4))
... )
>>> print(var.generate_initialization())
int test[2][3][4] = {
    {
        {0, 1, 2, 3},
        {4, 5, 6, 7},
        {8, 9, 10, 11}
    },
    {
        {12, 13, 14, 15},
        {16, 17, 18, 19},
        {20, 21, 22, 23}
    }
};
init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

property initialization: str

Initialization str.

Ends with a semicolon (;).

See also

generate_initialization() for the underlying method.

class csnake.BitField(primitive, width, name=None, comment=None)[source]

Bases: object

Class describing C bit fields.

Bit fields in C are a way of packing variables into bits.

the C syntax is: type [name] : width ;

where
  • type is usually an integer type.

  • name is optional so we could have unnamed bits for padding..

  • width is the number of bits.

Note

This class made for declaring bit field specifics for use with Struct.add_bit_field().

Parameters:
  • name (Optional[str]) – (Optional) name of the bit field

  • width (int) – width of the bit field

  • primitive (str) – primitive type of the bit field

  • comment (Optional[str]) – accompanying comment

property declaration: str

Declaration string.

Ends with a semicolon (;). Includes the comment if present.

Variable initialization values

These classes help You modify the literals you’re using to initialize your variables.

class csnake.VariableValue[source]

Bases: object

Abstract base class for any initializer value based on a variable.

Sometimes we want to initialize a value to another variable, but in some more complicated manner: using the address-of operator, dereference operator, subscripting, typecasting… This is an ABC for those modifiers.

abstract __str__()[source]

Return str containing initialization code.

abstract init_target_code(formatters=None)[source]

Return code used for variable initialization, formatted with the supplied formatters.

Parameters:

formatters (Optional[LiteralFormatters]) – collection of formatters used for formatting the initialization str

class csnake.AddressOf(variable)[source]

Bases: VariableValue

Address of (&) VariableValue for variable initialization.

Subclass of VariableValue that returns an initialization string containing the & (address of) used on a value.

Parameters:

variable (VariableValue) – variable to return the address of.

variable

variable to return the address of.

Examples

>>> from csnake import Variable, AddressOf
>>> var1 = Variable("var1", "int")
>>> addrof_var1 = AddressOf(var1)
>>> var2 = Variable("var2", "int", value=addrof_var1)
>>> print(var2)
int var2 = &var1;
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

class csnake.Arrow(variable, item)[source]

Bases: VariableValue

Arrow (->) VariableValue for variable initialization.

Subclass of VariableValue that returns an initialization string for accessing a specific member of a struct indirectly (through a pointer).

Parameters:
  • variable (Union[CLiteral, VariableValue]) – variable whose member we’re accessing

  • member – name of member we’re accessing

variable

variable whose member we’re accessing

member

name of member we’re accessing

Examples

>>> from csnake import Variable, Arrow
>>> var1 = Variable("var1", "struct somestr")
>>> arrvar = Arrow(var1, 'some_member')
>>> var2 = Variable("var2", "int", value=arrvar)
>>> print(var2)
int var2 = var1->some_member;
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

class csnake.Dereference(value)[source]

Bases: VariableValue

Dereference (*) modifier for variable initialization.

Subclass of VariableValue that returns an initialization string containing the * (dereference) used on a value.

Parameters:

value (Union[CExtendedLiteral, VariableValue]) – value to dereference.

value

value to dereference.

Examples

>>> from csnake import Variable, Dereference
>>> var1 = Variable("var1", "int")
>>> derefd_var1 = Dereference(var1)
>>> var2 = Variable("var2", "int", value=derefd_var1)
>>> print(var2)
int var2 = *var1;
>>> derefd_number = Dereference(16)
>>> var3 = Variable("var3", "int", value=derefd_number)
>>> print(var3)
int var3 = *16;
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other values

Return type:

str

class csnake.Dot(variable, member)[source]

Bases: VariableValue

Dot (.) VariableValue for variable initialization.

Subclass of VariableValue that returns an initialization string for accessing a specific member of a struct.

Parameters:
  • variable (Union[CLiteral, VariableValue]) – variable whose member we’re accessing

  • member (str) – name of member we’re accessing

variable

variable whose member we’re accessing

member

name of member we’re accessing

Examples

>>> from csnake import Variable, Dot
>>> var1 = Variable("var1", "struct somestr")
>>> dotvar = Dot(var1, 'some_member')
>>> var2 = Variable("var2", "int", value=dotvar)
>>> print(var2)
int var2 = var1.some_member;
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

class csnake.GenericModifier(value, function)[source]

Bases: VariableValue

VariableValue generated by applying a function to a value.

A value’s initializer string is passed through the supplied function, which should return a str.

Parameters:
  • value (Union[CExtendedLiteral, VariableValue]) – value whose initializer we’re passing through a function

  • format_function – function used for modifying a value’s initializer

value

value whose initializer we’re passing through a function

format_function

function used for modifying a value’s initializer

Examples

>>> from csnake import Variable, GenericModifier
>>> var1 = Variable("var1", "int")
>>> genmod_var1 = GenericModifier(var1, lambda l: f'TRANSLATE({l})')
>>> var2 = Variable("var2", "int", value=genmod_var1)
>>> print(var2)
int var2 = TRANSLATE(var1);
>>> genmod_var2 = GenericModifier('test', lambda l: f'do_whatever({l})')
>>> var3 = Variable("var3", "int", value=genmod_var2)
>>> print(var3)
int var3 = do_whatever("test");
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

class csnake.OffsetOf(struct, member)[source]

Bases: VariableValue

offsetof VariableValue modifier for initializing to offsets of struct members.

Subclass of VariableValue that returns an initialization string containing the offset of a specific member of a struct.

Parameters:
  • struct (Union[Struct, str]) – struct whose member’s offset we’re using

  • member (Union[VariableValue, str]) – struct member whose offset we’re using

struct

struct whose member’s offset we’re using

member

struct member whose offset we’re using

Examples

>>> from csnake import Variable, OffsetOf, Struct
>>> offs_val1 = OffsetOf('struct some', 'some_member')
>>> var2 = Variable("var2", "int", value=offs_val1 )
>>> print(var2)
int var2 = offsetof(struct some, some_member);
>>> test_struct = Struct('other')
>>> offs_val2 = OffsetOf(test_struct, 'other_member')
>>> var3 = Variable("var3", "int", value=offs_val2 )
>>> print(var3)
int var3 = offsetof(struct other, other_member);
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

class csnake.Subscript(variable, subscript)[source]

Bases: VariableValue

Subscript ([]) modifier for variable initialization.

Subclass of VariableValue that returns an initialization string with a subscripted value.

Parameters:
  • variable (Union[CLiteral, VariableValue]) – variable to be typecast

  • subscript (Iterable) – a VariableValue or int or list or tuple of them representing the subscript[s].

variable

variable to be typecast

subscript

a VariableValue or int or list or tuple of them representing the subscript[s].

Examples

>>> from csnake import Variable, Subscript
>>> var1 = Variable("var1", "int")
>>> subscr1_var1 = Subscript(var1, 3)
>>> var2 = Variable("var2", "int", value=subscr1_var1)
>>> print(var2)
int var2 = var1[3];
>>> subscr2_var1 = Subscript(var1, (3, 2))
>>> var3 = Variable("var3", "int", value=subscr2_var1)
>>> print(var3)
int var3 = var1[3][2];
>>> subscr2_var1 = Subscript(var1, (var3, 2))
>>> var4 = Variable("var4", "int", value=subscr2_var1)
>>> print(var4)
int var4 = var1[var3][2];
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

class csnake.TextModifier(text)[source]

Bases: VariableValue

Generic textual VariableValue for initializing to an arbitrary str.

The str supplied as the argument is output verbatim as the Initialization string.

Parameters:

text (str) – initialization string

text

initialization string

Examples

>>> from csnake import Variable, TextModifier
>>> textmod1 = TextModifier('whatever + you + want')
>>> var2 = Variable("var2", "int", value=textmod1)
>>> print(var2)
int var2 = whatever + you + want;
>>> textmod2 = TextModifier(f'you_can_do_this_too + {var2.name}')
>>> var3 = Variable("var3", "int", value=textmod2)
>>> print(var3)
int var3 = you_can_do_this_too + var2;
__str__()[source]

Initialization string.

init_target_code(formatters=None)[source]

Return a str used for initialization of other Variables

Return type:

str

class csnake.Typecast(value, cast)[source]

Bases: VariableValue

Typecast modifier for variable initialization.

Subclass of VariableValue that returns an initialization string containing the typecast to type used on a value.

Parameters:
  • value (Union[CExtendedLiteral, VariableValue]) – value to be typecast

  • cast (str) – type to cast to

value

value to be typecast

cast

type to cast to

Examples

>>> from csnake import Variable, Typecast
>>> var1 = Variable("var1", "int")
>>> cast_var1 = Typecast(var1, 'long')
>>> var2 = Variable("var2", "int", value=cast_var1)
>>> print(var2)
int var2 = (long) var1;
>>> cast_number = Typecast(16, 'long')
>>> var3 = Variable("var3", "int", value=cast_number)
>>> print(var3)
int var3 = (long) 16;
__str__()[source]

Initialization string.

Return type:

str

init_target_code(formatters=None)[source]

Return a str used for initialization of other values

Return type:

str

class csnake.FormattedLiteral(value, *args, **kwargs)[source]

Bases: object

A C literal with its formatter collection altered.

The accompanying literal formatter collection will be used when generating the initialization str.

Parameters:

**kwargs – keyword arguments for each of the formatters in [‘int_formatter’, ‘float_formatter’, ‘bool_formatter’, ‘string_formatter’] we want to change for this literal. Every missing formatter is inherited from the literal (or default).

value

value of literal

formatter

collection of literal formatters

Variable value literal formatters

You can specify formatters which are used to modify the way literals are printed by encasing your Variable’s value with a FormattedLiteral with the some formatters given by keyword arguments (see FormattedLiteral for details).

These are some format functions used by default by csnake:

csnake.simple_bool_formatter(value)[source]

Simple formatter that turns a bool into ‘true’ or ‘false’.

Parameters:

value (bool) – boolean to format

Return type:

str

Returns:

str’s ‘true’ or ‘false’

csnake.simple_str_formatter(value)[source]

Simple formatter that surrounds a str with quotes.

Parameters:

value (str) – string to format

Return type:

str

Returns:

str that’s the input string surrounded with double quotes

Variable type declaration helpers

These classes help you declare complex types for use as Variable’s type.

class csnake.FuncPtr(return_type, arguments=None)[source]

Bases: object

Class describing function pointer args and return type.

This class made for declaring function pointer type specifics for use with Variables as their type argument.

Parameters:
  • return_type (str) – str containing the return type

  • arguments (Optional[Iterable]) –

    an iterable which yields one the following types:

    • a Variable

    • a Collection (tuple/list-like) of 2 strings

      (name, primitive)

    • a Mapping (dict-like) with keys (name,

      primitive)

get_declaration(name, qualifiers=None, array=None)[source]

Generate the whole declaration str according to parameters.

This method is meant to be called from Variable.generate_declaration() and Variable.generate_initialization() function and is probably useless to You elsewhere.

Return type:

str

Extra variable value conversion modules

These submodules contain functions to convert more complicated types (like PIL Images, for instance) to types that can be used as initializers.

Module pil_converter

Module for conversion of PIL images to lists for variable initialization.

csnake.pil_converter.pil_image_to_list(image, outformat='ARGB8888')[source]

Convert a PIL image into an a list of ints.

Conversion is done from the Image.tobytes() to list of int, based on the format given by the argument format.

The main purpose of this is to turn Images into nested lists, which can be used as array initialization values by :class: csnake.variable.

image’s format is extracted from the image itself and there is only a limited number of conversions available. While the input format is fixed, the output format is supplied by outformat.

Here are the supported mappings of formats (PIL Image.mode → output format):

  • RGB → RGB888

  • RGB → RGB565

  • RGBA → ARGB888

  • L → A8

Parameters:
  • image (Image) – PIL or Pillow Image to be turned into array.

  • outformat (str) – Format of int’s in the output array.

Return type:

List[List[int]]

Returns:

list of list of int for pixels of the image

Raises:
  • TypeError – If the image arg passed isn’t a PIL Image.

  • ValueError – If the conversion between the listed formats isn’t possible.

Examples

>>> from csnake.pil_converter import pil_image_to_list
>>> from csnake import CodeWriter, Variable, FormattedLiteral
>>> from PIL import Image, ImageDraw
>>> im = Image.new('RGB', (3, 3))
>>> dr = ImageDraw.Draw(im)
>>> dr.line((0,0) + im.size, fill = '#8CAFAF')
>>> im_ls = pil_image_to_list(im, "RGB888")
>>> print(im_ls)
[[9220015, 0, 0], [0, 9220015, 0], [0, 0, 9220015]]
>>> var = Variable(
...     "pic",
...     primitive="int",
...     value=FormattedLiteral(im_ls, int_formatter=hex),
... )
>>> cw = CodeWriter()
>>> cw.add_variable_initialization(var)
>>> print(cw)
int pic[3][3] = {
    {0x8cafaf, 0x0, 0x0},
    {0x0, 0x8cafaf, 0x0},
    {0x0, 0x0, 0x8cafaf}
};