Comments (8)
After thinking a bit I only see the following options:
- Use
partial
as in description, either per-file (which could get annoying for folks with nontrivial task modules) or some sort of silly at-runtime mutation of the "real" callables (really don't want to do this and it didn't even work when I tested it). - Use a
Runner
class that can be instantiated with config options, then e.g.runner.run(xxx)
.- Probably the cleanest approach
- Makes the "DSL" more verbose, requires both setup/pass-around (of instance) boilerplate, plus just a longer call
- May pave the way for nigh inevitable Fabric API of e.g.
Host().run("remote cmd")
- Suck it up, use threadlocal globals or whatever.
Still need to research state of the art tho. But suspect the class is the way to go. Bye bye cutesy DSL.
from invoke.
Hadn't been considering the specifics of how the config data gets into Runner and friends, but:
- Something needs to load the conf file from disk
- And merge it with CLI options, if invoked by CLI
- This loaded result has to be stored somewhere
- Then referenced anytime one creates one of these classes
My suspicion is that in the CLI driven use case, we would build the config, then pass it into each task when the task is executed (thus requiring tasks to always have some initial argument, at which point it's effectively just like a method on a class where that argument is self
).
In library use users would be responsible for loading their own config and then doing the same handoff to tasks whenever they get executed.
from invoke.
Kenneth mentioned how Requests has a similar setup, albeit via a dual API:
get()
Session(defaults).get()
This is a lot like what I had in mind originally for the Fabric2 level stuff, except the "unqualified" API would still be able to refer to a threadlocal or similar (probably not by default tho) whereas in Requests it's largely about ability to set defaults.
Which, honestly, is kind of the same here; we could say "if you want the ability to globally tickle defaults, you must call methods on an instantiated class. Users with simple needs can still use the API calls directly if they prefer it, users who want to "hook in" can call the method version.
from invoke.
MOAR COMMENTZ
Think the way to go is really what I had in mind before:
- Core API is method calls on objects, so for the run-echo use case, maybe
runner = Runner(config); runner.run()
as above.- Figure out what sort of class/entity name would be extensible for Fab stuff too, i.e. what object like this would
Host
orHostCollection
inherit from? Use that name.
- Figure out what sort of class/entity name would be extensible for Fab stuff too, i.e. what object like this would
- Secondary API is module-level, e.g.
runner.run
/invoke.run
, has default-None context/options kwarg.- If context object is None, refer to threadlocal context obj
- Can optionally pass in a context object directly
- That object's
run
method is invoked with our*args/
**kwargs`
from invoke.
Thought about this a bunch more recently and started documenting it too.
The tl;dr is that it should look like this:
- Lowest level and "default" (re: trivial base case) API is wholly functional and simple and totally state-unaware. E.g. the current implementation of
run
. It offers kwargs controlling all aspects of behavior. - To obtain a "modified"
run
call that can honor configuration state (such as whether to echo commands executed, see #32), call arun
method on a settings or context object. - Such methods would understand their own, internal state (obtained from the CLI, conf files, or user manipulation) and use that as a guide re: default kwarg values, e.g.:
run(cmd)
: no echorun(cmd, echo=True)
: echoContext().run(cmd)
: no echoContext().run(cmd, echo=True)
: echoContext(echo=True).run(cmd)
: echo
- Tasks can opt to be handed a
Context
object as their 1st argument (which is not taken into account when determining CLI flags) and the CLI module will create and hand one in.- This is the key: CLI sees echo flag, creates core
Context
for statekeeping, with echo on. ThatContext
is what is passed into every "contextualized" task, they all usectx.run()
instead ofrun()
, and presto, echoing occurs.
- This is the key: CLI sees echo flag, creates core
- Specific API for how
Context
holds state related torun
and any other methods that pop up, is TBD. - Should account for config files too -- some sort of override hierarchy such that it probably boils down to a single namespace
- Though preserving the various sources for posterity.
- One question is whether Contexts should be allowed to mutate (thus allowing one task to alter it, then pass the altered copy into another task it calls internally) or if we should try to be functional-like and prefer it be cloned instead.
from invoke.
Have context object being handed around successfully now, omitted from arg parsing, etc etc.
It's an empty object right now, but I will flesh it out as I implement #32. Leaving this open so I ensure it applies to auto-positional + auto-shortflag as subject suggests, once I am done.
from invoke.
#32 implemented, also the rest of the run
related arguments. Hooray.
Right now the context object's inner API is very simply, just a .config
attribute dict which holds a run
subdict whose key/val pairs map to run()
kwargs.
It suffices to enable CLI-flag-driven config, but should get cleaned up for code-level config, and documented.
from invoke.
Documented things a bit better, not bothering with anything deeper than the __init__
API (it's not like giving Context(run={'default': 'kwargs'})
is that ugly an API) for the time being.
from invoke.
Related Issues (20)
- Accept --no-echo to turn off run.echo
- Task decorator removes docstring HOT 1
- Run tasks relative to `tasks.py` HOT 2
- How to manually set short flags? HOT 1
- context.run(): Expose API to pass command and separate args instead of a single string HOT 2
- Specify a config file per Collection... possible?
- Collection mix-up when cross importing invoke tasks
- Running post tasks even if the main task fail
- `--help` after the command treats `--help` as positional argument HOT 2
- Is there support for making invoke.yaml context settings cli flags?
- EncodeWarning's when running on python >= 3.11
- @task(pre=[call(setup, 'qwe')]) fails with "NameError: name 'call' is not defined" HOT 1
- Config run should handle shell paths with spaces HOT 2
- Is it possible to only mock one command and run the rest with MockContext?
- autoprint generators correctly
- Generate help infomation of task args from function docstring.
- Importing Python modules from a scripts directory beside the tasks directory
- Recommended way to forward arguments to commands HOT 2
- Printing Promise objects from asynchronous Runner.run() raises Attribute Error
- Sudo showing password in clear
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from invoke.