Class Reference

This page describes some miscellaneous classes you may encounter while developing esc plugins and want to know more about. This is not an exhaustive reference to all of esc’s classes; for details on classes that plugin developers do not come into contact with, you’ll want to dive into the source.

EscCommands

Anything that shows up on the Commands menu has an associated instance of EscCommand. EscCommand is subclassed as follows:

Inheritance diagram of esc.commands, esc.builtin_stubs

EscCommand subclasses

class esc.commands.EscCommand(key, description)[source]

Base class for some esc functionality or operation the user can activate.

When the user activates this item, execute() is called. Execution takes any action associated with the item, throwing an exception if something didn’t work right. It then returns the menu that the interface should return to. A return value of None returns to the main menu.

children = None

Mapping from keys to EscCommands on the current menu, if this is a menu. Add to this using register_child(), not directly.

description = None

How this item is described on its parent menu.

execute(access_key, ss, registry)[source]

Execute this EscCommand. For operations or builtins, this involves the class doing its own work; for menus, this returns the child defined by access_key.

Returns:An instance of EscCommand representing the menu the UI should now return to, or None to indicate the main menu.
help_title

The title this command should show in the help system. This is the access key and description if a description is defined; otherwise it is just the access key.

key = None

The key used to activate this item on its parent menu.

parent = None

An EscCommand (hopefully a menu) this item is contained in.

register_child(child)[source]

Register a new child EscCommand of this menu (either a menu or an operation). This operation doesn’t make sense for EscOperation instances; the caller should avoid doing this.

signature_info

An iterable of strings to display under the “Signature” section in help.

simulated_result(ss, registry)[source]

Execute this command against the given stack state and registry, but instead of actually changing the state, return a string describing the result.

May return None if the EscCommand does not change the stack state (e.g., a menu).

test()[source]

Execute any self-tests associated with this EscCommand. If a test fails, raise a ProgrammingError.

class esc.commands.EscMenu(key, description, doc, mode_display=None)[source]

Bases: esc.commands.EscCommand

A type of EscCommand that serves as a container for other menus and operations. Executing it activates a child item.

anonymous_children

Iterable of children without a description.

child(access_key)[source]

Return the child defined by access_key. Raises NotInMenuError if it doesn’t exist.

execute(access_key, ss, registry)[source]

Look up the child described by access_key and execute it. If said child is a menu, return it (so the user can choose an item from that menu). Otherwise, execute the child immediately.

Parameters:
  • access_key – A menu access key indicating which child to execute.
  • ss – The current stack state, passed through to a child operation.
  • registry – The current registry, passed through to a child operation.
Returns:

The EscMenu to display next, or None to return to the main menu. This will be a child menu, if one was selected, or None if an operation runs.

Raises:

FunctionExecutionError or a subclass, if a child operation was selected but does not complete successfully.

If the user chose the special quit command, return to the previous menu, or raise SystemExit if this is the main menu.

is_main_menu

This is the main menu if it has no parent.

mode_display = None

An optional callable whose return value will be shown under the menu title.

named_children

Iterable of children with a description.

signature_info

Constant string that describes the menu as a menu.

test()[source]

Execute the test method of all children.

class esc.commands.EscOperation(key, func, pop, push, description, menu, retain=False, log_as=None, simulate=True)[source]

Bases: esc.commands.EscCommand

execute(access_key, ss, registry)[source]

Execute the esc operation wrapped by this instance on the given stack state and registry.

Parameters:
  • access_key – Not used by this subclass.
  • ss – The current stack state, passed through to a child operation.
  • registry – The current registry, passed through to a child operation.
Returns:

A constant None, indicating that we go back to the main menu.

Raises:

FunctionExecutionError or a subclass, if the operation cannot be completed successfully.

function = None

The function, decorated with @Operation, that defines the logic of this operation.

log_as = None

A description of how to log this function’s execution (see the docs for @Operation for details on allowable values).

pop = None

The number of items the function gets from the bottom of the stack. -1 indicates the entire stack is popped.

push = None

The number of items the function returns to the stack. -1 indicates a variable number of items will be returned.

retain = None

If true, items pulled from the stack before execution won’t be removed.

signature_info

A description of the function’s signature as a tuple of strings (one per line to display in the help system), based on the pop and push values.

simulate_allowed = None

Whether this function should be run when a simulation is requested for help purposes. Turn off if the function is slow or has side effects.

simulated_result(ss, registry)[source]

Execute the operation on the provided StackState, but don’t actually change the state – instead, provide a description of what would happen.

test()[source]

If the function on this EscOperation has associated TestCases defined in its tests attribute, execute those tests.

class esc.commands.EscBuiltin[source]

Bases: esc.commands.EscCommand

Mock class for built-in commands. Built-in EscCommands do not actually get run and do anything – they are special-cased because they need access to internals normal commands cannot access. However, it’s still useful to have classes for them as stand-ins for things like retrieving help.

Unlike the other EscCommands, each EscBuiltin has its own subclass rather than its own instance, as they each need special behaviors. The subclasses are defined in the builtin_stubs module.

Subclasses should override the docstring and the simulated_result() method.

Subclasses should also define key and description as class variables. They’ll be shadowed by instance variables once we instantiate the class, but the values will be the same. That sounds dumb, but it makes sense for all other classes in the hierarchy and doesn’t hurt us here. We don’t want to define them in the __init__ of each subclass because then we have to instantiate every class to match on them by key (see the reflective search in esc.helpme).

execute(access_key, ss, registry)[source]

Executing a builtin does nothing.

signature_info

Constant string that describes the built-in as a built-in.

simulated_result(ss, registry)[source]

Reimplemented by each subclass.

test()[source]

Testing a builtin with esc’s function test feature does nothing.

Loading EscCommands

EscCommands are loaded by the function_loader:

function_loader.py - load esc functions from builtins and plugins onto menus

esc.function_loader.load_all()[source]

Load built-in and user functions files. This will execute the constructors in the functions files, which will (if these files are written correctly) ultimately register the functions onto main_menu. This method needs to be called only once at application startup.

The function loader imports the built-in functions file and any function files in your user config directory. Importing a function file causes calls to the constructors in EscCommand to be run (Operation(), Menu(), Constant(), Mode(), and ModeChange()), and these constructors in turn create EscCommand instances which are added to the children attribute of the main menu or a submenu of the main menu.

StackItems

StackItems are used to represent each number entered onto the stack. Typically, you can request a Decimal or string representation of the stack item in your operation functions (see the documentation on parameter binding in Operation for details). If you need both in one function, you may want to work with the full object:

class esc.stack.StackItem(firstchar=None, decval=None)[source]

An item placed on esc’s stack. At its root, this is a number, but it gets more complicated than that!

For one, we need a numeric value for calculations as well as a string value to display on the screen. The method finish_entry() updates the numeric representation from the string representation. We could dynamically compute the string representation with reasonable performance, but see the next paragraph for why this isn’t helpful.

For another, a stack item may be incomplete (is_entered attribute = False). That’s because the user doesn’t enter a number all at once – it will typically consist of multiple keystrokes. If so, there won’t be a decimal representation until we call finish_entry(). The StackState is in charge of calling this method if needed before trying to do any calculations with the number.

Note

By the time you receive a StackItem in a plugin function, is_entered should always be False, so many of the following methods will not be applicable.

add_character(nextchar)[source]

Add a character to the running string of the number being entered on the stack. Calling add_character() is illegal and will raise an AssertionError if the number has already been entered completely.

Returns:True if successful, False if the stack width (esc.consts.STACKWIDTH) has been exceeded.
backspace(num_chars=1)[source]

Remove the last character(s) from the string being entered. Calling backspace() is illegal and will raise an AssertionError if the number has already been entered completely.

decimal = None

Decimal representation. This is None if is_entered is False.

finish_entry()[source]

Signal that the user is done entering a string and it should be converted to a Decimal value. If successful, return True; if the entered string does not form a valid number, return False. This should be called only by the enter_number method of StackState.

is_entered = None

Whether the number has been fully entered. If not entered, many methods will not work as we don’t have a Decimal representation yet.

string = None

String representation.

Registry

In general, you should prefer working solely with the stack when writing operations, rather than accessing registers; operations that use registers are harder to write and harder for users to understand, and any changes made to registers can’t be undone. (Working through the undo/redo history will still deliver the correct values to the stack, since undoing and redoing restores past states rather than doing the calculations again, but history entries might not match the current values of registers anymore, and changes your operation makes to registers won’t be undone/redone.)

However, sometimes it may be useful to use registers as parameters or even as outputs in special-purpose custom operations. You should do this only if you fully understand the consequences as described in the previous paragraph! In this case, you can provide a parameter called registry, and you will receive the following object:

class esc.registers.Registry[source]

The Registry stores the values of esc registers. It’s basically a fancy dictionary with some validation and a display-sorted items() method.

__contains__(value)[source]
__delitem__(key)[source]
__getitem__(key)[source]
__len__()[source]
__setitem__(key, value)[source]

Set the value of a register.

Raises:InvalidNameError if the key (register name) isn’t valid.
static _valid_name(name: str)[source]

A key (register name) is valid if it’s exactly one alphabetic character.

items()[source]

Return an iterable of items, sorted by register key.

values()[source]

Warning

If you set a register in your operation, be sure to turn the simulate <esc.commands.Operation.simulate> option off in your Operation decorator, or users may end up inadvertently setting registers when viewing the help for your function.

Exceptions

The most important exceptions are described (and indexed) in the context where you need to deal with them, but here is the complete hierarchy for reference.

Inheritance diagram of EscError, FunctionExecutionError, InsufficientItemsError, ProgrammingError, FunctionProgrammingError, InvalidNameError, NotInMenuError
class esc.oops.EscError[source]

Base application exception for esc. Don’t raise directly.

class esc.oops.FunctionExecutionError[source]

A broad exception type that occurs when the code within an operation function couldn’t be executed successfully for some reason. Examples include:

  • a number is in the middle of being entered and isn’t a valid number
  • a function performed an undefined operation like dividing by zero
  • there are too many or too few items on the stack
  • a function directly raises this error due to invalid input or inability to complete its task for some other reason

FunctionExecutionErrors normally result in the __str__ of the exception being printed to the status bar, so exception messages should be concise.

A FunctionExecutionError may be raised directly, or one of its subclasses may be used.

class esc.oops.InsufficientItemsError(number_required, msg=None)[source]

Raised directly by operations functions that request the entire stack to indicate not enough items are on the stack to finish their work, or by the menu logic when an operation requests more parameters than items on the stack.

Functions may use the simplified form of the exception, providing an int describing the number of items that should have been on the stack for the number_required constructor parameter. esc will then reraise the exception with a more useful message; a fallback message is provided in case this doesn’t happen for some reason.

class esc.oops.ProgrammingError[source]

Indicates an error caused by incorrectly written or defined esc plugins. This includes modes, menus, operations, and so on. It does not include runtime errors within operation functions themselves; these are FunctionExecutionErrors.

class esc.oops.FunctionProgrammingError(operation, problem)[source]

A more specific type of ProgrammingError that occurs when a user’s @Operation decorator or function parameters are invalid or function tests fail.

The distinction is mostly for convenience within esc’s codebase rather than because client code needs to tell the difference from other ProgrammingErrors; this class wraps some handy logic for generating a standardized message.

class esc.oops.InvalidNameError[source]

Raised when the user chooses an invalid name for a register or other label.

class esc.oops.NotInMenuError(access_key)[source]

Raised when a keypress is parsed as a menu option or a menu’s children are programmatically accessed by key, but the key doesn’t refer to any choice on the current menu. Describes the problem in a message that can be printed to the status bar.