Metadata-Version: 2.4
Name: pymoku-parts
Version: 0.11
Summary: Another build tool
Author-email: Ben Coughlan <ben@liquidinstruments.com>
Maintainer-email: Ben Coughlan <ben@liquidinstruments.com>
License-Expression: MIT
Keywords: build,dependencies,tasks
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: psutil
Dynamic: license-file

# Installation

Using Pip

    pip install parts

Or using the self-contained executable

    ./parts

# Introduction

Parts is a build dependency and execution tool heavily inspired by SCons,
bitbake, GitLab-CI among others.

The motivation for parts was the scale of a particular project being managed
which had components larger and more independent than a typical SCons or
Makefile targets; but not requireing the external package and configuration
management provided by bitbake.  These existing solution either felt awkward or
overkill.

Parts intends to provide a simple, lightweight dependency tree API and runtime
to build these medium sized projects.  The command line interface and interation
will feel very familiar.

## Example

Assuming a folder structure

    ./parts.def
    ./module/parts.def


```python
# parts.def
mod = include('module')

default(mod['library'])  # use the instance of Module created in module/parts.def
```

```python
# module/parts.def
import asyncio
from parts import BuildStep


class Module(BuildStep):
    async def do_step(self):
        self.update_progress(total=100, phase='running')
        self.log.info(f'Running Module: {self.name}')
        for i in range(100):
            self.update_progress(advance=1, phase=f'loop {i:d}')
            await asyncio.sleep(0.1)  # do some work
        self.log.info(f'Completed Module: {self.name}')


Module('library')  # automatically registers target with name 'library'
```

Running

    parts --no-cache

will result in

```
[11:29:56] INFO     Building ['default']...                                parts
           INFO     Running Module: library                              library
[11:30:06] INFO     Completed Module: library                            library
╭──────────────────────────────────────────────────────╮
│ 0:00:10 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1/1 │
╰──────────────────────────────────────────────────────╯

           INFO     Complete                                               parts
```


## Design Goals

* parts.def use Python syntax with some shortcuts
* File paths are relative to the parts.def that references them
* BuildStep is the unit of work used by parts
* (sub)projects define all their BuildStep objects in a parts.def
* Build objects are useable by include()'ing another parts.def
* Build objects can be reproduced out of context if their input/output artefacts
match (to enable distribution over multiple hosts)
* One parts.def can reference object instances created from an included parts.def
* BuildSteps can be used to communicate configuration options to depenent steps

# Running parts

From within the toplevel of a project directory, next to a `parts.def`

    parts [targets]

or by specifying the `parts.def` using `--path`

    parts --path path/to/parts.def

Multiple targets can be specified simultaneously.  If no target is provided then
'default' will be run, assuming it was provided by a call the `default()`.

## Listing available targets

    parts --list

## Graphing project dependencies

If graphviz is installed, parts can produce a graph for specific build targets
to help visualize project dependencies.

    parts --graph target

# parts.def Reference

## include()

    # TODO

## source()

    # TODO

## alias()

    # TODO

## copy()

    # TODO

## link()

    # TODO

## publish()

This will create a BuildStep that copies the given dependencies to the global
ouput folder.

    publish('a', 'b', BuildStep('c'))

will copy the outputs of task 'a', 'b' and the newly created 'c' to ./output.

    alias('all', publish('a', 'b', 'c')

Will create a build target 'all' that publishes the outputs of 'a', 'b' and 'c'.

    publish('a', dest='module_a')

Will publish ouputs of 'a' to the `./output/module_a` folder.

## arg()

    # TODO

## default()

    # TODO

# BuildStep

A unit of work in parts is represented by the abstract BuildStep which provides
dependency linking with other BuildSteps as well as informative scheduling and
execution of each task.

    # TODO

## Dependencies

    # TODO

## ProcessStep

    # TODO

# Elaborate vs Execution

Parts will elaborate all included config files to resolve their dependecies
before beginning any execution.

This implies the inputs and outputs for each step must be defined during
elaboration and will not change during execution.

While the execution of each step is parallelised (co-routines, though steps will
likely produce their own processes), elaboration is serialized and not
thread-safe.

# Logging and Progress Bars

    # TODO

## ParseNodes

    # TODO

# State tracking

    # TODO

## phony targets

    # TODO
