Domain-Specific Language¶
Provides the names for the domain-specific language of ballparks.
The key feature of Ballparker is an embedded domain-specific-language (DSL) for
setting up trees of tasks and their associated estimates for ballparks, and a
task model for their manipulation. Your ballpark’s “source file” is just a
Python file, typically defining a single estimate and doing some manipulation
and output when called as __main__.
An “estimate” is just a recursive structure of ballparker.types.Task
objects. Some tasks are “groupings” - they have no intrinsic size, and they may
have subtasks. These are created with grouping() calls, or with a
project() call, used as the “top-level” grouping. Both of those calls take
any number of additional arguments that are or can be converted into tasks:
other ballparker.types.Task instances (like a nested grouping), strings
(which become non-grouping tasks with UNKNOWN size), or (string,
tshirt-size-constant or float size) tuples which become non-grouping tasks with
the indicated size. (See make_task() for details.)
Use via the following is recommended for easier-to-read ballparks:
from ballparker.dsl import *
or, especially if you have an over-eager linter, you can be more explicit:
from ballparker.dsl import project, grouping, XS, S, M, L, XL, DONE, process_estimate
See also
- Introduction to Ballparker
Details on the ballpark process using this DSL, including a template for starting a ballpark script
- ballparker/tests/data.py
Test data, which includes several anonymized real-world ballparks.
Groupings¶
-
ballparker.dsl.project(*args)[source]¶ Make a top-level “project” grouping - the root task of an estimate.
- Parameters
*args – See below.
Each argument is converted/coerced into a
Taskusingmake_task()and included in the list of subtasks.A project should start with a line like
ESTIMATE = project(, followed by as many tasks (including groupings) as desired, with all remaining closing parentheses)on the last task line, as needed to match the opening parentheses.
-
ballparker.dsl.grouping(description, *args)[source]¶ Make a “grouping” task with description and sub-tasks, but no inherent size.
- Parameters
description (
str) – An string description of this grouping*args – See below.
Each additional argument is converted/coerced into a
Taskusingmake_task()and included in the list of subtasks.Task groupings should start with a
grouping("group desc",line, followed by as many tasks (including groupings) as desired, with all remaining closing parentheses)on the last task line, as needed to match the opening parentheses.
Creating leaf tasks¶
-
ballparker.dsl.make_task(a)[source]¶ Coerce an argument into a
Task.This is mainly for use by
grouping()andproject(), not for direct use in your ballparks. However, since those two functions both process their arguments using this, it is documented separately. You can consider each argument to those functions (aside from the description argument togrouping()) to be implicitly wrapped in amake_task()call.If the argument is a string or single-element tuple, it becomes a leaf task with the string as a description and with unknown (
UNKNOWN) size.If the argument is a two-element tuple, it’s treated as a (description, size) pair and converted to a
Taskwith a string description and specified size (either aTShirtSizesor a number).If the argument already is a
Task(e.g., usinggrouping()), no conversion is required, and the argument is returned unchanged.
So, lines with “leaf” tasks can simply be a string or a 2-tuple of string and size (number or t-shirt size).
T-shirt size constants¶
The “t-shirt size” constants referred to above are the elements of
ballparker.types.TShirtSizes, which are imported into the
ballparker.dsl namespace as follows:
ballparker.dsl.XS= <TShirtSizes.XS: 0.5>¶Smallest task possible - about half a day.
ballparker.dsl.S= <TShirtSizes.S: 1>¶Common task size with some interaction (may have to talk to someone, etc.) - about a day.
ballparker.dsl.M= <TShirtSizes.M: 3>¶Common task size, taking about half a week.
ballparker.dsl.L= <TShirtSizes.L: 5>¶Task size of “half a sprint” (about 1 week).
You will want to split this into finer-grained tasks before finalizing the ballpark.
ballparker.dsl.XL= <TShirtSizes.XL: 10>¶Largest task size, an entire sprint (about two weeks).
You will want to split this into finer-grained tasks before finalizing the ballpark.
ballparker.dsl.DONE= <TShirtSizes.DONE: 0>¶Use this as the size when you’re tracking an ongoing project with ballparker, and a task is completed.
ballparker.dsl.UNKNOWN= <TShirtSizes.UNKNOWN: None>¶This is the default task size if unspecified.
Adds “uncertainty” to the ballpark (doesn’t add any points to parent tasks, but does turn them into an inequality).
Output¶
In addition to as_markdown() and other properties
and methods of Task, a general-purpose function is
provided in the DSL module that automates some common uses.
-
ballparker.dsl.process_estimate(estimate, fn='output.md', *args, **kwargs)[source]¶ Output an estimate in Markdown format to screen and a file.
- Parameters
estimate (
Task) – An estimate (task tree).fn (
str) – Filename to write Markdown-formatted estimate to.*args – Any dditional positional arguments are passed to
as_markdown().**kwargs – Any additional keyword arguments are passed to
as_markdown().