Skip to content

Commit

Permalink
Fixed: com-lihaoyi#4054 Re-Write Docs for First Class Python Support …
Browse files Browse the repository at this point in the history
…[Basic Example] (com-lihaoyi#4063)

# Pull Request 
Re-write Docs for First Class Python Support [Basic Example]
Fixes: com-lihaoyi#4054 

## Description
Rewrite Docs for Python `1-simple`, `2-custom-build-logic` and
`3-multi-module` Examples


## Related Issues
- Link to related issue com-lihaoyi#4054.

## Checklist
- [x] Updated Documentation

## Status
Updated & Require Review!!!
  • Loading branch information
himanshumahajan138 authored and jodersky committed Jan 14, 2025
1 parent 95d5783 commit 6bf5044
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 5 deletions.
28 changes: 25 additions & 3 deletions example/pythonlib/basic/1-simple/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ object foo extends PythonModule {
// This is a basic Mill build for a single `PythonModule`, with one
// dependency and a test suite using the `Unittest` Library.
//
// You can download the example project using the **download** link above,
// or browse the full sources via the **browse** link.
// Ensure you have a JVM installed; the `./mill` script manages all other dependencies.
// All examples, from simple hello-world projects on this page to advanced
// link:[web build examples(Coming Soon...)] and link:[real-world projects(Coming Soon...)],
// are fully executable and tested in Mill’s CI workflows.
//
// The source code for this module lives in the `src/` folder.
// Output for this module (typeChecked files, resolved dependency lists, …​) lives in `out/`.
//
// ----
// build.mill
// foo/
Expand Down Expand Up @@ -72,9 +82,7 @@ Success: no issues found in 1 source file
...
test_escaping (test.TestScript...) ... ok
test_simple (test.TestScript...) ... ok
...
----------------------------------------------------------------------
Ran 2 tests...
...Ran 2 tests...
OK
...

Expand All @@ -90,3 +98,17 @@ OK
error: ...Name "maaain" is not defined...

*/

// The output of every Mill task is stored in the `out/` folder under a name corresponding to
// the task that created it. e.g. The `typeCheck` task puts its metadata output in `out/typeCheck.json`,
// and its output files in `out/typeCheck.dest`.
// You can also use `show` to make Mill print out the metadata output for a particular task.
//
// You can run mill `resolve __` to see a full list of the different tasks that are available,
// `mill resolve _` to see the tasks within foo, `mill inspect typeCheck` to inspect a task’s doc-comment
// documentation or what it depends on, or `mill show foo.typeCheck` to show the output of any task.
//
// The most common **tasks** that Mill can run are cached tasks, such as `typeCheck`, `test`, `bundle` and
// `run`. Cached tasks do not re-evaluate unless one of their inputs changes, whereas commands re-run every time.
// See the documentation for https://mill-build.org/mill/main-branch/fundamentals/tasks.html[Tasks]
// for details on the different task types.
69 changes: 69 additions & 0 deletions example/pythonlib/basic/2-custom-build-logic/build.mill
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Mill makes it very easy to customize your build graph, overriding portions of it with custom logic.
// In this example, we override the `resources` of our `PythonModule` - normally the `resources/` folder
// - to instead contain a single generated text file containing the line count of all the source files in that module

package build
import mill._, pythonlib._

Expand Down Expand Up @@ -25,3 +29,68 @@ object foo extends PythonModule {

object test extends PythonTests with TestModule.Unittest
}

// The addition of `lineCount` and `resources` overrides the previous `resource` folder
// provided by `PythonModule` (labelled `resources.super` below), replacing it with the
// `destination` folder of the new `resources` task, which is wired up to `lineCount`:
//
// ```graphviz
// digraph G {
// rankdir=LR
// node [shape=box width=0 height=0 style=filled fillcolor=white]
// allSourceFiles -> lineCount -> resources -> "..." -> run
// "resources.super" -> "resources"
// "..." [color=white]
// "resources.super" [color=white]
// allSourceFiles [color=white]
// run [color=white]
// }
// ```

/** Usage

> ./mill foo.run
Line Count: 10

> ./mill show foo.lineCount
10

> ./mill inspect foo.lineCount
...
foo.lineCount(build.mill...)
Total number of lines in module source files
Inputs:
foo.allSourceFiles
...

> ./mill foo.test
...
test_line_count (test.TestScript...) ... ok
...Ran 1 test...
OK
...

*/

// Above, def `lineCount` is a new build task we define, which makes use of `allSourceFiles`
// and is in-turn used in our override of `resources` (an existing task).
// The `override` keyword is optional in Mill. This generated file can then be loaded
// and used at runtime, as see in the output of `mill run`.
//
// If you’re not familiar with what tasks you can `override` or how they are related,
// you can explore the existing tasks via autocomplete in your IDE, or use the
// https://mill-build.org/mill/main-branch/cli/builtin-commands.html#_visualize[mill visualize].
//
// `os.read.lines` and `os.write` come from the https://github.com/com-lihaoyi/os-lib[OS-Lib] library,
// which is one of Mill’s https://mill-build.org/mill/main-branch/fundamentals/bundled-libraries.html[Bundled Libraries].
// You can also import any other library you want from Maven Central using
// https://mill-build.org/mill/main-branch/extending/import-ivy-plugins.html[import $ivy],
// so you are not limited to what is bundled with Mill.
//
// Custom user-defined tasks in Mill benefit from all the same things that built-in tasks do: automatic caching
// (in the https://mill-build.org/mill/main-branch/fundamentals/out-dir.html[out/ folder]),
// parallelism (with the https://mill-build.org/mill/main-branch/cli/flags.html#_jobs_j[-j/--jobs flag]),
// inspectability (via https://mill-build.org/mill/main-branch/cli/builtin-commands.html#_show[show] /
// https://mill-build.org/mill/main-branch/cli/builtin-commands.html#_inspect[inspect]), and so on.
// While these things may not matter for such a simple example that runs quickly, they ensure that custom
// build logic remains performant and maintainable even as the complexity of your project grows.
4 changes: 2 additions & 2 deletions example/pythonlib/basic/2-custom-build-logic/foo/src/foo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@


def line_count() -> int:
with importlib.resources.open_text("resources", "line-count.txt") as file:
return int(file.readline().strip())
resource_content = (importlib.resources.files("resources").joinpath("line-count.txt").read_text())
return int(resource_content.strip())


if __name__ == "__main__":
Expand Down
83 changes: 83 additions & 0 deletions example/pythonlib/basic/3-multi-module/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package build
import mill._, pythonlib._

trait MyModule extends PythonModule {
def resources = super.resources() ++ Seq(PathRef(millSourcePath / "res"))
object test extends PythonTests with TestModule.Unittest
}

Expand All @@ -14,7 +15,18 @@ object bar extends MyModule {
def mainScript = Task.Source { millSourcePath / "src" / "bar.py" }
def pythonDeps = Seq("Jinja2==3.1.4")
}

// This example contains a simple Mill build with two modules, `foo` and `bar`, which you can run
// tasks on such as `foo.run` or `bar.run`. You can define multiple modules the same way you define
// a single module, using `def moduleDeps` to define the relationship between them. Modules can also
// be nested within each other, as `foo.test` and `bar.test` are nested within `foo` and `bar` respectively

// Note that we split out the `test` submodule configuration common to both modules into a
// separate `trait MyModule`. This https://mill-build.org/mill/main-branch/fundamentals/modules.html[Trait Module]
// lets us avoid the need to copy-paste common settings, while still letting us define any per-module
// configuration such as `pythonDeps` specific to a particular module. This is a common pattern within Mill builds.
//
// The above builds expect the following project layout:
// ----
// build.mill
// foo/
Expand Down Expand Up @@ -44,3 +56,74 @@ object bar extends MyModule {
// ...
// ----
//
// Typically, both source code and output files in Mill follow the module hierarchy,
// so e.g. input to the foo module lives in `foo/src/` and compiled output files live in
// `out/foo/run.dest`. You can use `mill resolve` to list out what tasks you can run,
// e.g. `mill resolve __.run` below which lists out all the `run` tasks:
//

/** Usage

> ./mill resolve __.run
bar.run
...
foo.run

> ./mill foo.run --foo-text hello --bar-text world
...
Foo.value: hello
Bar.value: <h1>world</h1>
...

> ./mill bar.run world
Bar.value: <h1>world</h1>

> ./mill bar.test
...
test_escaping (test.TestScript...) ... ok
test_simple (test.TestScript...) ... ok
...Ran 2 tests...
OK
...

*/

// Mill’s evaluator will ensure that the modules are compiled in the right order, and recompiled
// as necessary when source code in each module changes. The unique path on disk that Mill
// automatically assigns each task also ensures you do not need to worry about choosing a path on
// disk to cache outputs, or filesystem collisions if multiple tasks write to the same path.

// You can use wildcards and brace-expansion to select
// multiple tasks at once or to shorten the path to deeply nested tasks. If
// you provide optional task arguments and your wildcard or brace-expansion is
// resolved to multiple tasks, the arguments will be applied to each of the
// tasks.
//
// .Wildcards and brace-expansion
// |==========================================================
// | Wildcard | Function
// | `_` | matches a single segment of the task path
// | `__` | matches arbitrary segments of the task path
// | `{a,b}` | is equal to specifying two tasks `a` and `b`
// |==========================================================
//
//
// You can use the + symbol to add another task with optional arguments.
// If you need to feed a + as argument to your task, you can mask it by
// preceding it with a backslash (`\`).
//

/** Usage

> mill foo._.typeCheck # Runs `typeCheck` for all direct sub-modules of `foo`

> mill foo.__.test # Runs `test` for all transitive sub-modules of `foo`

> mill {foo,bar}.__.testCached # Runs `testCached` for all sub-modules of `foo` and `bar`

> mill __.typeCheck + foo.__.test # Runs all `typeCheck` tasks and all tests under `foo`.

*/

// For more details on the query syntax, check out the
// xref:cli/query-syntax.adoc[query syntax documentation]

0 comments on commit 6bf5044

Please sign in to comment.