# Basic workflow The `editables` project is designed to support *build backends*, allowing them to declare what they wish to expose as "editable", and returning a list of support files that need to be included in the wheel generated by the `build_editable` [backend hook](https://peps.python.org/pep-0660/#build-editable). Note that the `editables` library does not build wheel files directly - it returns the content that needs to be added to the wheel, but it is the build backend's responsibility to actually create the wheel from that data. ## Create a project The first step is for the backend to create an "editable project". The project name must follow the normal rules for Python project names from [PEP 426](https://peps.python.org/pep-0426/#name). ```python project = EditableProject("myproject") ``` ## Specify what to expose Once the project has been created, the backend can specify which files should be exposed when the editable install is done. The following mechanisms are currently implemented for this. ### Adding a directory to `sys.path` To add a particular directory (typically the project's "src" directory) to `sys.path` at runtime, simply call the `add_to_path` method ```python project.add_to_path("src") ``` This will simply write the given directory into the `.pth` file added to the wheel. See the "Implementation Details" section for more information. ### Adding a directory as package content To expose a directory as a package on `sys.path`, call the `add_to_subpackage` method, giving the package name to use, and the path to the directory containing the contents of that package. For example, if the directory `src` contains a package `my_pkg`, which you want to expose to the target interpreter as `some.package.my_pkg`, run the following: ```python project.add_to_subpackage("some.package", "src") ``` Note that everything in the source directory will be available under the given package name, and the source directory should *not* contain an `__init__.py` file (if it does, that file will simply be ignored). Also, the target (`some.package` here) must *not* be an existing package that is already part of the editable wheel. This is because its `__init__.py` file will be overwritten by the one created by this method. # Mapping individual files/packages To expose a single `.py` file as a module, call the `map` method, giving the name by which the module can be imported, and the path to the implementation `.py` file. It *is* possible to give the module a name that is not the same as the implementation filename, although this is expected to be extremely uncommon. ```python project.map("module", "src/module.py") ``` To expose a directory with an `__init__.py` file as a package, the `map` method is used in precisely the same way, but with the directory name: ```python project.map("mypackage", "src/mypackage") ``` The directory *must* be a Python package - i.e., it must contain an `__init__.py` file, and the target package name must be a top-level name, not a dotted name. The `map` method does *not* support mapping implicit namespace packages (directories which do not contain an `__init__.py` file). There are two different ways that the `map` method can be implemented at runtime. To choose which one to use, set the `map_method` attribute on your `EditableProject` instance. The two methods are `import_hook` (the default) and `self_replace`. For details on the differences between the two methods, see the "Implementation Details" section of the documentation. Using the `map` method with the `import_hook` method requires a runtime support module. ## Build the wheel ### Files to add Once all of the content to expose is specified, the backend can start building the wheel. To determine what files to write to the wheel, the `files` method should be used. This returns a sequence of pairs, each of which specifies a filename, and the content to write to that file. Both the name and the content are strings, and so should be encoded appropriately (i.e., in UTF-8) when writing to the wheel. ```python for name, content in my_project.files(): wheel.add_file(name, content) ``` Note that the files to be added must be included unchanged - it is *not* supported for the caller to modify the returned content. Also, it is the caller's responsibility to ensure that none of the generated files clash with files that the caller is adding to the wheel as part of its own processes. ### Runtime dependencies If the `map` method is used with the "import_hook" implementation, the resulting wheel will require that the runtime support module is installed. To ensure that is the case, dependency metadata must be added to the wheel. The `dependencies` method provides the required metadata. ```python for dep in my_project.dependencies(): wheel.metadata.dependencies.add(dep) ``` Note that when runtime support is not needed, the `dependencies` method will return an empty list. So it is safe (and recommended) to call it in all cases.