puzzlepiece.extras.hardware_tools module

puzzlepiece.extras.hardware_tools.debug_prompt(force_terminal=False)[source]

Display a prompt asking the user whether to launch the Puzzle in debug mode. If a QApplication exists, this will be a GUI prompt, otherwise Launch Puzzle in debug mode? (Y/n) is shown in the terminal. Returns False if the user types anything starting with “n” (n/no/No/N etc.), otherwise returns True. The GUI prompt can also be cancelled, which raises an Exception to halt the launch.

This is useful in __main__ declaration in Piece files, so that the same file can be run directly and used for testing both debug and non-debug operation, but changes to the debug flag don’t get checked into version control:

if __name__ == "__main__":
    app = pzp.QApp()
    puzzle = pzp.Puzzle(name="Template", debug=pht.debug_prompt())
    puzzle.add_piece("template", Piece, row=0, column=0)
    puzzle.show()
    app.exec()
Parameters:

force_terminal – Skip the QApplication check and always prompt in the terminal, not the GUI.

Return type:

bool

puzzlepiece.extras.hardware_tools.config(key, *, default=None, description=None, validator=None)[source]

Obtain a config value (specific to the calling file) for a given key. If a saved value is not present, prompt the user for one with the given description. A validator function can be given, which should raise an exception if the user input value is not valid (the validator is not used to test already stored values).

The config files use the INI format and are placed alongside the calling Python file. For example, if config is called in camera.py, it will create camera.config next to camera.py.

The method enables storing local configuration files for installation-specific things like DLL directories. For example:

from puzzlepiece.extras import hardware_tools as pht
dll_directory = pht.config(
    "thorcam_dll_directory",
    default="C:/DLLs",
    validator=pht.validator_path_exists
)
Parameters:
  • key – The config key name to retrieve/save

  • default (Any) – A default value for the key, the user can accept it by pressing enter

  • description (str) – A description that will be shown along with the input prompt

  • validator (Callable) – A function that checks if the user input is valid (should raise an exception if not)

Returns:

The stored/saved value

puzzlepiece.extras.hardware_tools.validator_path_exists(name)[source]

Raise a FileNotFoundError if the provided path (directory or file) does not exist. Can be used as a validator for puzzlepiece.extras.hardware_tools.config().

Parameters:

name (str) – Path to a directory or file

Return type:

None

puzzlepiece.extras.hardware_tools.requirements(packages_spec)[source]

Indicate that some Python packages are required to proceed. Can be used to implement per-file requirements for larger automation suites - the user may not have to install all the packages, but some are required for running specific files. Calls to this method are also parsed to indicate Piece requirements in https://pzp-hardware.readthedocs.io

When called, this function will stop script execution and inform the user that a package is required. The next steps depend on the specification provided in packages_spec. If it’s a simple list of package names, requirements will raise a ModuleNotFoundError if any of them are not installed. If packages_spec is a dictionary with installation instructions, the user will be asked whether they want to automatically install the package with pip (which will use the current Python executable to install into the right virtual environment), or online installation instructions will be opened.

For example, in a Piece’s setup() method:

def setup(self):
    pht.requirements({
        "thorlabs_tsi_sdk": {
            # This will just open installation instructions in a browser and raise ModuleNotFoundError
            "url": "https://pzp-hardware.readthedocs.io/en/latest/auto/pzp_hardware.thorlabs.camera.html#installation"
        },
        "PIL": { # the name of the package, as in "import PIL"
            "pip": "pillow", # the PyPI name of the package, as in "pip install pillow"
            # If pip installation fails or is not chosen by the user, open installation instructions
            "url": "https://pillow.readthedocs.io/en/stable/installation/basic-installation.html",
        }
    })

    # This will indicate requirements but not help the user install them:
    pht.requirements(["thorlabs_tsi_sdk", "PIL"])

    # Once we ensure the requirements are installed, we can import them:
    import thorlabs_tsi_sdk
Parameters:

packages_spec (dict | List[str]) – The specification for the required packages

Return type:

None

puzzlepiece.extras.hardware_tools.add_path_directory(directory)[source]

Add the directory provided to the PATH. This will add both to the system path and the Python search path for the current Python session.

Parameters:

directory (str) – The directory to add to the PATH. Can be relative.

Return type:

None

puzzlepiece.extras.hardware_tools.add_dll_directory(directory)[source]

Add the directory provided to the PATH as in add_path_directory(), but also to the allowed DLL directory list (using os.add_dll_directory). This is needed since Python 3.8 for your DLLs to be found and used.

Parameters:

directory (str) – The directory to add to the PATH. Can be relative.

Return type:

None

puzzlepiece.extras.hardware_tools.load_dll(path, fallback=None)[source]

Load a DLL from a path. Also calls add_dll_directory() for you. Returns a ctypes WinDLL object.

Installation instructions can be provided for the user in the form of the fallback dictionary. These are shown if the DLL load fails in any way, along with the exception. A message can be printed in the console, and/or installation instructions opened in the default browser.

Example usage:

from puzzlepiece.extras import hardware_tools as pht
pht.load_dll(
    dll_path,
    fallback = {
        "message": "This Piece requires the ThorLabs APT DLLs.",
        "url": "https://example.org",
    }
)
Parameters:
  • path (str) – Path to the DLL to load

  • fallback (dict) – A dictionary of instructions for the user to install the DLL. Currently supports “message” and “url” as keys.

Return type:

c.WinDLL

puzzlepiece.extras.hardware_tools.dll_methods(path)[source]

Use pefile to return a list of function names for a DLL given as a path. Can be used to inspect the methods exposed by a manufacturer’s DLL, useful during initial exploration when developing a hardware Piece. Does not parse method arguments or return types, the manufacturer’s manual needs to be consulted for these.

pefile is an optional dependency, it can be installed with pip install pefile, or at runtime, as it is required with requirements().

Parameters:
  • str – Path to the DLL.

  • path (str) –

Returns:

A list of method names exposed by the DLL.

Return type:

List[str]

puzzlepiece.extras.hardware_tools.load_dll_with_methods(path)[source]

Use load_dll() to load a DLL from a path, and dll_methods() to get the methods it exposes. Both are returned.

Additionally, the returned WinDLL will have the methods saved in its __dir__, meaning that they are available for autocompletion in IPython. This is particularly useful in early development, making inspection of available methods easier.

pefile is an optional dependency, it can be installed with pip install pefile, or at runtime, as it is required with requirements().

Parameters:
  • str – Path to the DLL.

  • path (str) –

Return type:

Tuple[c.WinDLL, List[str]]