Project Structure Representation

Each Python package project is internally represented by PyScaffold as a tree data structure, that directly relates to a directory entry in the file system. This tree is implemented as a simple (and possibly nested) dict in which keys indicate the path where files will be generated, while values indicate their content. For instance, the following dict:

{
    "folder": {
        "file.txt": "Hello World!",
        "another-folder": {
            "empty-file.txt": ""
        }
    }
}

represents a project directory in the file system that contains a single directory named folder. In turn, folder contains two entries. The first entry is a file named file.txt with content Hello World! while the second entry is a sub-directory named another-folder. Finally, another-folder contains an empty file named empty-file.txt.

Note

Changed in version 4.0: Prior to version 4.0, the project structure included the top level directory of the project. Now it considers everything under the project folder.

Additionally, tuple values are also allowed in order to specify a file operation (or simply file op) that will be used to produce the file. In this case, the first element of the tuple is the file content, while the second element will be a function (or more generally a callable object) responsible for writing that content to the disk. For example, the dict:

from pyscaffold.operations import create

{
    "src": {
        "namespace": {
            "module.py": ('print("Hello World!")', create)
        }
    }
}

represents a src/namespace/module.py file, under the project directory, with content print("Hello World!"), that will written to the disk. When no operation is specified (i.e. when using a simple string instead of a tuple), PyScaffold will assume create by default.

Note

The create function simply creates a text file to the disk using UTF-8 encoding and the default file permissions. This behaviour can be modified by wrapping create within other fuctions/callables, for example:

from pyscaffold.operations import create, no_overwrite

{"file": ("content", no_overwrite(create))}

will prevent the file to be written if it already exists. See pyscaffold.operations for more information on how to write your own file operation and other options.

Finally, while it is simple to represent file contents as a string directly, most of the times we want to customize them according to the project parameters being created (e.g. package or author’s name). So PyScaffold also accepts string.Template objects and functions (with a single dict argument and a str return value) to be used as contents. These templates and functions will be called with PyScaffold's options when its time to create the file to the disk.

Note

string.Template objects will have safe_substitute called (not simply substitute).

This tree representation is often referred in this document as project structure or simply structure.