Configuration

CFiddle has a few personalities depending on how it’s run.

Running Under Jupyter

CFiddle will automatically detect if it’s running under Jupyter Notebook/Lab, but you can enable the mode mannually. This includes interacive mode (see below).

When CFiddle detects a user error (e.g., code that does not compile), it raises an exeception and CFiddle tries to provide a useful error message. These errors will be more readable (i.e., they will not print the mostly-useless stack trace) with if you invoke

%xmode Minimal

in the notebook. There doesn’t seem to be a safe way to do this is from inside CFiddle.

cfiddle.jupyter.configure_for_jupyter()

Set things up to run under Jupyter Notebook/lab

This turns on Jupyter-aware progress bars. It also enables Jupyter-aware formatting for extracting source code, assembly, etc.

Error Reporting

By default CFiddle raises instances of CFiddleException for all errors and hides the internal stack trace. You can expose it with enable_debug()

cfiddle.enable_debug(enable=True)

Put CFiddle into debugging mode.

Parameters:

enable – New value for the internal debug mode flag. True mean debug is enabled. Defaults to True.

Limiting Configuration Scope

CFiddle maintains a stack of configuration environments.

You can limit the impact of a configuration change by using a with statement an cfiddle_config(). It pushes a copy of the current configuration onto the stack and pops it off at the end of the with.

cfiddle.cfiddle_config(**kwargs)

Create a local configuration context.

Any configuration changes made inside this context will be undone after the context completes.

For example:

>>> from cfiddle import *
>>> get_config("DEBUG_MODE")
False
>>> with cfiddle_config():
...    enable_debug()
...    print(get_config("DEBUG_MODE"))
True
>>> print(get_config("DEBUG_MODE"))
False

You can also set parmeters in the current configuration with set_config() and query the current configuration with get_config().

cfiddle.config.set_config(k, v)

Set a configuration values.

Parameters:
  • k – The name of the configuration variable.

  • v – The value.

cfiddle.config.get_config(k)

Query a configuration values.

Parameters:

k – The name of the configuration variable.

Returns:

The value in the current configuration.

Controlling the Code’s Execution Environment

You can control the execution environment for the code using the run_options paremeter to run(). It takes a dictionary that’s passed to an implementation of RunOptionIntepreter specified by the RunOptionInterpreter_type configuration option.

That should be context manager that sets up the execution environment. RunOptionInterpreter just adds the values in run_options to the environment.

The default just adds run_options as environment variables.

class cfiddle.Runner.RunOptionInterpreter(options)

Interpret the contents of the run_options argument to cfiddle.run().

This is a context manager. The base class implementation just copies the values into environment variables. Subclasses or substitutions could implement other behavior.

Setting Defaults for Building and Running

You set defaults for build_parameters, run_options, and perf_counters to avoid setting them repeatedly.

The corresponding configuration options are perf_counters_default, build_parameters_default, and run_options_default. You can set them using cfiddle.cfiddle_config():

>>> from cfiddle import  *
>>> sample = code(r"""void nothing(){}""")
>>> with cfiddle_config(build_parameters_default=arg_map(OPTIMIZE="-O3")):
...    b = build(code(r"""void nothing() {}"""))

Controlling How CFiddle Runs Code

Usually CFiddle runs your code in a separate process using Runner. You can modify this behavior by creating an alternative implementation of Runner and setting the Runner_type configuration option accordingly.

CFiddle includes DirectRunner which will run your code in the current Python process (which means a segfault in your code will take out Python).

class cfiddle.Runner(invocations, invoker=None, result_factory=None, result_list_factory=None, progress_bar=None)

Runs a set of InvocationDescription instances to produce to InvocationResults.

Execution occurs in a separate process to protect the python interpreter from misbehaving functions (e.g., segmentation faults).

This works by pickling this object, and invoking the cfiddle-run command line tool to unpickle this object, run the invocations, and then pickle and return the results.

The cfiddle-run command line is passed to :class:SubprocessDelegate` which runs with Python’s subprocess.run().

You can change this behavior by setting the RunnerDelegate_type configuration option. For instance, a replacement could submit the commandline to job scheduling system or execute it remotely via ssh.

Creating a subclass allows for other execution methods. Notably, DirectRunner runs the function in the current Python process, which can be useful in some instances.

class cfiddle.DirectRunner(invocations, invoker=None, result_factory=None, result_list_factory=None, progress_bar=None)

Run code in the current Python process instead of a separate process.

You can use it like so:

>>> from cfiddle import  *
>>> sample = code(r'''
... #include <cfiddle.hpp>
... extern "C"
... int loop(int count) {
...        int sum = 0;
...    for(int i = 0; i < count; i++) {
...       sum += i;
...    }
...    return sum;
... }
... ''')
>>> exes = build(sample)
>>> with cfiddle_config(Runner_type=DirectRunner):
...    results = run(exes, "loop", arguments=arg_map(count=[1]))