Changelog¶
Next 1.x feature release
[Support]: Fix a non-fatal bug in our setup.py
long_descriptiongeneration causing 1.7.0-1.7.2 to have malformed description text on PyPI.
2.2.0 2023-07-12
[Feature]: Remove the somewhat inaccurate subclass requirement around
Config’s.clone(into=...)constructor call. It was broken for certain use cases (such as trying to clone one subclass into a sibling subclass, which would yield aTypeError) and is irrelevant if one is using the new type annotations.[Support] #936: Make sure
py.typedis in our packaging manifest; without it, users working from a regular installation can’t perform type checks. Thanks to Nikita Sobolev for catch & patch.
2.1.3 2023-06-14
[Bug] #944: After the release of 2.1, package-style task modules started looking in the wrong place for project-level config files (inside one’s eg
tasks/dir, instead of next to that dir) due to a subtlety in the new import/discovery mechanism used. This has been fixed. Thanks to Arnaud V. and Hunter Kelly for the reports and to Jesse P. Johnson for initial debugging/diagnosis.
2.1.2 2023-05-15
[Support] #936: Make sure
py.typedis in our packaging manifest; without it, users working from a regular installation can’t perform type checks. Thanks to Nikita Sobolev for catch & patch.
2.1.1 2023-05-01
[Bug] #910: Add more rigor around subprocess/runner shutdown to avoid spurious exceptions & also fix downstream issues in libraries like Fabric. Reported by Orlando Rodríguez.
[Bug] #934: The
importlibupgrade in 2.1 had a corner case bug (regardingfrom . import <submodule>functionality within package-like task trees) which in turn exposed a false-pass in our test suite. Both have now been fixed. Thanks to Greg Meyer and Robert J. Berger for the bug reports.
2.0.1 2023-04-29
[Bug] #910: Add more rigor around subprocess/runner shutdown to avoid spurious exceptions & also fix downstream issues in libraries like Fabric. Reported by Orlando Rodríguez.
[Support] #901: (via #903) Tweak test suite
setupmethods to be namedsetup_methodso pytest stops whining about it. Patch via Jesse P. Johnson.
2.1.0 2023-04-28
[Bug] #376: Resolve equality comparison bug for non-collections. Patch via Jesse P. Johnson
[Support] #901: (via #903) Tweak test suite
setupmethods to be namedsetup_methodso pytest stops whining about it. Patch via Jesse P. Johnson.[Support] #906: Implement type hints and type checking tests with mypy to reduce errors and impove code documentation. Patches by Jesse P. Johnson and review by Sam Bull.
[Support] #675: Implement
importliband deprecateimpmodule. Patches provided by Jesse P. Johnson
2.0.0 2023-01-16
[Support]:
Task.argspechas changed its return value; it now returns aninspect.Signaturederived from that of the task’s body callable.警告
This change is backwards incompatible if you were using this method directly.
[Support]: Remove support for, and imports related to, all Python versions less than 3.6 - including Python 2. This also includes updates to vendored packages, such as removing
sixand upgradinglexiconto the latest version; and also treatment of things likeMockuse withininvoke.context.MockContext(which now expects stdlib’sunittest.mockinstead of hunting for the old standalonemocklibrary).Thanks to various folks for patches related to some of this work, including Jesse P. Johnson who supplied multiple PRs whose commits made it in.
警告
This change is backwards incompatible in the following scenarios:
You use Python <3.6. Shouldn’t be an issue as we now specify
python_requiresin packaging metadata.You call
invoke.util.encode_outputmanually for some reason. (This became a noop under Python 3, so just…remove it!)You use
invoke.context.MockContext; itsrepeatinit kwarg changed its default value fromFalsetoTrue. This probably won’t bite you, but we mention it just in case you somehow relied upon the legacy behavior.You subclass
invoke.runners.Runnerand/or have had to interact with itsstoporstop_timermethods. The latter has been merged into the former, and if you are overridingstop, you’ll want to make sure you now callsuper()somewhere if you were not already.
1.7.3 2022-09-30
[Support]: Fix a non-fatal bug in our setup.py
long_descriptiongeneration causing 1.7.0-1.7.2 to have malformed description text on PyPI.
1.7.2 2022-09-30
1.7.1 2022-05-11
[Bug] #659: Improve behavior under
nohup, which causes stdin to become an undetectably-unreadable (but otherwise legit) file descriptor. Previously this led toOSErroreven if you weren’t expecting anything on stdin; we now trap this specific case and silently ignore it, allowing execution to continue. Thanks to@kingkisskillfor initial report and to Ryan Stoner for followup and workshopping.
1.7.0 2022-03-18
[Feature] #845: Env vars explicitly supplied to
sudo(via itsenvkwarg) are now explicitly preserved viasudo’s--preserve-envargument. Patch courtesy of Benno Rice.[Feature] #793: Add a new
tasks.ignore_unknown_helpconfig option for users who hand their tasks centrally-defined argument help dictionaries; it defaults toFalsebut such users may set it toTrueto avoid exceptions. Thanks to@Allu2for the report.[Support]: Switch our continuous integration service from Travis-CI to Circle-CI, plus related and necessary updates to various administrative config files, management tasks and metadata. Including but not limited to:
Enhanced PyPI-level metadata/links
Split out tool config data from
setup.cfgEnhance execution & coverage of unit vs integration tests under CI
警告
Due to various factors, this release will not include a Python 2-compatible wheel archive. Users of Python 2 can still install from the sdist, and are strongly encouraged to check the roadmap as the next release will likely be the one that removes Python 2 entirely!
[Support] #803: Upgrade our vendored PyYAML from 3.11 to 5.4.1; this should both supply a number of security fixes, and address problems loading project-level YAML config files under Python 3.10. Fix via Andreas Rammhold.
[Support]: Switch to using
yaml.safe_loadfor loading config files. This avoids some warnings under newer PyYAML versions and is also, in a shocking twist, more secure.
1.6.0 2021-07-09
[Feature] #791: Add a new
run.echo_formatconfiguration option allowing control over the format of echoed commands. It defaults to the previously hardcoded value (wrap in ANSI bold) and is thus backwards compatible. Thanks to David JM Emmett for the patch.[Support]: Document the
drykeyword argument torun, which had been added in version 1.3 but only documented as a CLI flag; it does also work as a kwarg (and as a config option).[Support]: (Mostly) alphabetize the list of
run()params in the runners API docs. Previously they were an unordered mess.
1.5.1 2021-07-09
[Bug] #751: Don’t explode on empty-but-for-whitespace task docstrings. Thanks to Matt Hayden for the report & initial patches.
[Support]: Document the
drykeyword argument torun, which had been added in version 1.3 but only documented as a CLI flag; it does also work as a kwarg (and as a config option).[Support]: (Mostly) alphabetize the list of
run()params in the runners API docs. Previously they were an unordered mess.
1.5.0 2020-12-30
[Feature]: Upgrade
MockContextto wrap its methods inMockobjects if the(unittest.)mocklibrary is importable. This makes testing Invoke-using codebases even easier.[Feature] #700: Automatically populate the
commandattribute ofResultobjects returned byMockContextmethods, with the command string triggering that result. Previously users had to do this by hand or otherwise suffered inaccurate result objects. Thanks to@SwampFalcfor the report & initial patch.[Feature] #441: Add a new
repeatkwarg toMockContextwhich, when True (default: False) causes stored results for its methods to be yielded repeatedly instead of consumed. Feature request courtesy of@SwampFalc.[Feature]:
MockContextnow accepts a few quality-of-life shortcuts as keys and values in itsrun/sudoarguments:Keys may be compiled regular expression objects, as well as strings, and will match any calls whose commands match the regex.
Values may be
TrueorFalseas shorthand for otherwise emptyResultobjects with exit codes of0or1respectively.Values may also be strings, as shorthand for otherwise empty
Resultobjects with those strings given as thestdoutargument.
[Feature]:
MockContextnow populates itsNotImplementedErrorexception instances (typically raised when a command is executed which had no pre-prepared result) with the command string that triggered them; this makes it much easier to tell what exactly in a test caused the error.[Feature] #197: Allow subcollections to act as the default ‘tasks’ of their parent collections (via the new
defaultkwarg toadd_collection). This means that nontrivial task trees can specify eg “use my test subcollection’s default task as the global default task” and similar. Thanks to Tye Wang for the request and initial patch.[Feature] #454: (also #577/#658, via #583/#681/#607) Allow any string-compatible object to be passed to
Context.cd, enabling use of egpathlib.Pathinstances. Thanks to Jimm Domingo for the original report and Ludovico Bianchi, Mario César, and Floris Lambrechts for patches.[Bug]: Immutable iterable result values handed to
MockContextwould yield errors (due to the use ofpop()). The offending logic has been retooled to be more iterator-focused and now works for tuples and etc.[Bug] #398: (via #611/#580) Don’t silently ignore task help specifiers which don’t actually map to the decorated task’s arguments (eg
@task(help={"foo": "help for foo"})wrapping a task without afooargument). Reported by Sohaib Farooqi, with original patches by Hayden Flinner and Floris Lambrechts.[Bug] #409: (via #611/#580) Don’t silently discard help text for task arguments whose names happen to contain underscores. Reported by
@iago1460, original patches by Hayden Flinner and Floris Lambrechts.[Support] #586: Explicitly strip out
__pycache__(and for good measure,.py[co], which previously we only stripped from thetests/folder) in ourMANIFEST.in, since at least some earlier releases erroneously included such. Credit to Martijn Pieters for the report and Floris Lambrechts for the patch.[Support]: Update the testing documentation a bit: cleaned up existing examples and added new sections for the other updates in the 1.5 release.
[Support]: Enhanced test coverage in a handful of modules whose coverage was under 90%.
1.4.1 2020-01-29
[Bug] #518: Close pseudoterminals opened by the
Localclass duringrun(..., pty=True). Previously, these were only closed incidentally at process shutdown, causing file descriptor leakage in long-running processes. Thanks to Jonathan Paulson for the report.[Bug] #660: Fix an issue with
run& friends having intermittent problems at exit time (symptom was typically about the exit code value beingNoneinstead of an integer; often with an exception trace). Thanks to Frank Lazzarini for the report and to the numerous others who provided reproduction cases.[Support] #586: Explicitly strip out
__pycache__(and for good measure,.py[co], which previously we only stripped from thetests/folder) in ourMANIFEST.in, since at least some earlier releases erroneously included such. Credit to Martijn Pieters for the report and Floris Lambrechts for the patch.
1.3.1 2020-01-29
[Bug] #518: Close pseudoterminals opened by the
Localclass duringrun(..., pty=True). Previously, these were only closed incidentally at process shutdown, causing file descriptor leakage in long-running processes. Thanks to Jonathan Paulson for the report.[Bug] #660: Fix an issue with
run& friends having intermittent problems at exit time (symptom was typically about the exit code value beingNoneinstead of an integer; often with an exception trace). Thanks to Frank Lazzarini for the report and to the numerous others who provided reproduction cases.[Support] #586: Explicitly strip out
__pycache__(and for good measure,.py[co], which previously we only stripped from thetests/folder) in ourMANIFEST.in, since at least some earlier releases erroneously included such. Credit to Martijn Pieters for the report and Floris Lambrechts for the patch.
1.4.0 2020-01-03
[Feature]: Never accompanied the top-level singleton
run(which simply wraps an anonymousContext’srunmethod) with its logical sibling,sudo- this has been remedied.[Feature] #682: (originally reported as #194) Add asynchronous behavior to
run:Basic asynchronicity, where the method returns as soon as the subprocess has started running, and that return value is an object with methods allowing access to the final result.
“Disowning” subprocesses entirely, which not only returns immediately but also omits background threading, allowing the subprocesses to outlive Invoke’s own process.
See the updated API docs for the
Runnerfor details on the newasynchronousanddisownkwargs enabling this behavior. Thanks to@MinchinWebfor the original report.[Bug]: As part of feature work on #682, we noticed that the
Resultreturn value fromrunwas inconsistent between dry-run and regular modes; for example, the dry-run version of the object lacked updated values forhide,encodingandenv. This has been fixed.[Bug] #637: A corner case in
runcaused overridden streams to be unused if those streams were also set to be hidden (egrun(command, hide=True, out_stream=StringIO())would result in no writes to theStringIOobject).This has been fixed - hiding for a given stream is now ignored if that stream has been set to some non-
None(and in the case ofin_stream, non-False) value.
1.3.0 2019-08-06
[Feature]: Allow the configuration system to override which
Executorsubclass to use when executing tasks (via an import-oriented string).Specifically, it’s now possible to alter execution by distributing such a subclass alongside, for example, a repository-local config file which sets
tasks.executor_class; previously, this sort of thing required use of custom binaries.[Feature] #539: (via #645) Add support for command timeouts, i.e. the ability to add an upper bound on how long a call to
runmay take to execute. Specifically:A
timeoutargument torun.The
timeouts.commandconfig setting mapping to that argument.The
-T/--command-timeoutCLI flag.
Thanks to Israel Fruchter for the request & an early version of the patchset.
[Feature] #324: Add basic dry-run support, in the form of a new
--dryCLI option and matchingrun.dryconfig setting, which causes command runners (egrun,Context.run) to:Act as if the
echooption has been turned on, printing the command-to-be-run to stdout;Skip actual subprocess invocation (returning before any of that machinery starts running);
Return a dummy
Resultobject with ‘blank’ values (empty stdout/err strings,0exit code, etc).
This allows quickly seeing what a given task or series of tasks might do, without actually running any shell commands (though naturally, any state-modifying Python code will still run).
Thanks to Monty Hindman for the feature request and
@thebjornfor the initial patch.[Bug] #466: Update the parsing and CLI-program mechanisms so that all core arguments may be given within task CLI contexts; previously this functionality only worked for the
--helpflag, and other core arguments given after task names (such as--echo) were silently ignored.[Bug] #557: (with assist from #640) Fix the
cdandprefixcontext managers so thatwith cdandwith prefixcorrectly revert their state manipulations after they exit, when exceptions occur. Thanks to Jon Walsh and Artur Puzio for their respective patches.[Bug] #552: (also #553) Add a new
Runnermethod,close_proc_stdin, and call it when standard input processing detects an EOF. Without this, subprocesses that read their stdin until EOF would block forever, hanging the program. Thanks to@plockcfor the report & initial patch.备注
This fix only applies when
pty=False(the default); PTYs complicate the situation greatly (but also mean the issue is less likely to occur).[Bug] #384: (via #653) Modify config file loading so it detects missing-file IOErrors via their
errnoattribute instead of their string rendering (eg"No such file"). This should improve compatibility for non-English locales. Thanks to Patrick Massot for the report and Github user@cybierefor the patch.
1.2.0 2018-09-13
[Feature] #301: (via #414) Overhaul tab completion mechanisms so users can print a completion script which automatically matches the emitting binary’s configured names (compared to the previous hardcoded scripts, which only worked for
inv/invokeby default). Thanks to Nicolas Höning for the foundational patchset.
1.1.1 2018-07-31
[Bug] #559: (also fabric/fabric#1812) Modify how
Runnerperforms stdin terminal mode changes, to avoid incorrect terminal state restoration when run concurrently (which could lead to things like terminal echo becoming disabled after the Python process exits).Thanks to Adam Jensen and Nick Timkovich for the detailed bug reports & reproduction assistance.
[Bug] #556: (also fabric/fabric#1823) Pre-emptively check for an error condition involving an unpicklable config file value (Python config files and imported module objects) and raise a useful exception instead of allowing a confusing
TypeErrorto bubble up later. Reported by Pham Cong Dinh.
1.0.2 2018-07-31
[Bug] #559: (also fabric/fabric#1812) Modify how
Runnerperforms stdin terminal mode changes, to avoid incorrect terminal state restoration when run concurrently (which could lead to things like terminal echo becoming disabled after the Python process exits).Thanks to Adam Jensen and Nick Timkovich for the detailed bug reports & reproduction assistance.
[Bug] #556: (also fabric/fabric#1823) Pre-emptively check for an error condition involving an unpicklable config file value (Python config files and imported module objects) and raise a useful exception instead of allowing a confusing
TypeErrorto bubble up later. Reported by Pham Cong Dinh.
1.1.0 2018-07-12
[Feature] #543: Implemented support for using
INVOKE_RUNTIME_CONFIGenv var as an alternate method of supplying a runtime configuration file path (effectively, an env var based version of using the-f/--configoption). Feature request via Kevin J. Qiu.[Feature]: Add a
klasskwarg to@taskto allow extending codebases the ability to create their own variants on@task/Task.[Feature]: Remove overzealous argument checking in
@task, instead just handing any extra kwargs into the task class constructor. The high level behavior for truly invalid kwargs is the same (TypeError) but now extending codebases can add kwargs to their versions of@taskwithout issue.[Feature]: Refactor
Callinternals slightly, exposing some previously internal logic as theclone_datamethod; this is useful for client codebases when extendingCalland friends.[Feature]: Enhance
Callwith a new method (clone_data) and new kwarg to an existing method (clonegrewwith_) to assist subclassers when extending.[Support]: Implemented some minor missing tests, such as testing the
INVOKE_DEBUGlow-level env var.[Support]: Fix some test-suite-only failures preventing successful testing on Python 3.7 and PyPy3, and move them out of the ‘allowed failures’ test matrix quarantine now that they pass.
[Support]: Apply the black code formatter to our codebase and our CI configuration.
[Support]: Fixed some inaccuracies in the API docs around
Executorand itscorekwarg (was erroneously referring toParserContextinstead ofParseResult). Includes related cleaning-up of docstrings and tests.
1.0.1 2018-07-12
[Bug]: As part of solving #528 we found a related bug, where unnamed subcollections also caused issues with
inv --list --list-format=json. Specifically,Collection.serializedsorts subcollections by name, which is problematic when that name isNone. This is now fixed.[Bug] #528: Around Invoke 0.23 we broke the ability to weave in subcollections via keyword arguments to
Collection, though it primarily manifests asNoneTyperelated errors duringinv --list. This was unintentional and has been fixed. Report submitted by Tuukka Mustonen.[Bug]: Fix up the
__repr__ofCallto reference dynamic class name instead of hardcoding"Call"; this allows subclasses’__repr__output to be correct instead of confusing.[Bug] #270: (also #551)
Nonevalues in config levels (most commonly caused by empty configuration files) would raiseAttributeErrorwhenmerge_dictswas used to merge config levels together. This has been fixed. Thanks to Tyler Hoffman and Vlad Frolov for the reports.[Support]: Implemented some minor missing tests, such as testing the
INVOKE_DEBUGlow-level env var.[Support]: Fix some test-suite-only failures preventing successful testing on Python 3.7 and PyPy3, and move them out of the ‘allowed failures’ test matrix quarantine now that they pass.
[Support]: Apply the black code formatter to our codebase and our CI configuration.
[Support]: Fixed some inaccuracies in the API docs around
Executorand itscorekwarg (was erroneously referring toParserContextinstead ofParseResult). Includes related cleaning-up of docstrings and tests.
1.0.0 2018-05-09
[Feature]: Updated
Taskto mimic the wrapped function’s__module__attribute, allowing for better interaction with things like Sphinx autodoc that attempt to filter out imported objects from a module.[Feature]: Added the –prompt-for-sudo-password CLI option for getpass-based up-front prompting of a sensitive configuration value.
[Bug]: Tweaked the innards of
Config/DataProxyto prevent accessing properties & other attributes’ values during__setattr__(the code in question only needed the names). This should have no noticeable effect on user code (besides a marginal speed increase) but fixed some minor test coverage issues.[Bug]: Removed an old, unused and untested (but, regrettably, documented and public) method that doesn’t seem to be much use:
invoke.config.Config.paths. Please reach out if you were actually using it and we may consider adding some form of it back.警告
This is a backwards incompatible change if you were using
Config.paths.
0.23.0 2018-04-29
[Feature] #33: Overhaul task listing (formerly just a simple, boolean
--list) to make life easier for users with nontrivial task trees:Limit display to a specific namespace by giving an optional argument to
--list, e.g.--list build;Additional output formats besides the default (now known as
flat) such as a nested view with--list-format nestedor script-friendly output with--list-format json.The default
flatformat now sorts a bit differently - the previous algorithm would break up trees of tasks.Limit listing depth, so it’s easier to view only the first level or two (i.e. the overall namespaces) of a large tree, e.g.
--list --list-depth 1;
Thanks to the many users who submitted various requests under this ticket’s umbrella, and to Dave Burkholder in particular for detailed use case analysis & feedback.
[Bug]: (partially re: #449) Update error message around missing positional arguments so it actually lists them. Includes a minor tweak to the API of
ParserContext, namely changingneeds_positional_arguments(bool) tomissing_positional_arguments(list).[Bug] #516: Remove the CLI parser ambiguity rule regarding flag-like tokens which are seen after an optional-value flag (e.g.
inv task --optionally-takes-a-value --some-other-flag.) Previously, any flag-like value in such a spot was considered ambiguous and raised aParseError. Now, the surrounding parse context is used to resolve the ambiguity, and no error is raised.警告
This behavior is backwards incompatible, but only if you had the minority case where users frequently and erroneously give otherwise-legitimate flag-like values to optional-value arguments, and you rely on the parse errors to notify them of their mistake. (If you don’t understand what this means, don’t worry, you almost certainly don’t need to care!)
[Bug]: Integer-type CLI arguments were not displaying placeholder text in
--helpoutput (i.e. they appeared as--myintinstead of--myint=INT.) This has been fixed.[Bug]:
Collectionhad some minor bugs or oversights in how it responds to things likerepr(),==; boolean behavior; how docstrings appear when created from a Python module; etc. All are now fixed. If you’re not sure whether this affects you, it does not :)[Bug]: Previously, some error conditions (such as invalid task or collection names being supplied by the user) printed to standard output, instead of standard error. Standard error seems more appropriate here, so this has been fixed.
警告
This is backwards incompatible if you were explicitly checking the standard output of the
inv[oke]program for some of these error messages.警告
If your code is manually raising or introspecting instances of
Exit, note that its signature has changed fromExit(code=0)toExit(message=None, code=None). (Thus, this will only impact you if you were calling its constructor instead of raising the class object itself.)[Support] #469: Fix up the doc/example re: subclassing
Config. Credit:@Aiky30.[Support] #433: Add -dev and -nightly style Python versions to our Travis builds. Thanks to
@SylvainDefor the contribution.[Support]: Rename
invoke.platformtoinvoke.terminals; it was inadvertently shadowing theplatformstandard library builtin module. This was not causing any bugs we are aware of, but it is still poor hygiene.警告
This change is technically backwards incompatible. We don’t expect many users import
invoke.platformdirectly, but if you are, take note.[Support] #515: Ported the test suite from spec (nose) to pytest-relaxed (pytest) as pytest basically won the test-runner war against nose & has greater mindshare, more shiny toys, etc.
[Support]: (partially re: #33) Renamed the
--rootCLI flag to--search-root, partly for clarity (#33 will be adding namespace display-root related flags, which would make--rootambiguous) and partly for consistency with the config option, which was already namedsearch_root. (The short version of the flag,-r, is unchanged.)警告
This is a backwards incompatible change. To fix, simply use
--search-rootanywhere you were previously using--root.
0.22.1 2018-01-29
[Bug] #488: Account for additional I/O related
OSErrorerror strings when attempting to capture only this specific subtype of error. This should fix some issues with less common libc implementations such asmusl(as found on e.g. Alpine Linux.) Thanks to Rajitha Perera for the report.[Bug] #437: When merging configuration levels together (which uses
copy.copyby default), pass file objects by reference so they don’t get closed. Catch & patch by Paul Healy.[Bug] #342: Accidentally hardcoded
Collectioninstead ofclsinCollection.from_module(an alternate constructor and therefore a classmethod.) This made it rather hard to properly subclassCollection. Report and initial patch courtesy of Luc Saffre.[Support] #469: Fix up the doc/example re: subclassing
Config. Credit:@Aiky30.[Support] #433: Add -dev and -nightly style Python versions to our Travis builds. Thanks to
@SylvainDefor the contribution.
0.22.0 2017-11-29
[Bug]: Iterable-type CLI args were actually still somewhat broken & were ‘eating’ values after themselves in the parser stream (thus e.g. preventing parsing of subsequent tasks or flags.) This has been fixed.
[Bug] #407: (also #494, #67) Update the default value of the
run.shellconfig value so that it reflects a Windows-appropriate value (specifically, theCOMSPECenv var or a fallback ofcmd.exe) on Windows platforms. This prevents Windows users from being forced to always ship around configuration-level overrides.Thanks to Maciej ‘maQ’ Kusz for the original patchset, and to
@thebjornand Garrett Jenkins for providing lots of feedback.[Support] #364: Drop Python 2.6 and Python 3.3 support, as these versions now account for only very low percentages of the userbase and are unsupported (or about to be unsupported) by the rest of the ecosystem, including
pip.This includes updating documentation & packaging metadata as well as taking advantage of basic syntax additions like set literals/comprehensions (
{1, 2, 3}instead ofset([1, 2, 3])) and removing positional string argument specifiers ("{}".format(val)instead of"{0}".format(val)).
0.21.0 2017-09-18
[Feature] #132: Implement ‘iterable’ and ‘incrementable’ CLI flags, allowing for invocations like
inv mytask --listy foo --listy bar(resulting in a call likemytask(listy=['foo', 'bar'])) orinv mytask -vvv(resulting in e.g.mytask(verbose=3). Specifically, these require use of the new iterable and incrementable arguments to@task- see those links to the conceptual docs for details.
0.20.4 2017-08-14
[Bug]: The behavior of
Configwhenlazy=Truedidn’t match that described in the API docs, after the recent updates to its lifecycle. (Specifically, any config data given to the constructor was not visible in the resulting instance untilmerge()was explicitly called.) This has been fixed, along with other related minor issues.
0.20.3 2017-08-04
[Bug] #467: (Arguably also a feature, but since it enables behavior users clearly found intuitive, we’re considering it a bug.) Split up the parsing machinery of
Programand pushed theCollection-making out ofLoader. Combined, this allows us to honor the project-level config file before the second (task-oriented) CLI parsing step, instead of after.For example, this means you can turn off
auto_dash_namesin your per-project configs and not only in your system or user configs.Report again courtesy of Luke Orland.
警告
This is a backwards incompatible change if you were subclassing and overriding any of the affected methods in the
ProgramorLoaderclasses.
0.20.2 2017-08-02
[Bug] #465: The
tasks.auto_dash_namesconfig option added in0.20.0wasn’t being fully honored when set toFalse; this has been fixed. Thanks to Luke Orland for the report.
0.20.1 2017-07-27
[Bug]: Fix a broken
six.movesimport withininvoke.util; was causingImportErrorin environments without an external copy ofsixinstalled.The dangers of one’s local and CI environments all pulling down packages that use
six! It’s everywhere!
0.20.0 2017-07-27
[Feature] #322: Allow users to completely disable mirroring of stdin to subprocesses, by specifying
Falsefor therun.in_streamconfig setting and/or keyword argument.This can help prevent problems when running Invoke under systems that have no useful standard input and which otherwise defeat our pty/fileno related detection.
[Feature] #329: All task and collection names now have underscores turned into dashes automatically, as task parameters have been for some time. This impacts
--list,--help, and of course the parser. For details, see 破折号和下划线.This behavior is controlled by a new config setting,
tasks.auto_dash_names, which can be set toFalseto go back to the classic behavior.Thanks to Alexander Artemenko for the initial feature request.
[Feature] #310: (also #455, #291) Allow configuring collection root directory & module name via configuration files (previously, they were only configurable via CLI flags or generating a custom
Program.)[Feature]: (required to support #310 and #329) Break up the
Configlifecycle some more, allowing it to gradually load configuration vectors; this allows the CLI machinery (Executor) to honor configuration settings from config files which impact how CLI parsing and task loading behaves.Specifically, this adds more public
Config.load_*methods, which in tandem with thelazykwarg to__init__(formerlydefer_post_init, see below) allow full control over exactly when each config level is loaded.警告
This change may be backwards incompatible if you were using or subclassing the
Configclass in any of the following ways:If you were passing
__init__kwargs such asproject_homeorruntime_pathand expecting those files to auto-load, they no longer do; you must explicitly callload_projectand/orload_runtimeexplicitly.The
defer_post_initkeyword argument toConfig.__init__has been renamed tolazy, and controls whether system/user config files are auto-loaded.Config.post_inithas been removed, in favor of explicit/granular use of theload_*family of methods.All
load_*methods now callConfig.mergeautomatically by default (previously, merging was deferred to the end of most config related workflows.)This should only be a problem if your config contents are extremely large (it’s an entirely in-memory dict-traversal operation) and can be avoided by specifying
merge=Falseto any such method. (Note that you must, at some point, callmergein order for the config object to work normally!)
[Bug]: Display of hidden subprocess output when a command execution failed (end-of-session output starting with
Encountered a bad command exit code!) was liable to display encoding errors (e.g.'ascii' codec can't encode character ...) when that output was not ASCII-compatible.This problem was previously solved for non-hidden (mirrored) subprocess output, but the fix (encode the data with the local encoding) had not been applied to exception display. Now it’s applied in both cases.
[Bug] #396:
Collection.add_task(task, aliases=('other', 'names')was listed in the conceptual documentation, but not implemented (technically, it was removed at some point and never reinstated.) It has been (re-)added and now exists. Thanks to@jenisysfor the report.警告
This technically changes argument order for
Collection.add_task, so be aware if you were using positional arguments!
0.19.0 2017-06-19
[Feature]: Add
MockContext.set_result_forto allow massaging a mock Context’s configured results after instantiation.
0.18.1 2017-06-07
[Bug]: Update Context internals re: command execution & configuration of runner subclasses, to work better in client libraries such as Fabric 2.
0.18.0 2017-06-02
[Feature] #444: Add support for being used as
python -m invoke <args>on Python 2.7 and up. Thanks to Pekka Klärck for the feature request.[Feature] #205: Allow giving core flags like
--helpafter tasks to trigger per-task help. Previously, onlyinv --help tasknameworked.备注
Tasks with their own
--helpflags won’t be able to leverage this feature - the parser will still interpret the flag as being per-task and not global. This may change in the future to simply throw an exception complaining about the ambiguity. (Feedback welcome.)[Feature] #446: Implement
cdandprefixcontext managers (as methods on the not-that-one-the-other-oneContextclass.) These are based on similar functionality in Fabric 1.x. Credit: Ryan P Kilby.[Support] #448: Fix up some config-related tests that have been failing on Windows for some time. Thanks to Ryan P Kilby.
0.17.0 2017-05-05
[Feature]: Add a
userkwarg & config parameter toContext.sudo, which corresponds roughly tosudo -u <user> <command>.[Bug] #440: Make sure to skip a call to
struct/ioctlon Windows platforms; otherwise certain situations insideruncalls would trigger import errors. Thanks to@chrisc11for the report.[Bug] #425: Fix
Inappropriate ioctl for deviceerrors (usuallyOSError) when running Invoke without a tty-attached stdin (i.e. when run under ‘headless’ continuous integration systems or simply as e.g.inv sometask < /dev/null(redirected stdin.) Thanks to Javier Domingo Cansino for the report & Tuukka Mustonen for troubleshooting assistance.[Bug] #439: Avoid placing stdin into bytewise read mode when it looks like Invoke has been placed in the background by a shell’s job control system; doing so was causing the shell to pause the Invoke process (e.g. with a message like
suspended (tty output).) Reported by Tuukka Mustonen.
0.16.3 2017-04-18
[Bug]: Even more setup.py related tomfoolery.
0.16.2 2017-04-18
[Bug]: Deal with the fact that PyPI’s rendering of Restructured Text has no idea about our fancy new use of Sphinx’s doctest module. Sob.
0.16.1 2017-04-18
[Bug]: Fix a silly typo preventing proper rendering of the packaging
long_description(causing an effectively blank PyPI description.)
0.16.0 2017-04-18
[Feature]:
ResultandUnexpectedExitobjects now have a more usefulrepr()(and in the case ofUnexpectedExit, a distinctrepr()from their preexistingstr().)[Feature]:
Context.sudono longer prompts the user when the configured sudo password is empty; thus, an empty sudo password and asudoprogram configured to require one will result in an exception.The runtime prompting for a missing password was a temporary holdover from Fabric v1, and in retrospect is undesirable. We may add it back in as an opt-in behavior (probably via subclassing) in the future if anybody misses it.
警告
This is a backwards incompatible change, if you were relying on
sudo()prompting you for your password (vs configuring it). If you were doing that, you can simply switch torun("sudo <command>")and respond to the subprocess’ sudo prompt by hand instead.[Feature]: Switched the order of the first two arguments of
Config.__init__, so that theoverrideskwarg becomes the first positional argument.This supports the common use case of making a
Configobject that honors the system’s core/global defaults; previously, becausedefaultswas the first argument, you’d end up replacing those core defaults instead of merging with them.警告
This is a backwards incompatible change if you were creating custom
Configobjects via positional, instead of keyword, arguments. It should have no effect otherwise.[Feature] #309: Overhaul how task execution contexts/configs are handled, such that all contexts in a session now share the same config object, and thus user modifications are preserved between tasks. This has been done in a manner that should not break things like collection-based config (which may still differ from task to task.)
警告
This is a backwards incompatible change if you were relying on the post-0.12 behavior of cloning config objects between each task execution. Make sure to investigate if you find tasks affecting one another in unexpected ways!
[Feature] #418: Enhance ability of client libraries to override config filename prefixes. This includes modifications to related functionality, such as how env var prefixes are configured.
警告
This is a backwards incompatible change if:
you were relying on the
env_prefixkeyword argument toConfig.__init__; it is now theprefixorenv_prefixclass attribute, depending.or the kwarg/attribute of the same name in
Program.__init__; you should now be subclassingConfigand using itsenv_prefixattribute;or if you were relying on how standalone
Configobjects defaulted to having aNonevalue forenv_prefix, and thus loaded env vars without anINVOKE_style prefix.See new documentation for this functionality at Customizing the configuration system’s defaults for details.
[Feature] #232: Add support for
.yml-suffixed config files (in addition to.yaml,.jsonand.py.) Thanks to Matthias Lehmann for the original request & Greg Back for an early patch.[Bug] #430: Fallback importing of PyYAML when Invoke has been installed without its vendor directory, was still trying to import the vendorized module names (e.g.
yaml2oryaml3instead of simplyyaml). This has been fixed, thanks to Athmane Madjoudj.[Bug] #432: Tighten application of IO thread
jointimeouts (inrun) to only happen when #351 appears actually present. Otherwise, slow/overworked IO threads had a chance of being joined before truly reading all data from the subprocess’ pipe.[Support]: Fixed some Python 2.6 incompatible string formatting that snuck in recently.
0.15.0 2017-02-14
[Feature]:
Config.clonegrew a newintokwarg allowing client libraries with their ownConfigsubclasses to easily “upgrade” vanilla Invoke config objects into their local variety.[Feature] #421: Updated
Config.clone(and a few other related areas) to replace use ofcopy.deepcopywith a less-rigorous but also less-likely-to-explode recursive dict copier. This prevents frustratingTypeErrorswhile still preserving barriers between different tasks’ configuration values.[Feature]:
Config’s internals got cleaned up somewhat; end users should not see much of a difference, but advanced users or authors of extension code may notice the following:Direct modification of config data (e.g.
myconfig.section.subsection.key = 'value'in user/task code) is now stored in its own config ‘level’/data structure; previously such modifications simply mutated the central, ‘merged’ config cache. This makes it much easier to determine where a final observed value came from, and prevents accidental data loss.Ditto for deleted values.
Merging/reconciliation of the config levels now happens automatically when data is loaded or modified, which not only simplifies the object’s lifecycle a bit but allows the previous change to function without requiring users to call
.merge()after every modification.
[Bug] #413: Update behavior of
DataProxy(used withinContextandConfig) again, fixing two related issues:Creating new configuration keys via attribute access wasn’t possible: one had to do
config['foo'] = 'bar'becauseconfig.foo = 'bar'would set a real attribute instead of touching configuration.Supertypes’ attributes weren’t being considered during the “is this a real attribute on
self?” test, leading to different behavior between a nested config-value-as-attribute and a top-level Context/Config one.
[Bug]: Fix configuration framework such that nested or dict-like config values may be compared with regular dicts. Previously, doing so caused an
AttributeError(as regular dicts lack a.config).[Bug] #419: Optional parser arguments had a few issues:
The conceptual docs about CLI parsing mentioned them, but didn’t actually show via example how to enable the feature, implying (incorrectly) that they were active always by default. An example has been added.
Even when enabled, they did not function correctly when their default values were of type
bool; in this situation, trying to give a value (vs just giving the flag name by itself) caused a parser error. This has been fixed.
Thanks to
@ouroboroscodingfor the report.[Bug]: Configuration keys named
configwere inadvertently exposing the internal dict representation of the containing config object, instead of displaying the actual value stored in that key. (Thus, a set config ofmycontext.foo.bar.configwould act as if it was the key/value contents of themycontext.foo.barsubtree.) This has been fixed.[Bug]: Python 3’s hashing rules differ from Python 2, specifically:
A class that overrides
__eq__()and does not define__hash__()will have its__hash__()implicitly set to None.Config(specifically, its foundational classDataProxy) only defined__eq__which, combined with the above behavior, meant thatConfigobjects appeared to hash successfully on Python 2 but yieldedTypeErrorson Python 3.This has been fixed by explicitly setting
__hash__ = Noneso that the objects do not hash on either interpreter (there are no good immutable attributes by which to define hashability).[Bug] #426:
DataProxybased classes likeConfigandContextdidn’t like beingpickledorcopiedand threwRecursionError. This has been fixed.[Support] #204: (via #412) Fall back to globally-installed copies of our vendored dependencies, if the import from the
vendortree fails. In normal situations this won’t happen, but it allows advanced users or downstream maintainers to nukevendor/and prefer explicitly installed packages of e.g.six,pyyamlorfluidity. Thanks to Athmane Madjoudj for the patch.
0.14.0 2016-12-05
[Feature] #369: Overhaul the autoresponse functionality for
runso it’s significantly more extensible, both for its own sake and as part of implementing #294 (see its own changelog entry for details).警告
This is a backwards incompatible change: the
responseskwarg torun()is nowwatchers, and accepts a list ofStreamWatcherobjects (such asResponder) instead of a dict.If you were using
run(..., responses={'pattern': 'response'}previously, just update to instead userun(..., watchers=[Responder('pattern', 'response')]).[Feature] #294: Implement
Context.sudo, which wrapsruninside asudocommand. It is capable of auto-responding tosudo’s password prompt with a configured password, and raises a specific exception (AuthFailure) if that password is rejected.[Feature]: Update implementation of
Resultso it has default values for all parameters/attributes. This allows it to be more easily used when mockingruncalls in client libraries’ tests.警告
This is a backwards incompatible change if you are manually instantiating
Resultobjects with positional arguments: positional argument order has changed. (Compare the API docs between versions to see exactly how.)[Feature]: Add a
MockContextclass for easier testing of user-written tasks and related client code. Includes adding a conceptual document on how to test Invoke-using code.[Feature] #406: Update handling of Ctrl-C/
KeyboardInterrupt, and subprocess exit status pass-through, to be more correct than before:Submit the interrupt byte sequence
\x03to stdin of all subprocesses, instead of sendingSIGINT.This results in behavior closer to that of truly pressing Ctrl-C when running subprocesses directly; for example, interactive programs like
vimorpythonnow behave normally instead of prematurely exiting.Of course, programs that would normally exit on Ctrl-C will still do so!
The exit statuses of subprocesses run with
pty=Trueare more rigorously checked (usingos.WIFEXITEDand friends), allowing us to surface the real exit values of interrupted programs instead of manually assuming exit code130.Typically, this will be exit code
-2, but it is system dependent.Other, non-Ctrl-C-driven signal-related exits under PTYs should behave better now as well - previously they could appear to exit
0!
Non-subprocess-related
KeyboardInterrupt(i.e. those generated when running top level Python code outside of anyrunfunction calls) will now trigger exit code1, as that is how the Python interpreter typically behaves if youKeyboardInterruptit outside of a live REPL.
警告
These changes are backwards incompatible if you were relying on the “exits
130” behavior added in version 0.13, or on the (incorrect)SIGINTmethod of killing pty-driven subprocesses on Ctrl-C.[Feature]: Expose the (normalized) value of
run’shideparameter in its return-valueResultobjects.[Bug]: Fix a bug in
Config.clonewhere it was instantiating a newConfiginstead of a member of the subclass.[Bug]: Correctly raise
TypeErrorwhen unexpected keyword arguments are given torun.[Bug] #58: Work around bugs in
select()when handling subprocess stream reads, which was causing poor behavior in many nontrivial interactive programs (such asvimand other fullscreen editors,pythonand other REPLs/shells, etc). Such programs should now be largely indistinguishable from their behavior when run directly from a user’s shell.[Bug]: Fix
DataProxy(used withinContextandConfig) so that real attributes and methods which are shadowed by configuration keys, aren’t proxied to the config during regular attribute get/set. (Such config keys are thus required to be accessed via dict-style only, or (onContext) via the explicit.configattribute.)[Bug] #283: Fix the concepts/library docs so the example of an explicit
namespace=argument correctly shows wrapping an imported task module in aCollection. Thanks to@zaistefor the report.[Bug] #288: Address a bug preventing reuse of Invoke as a custom binstub, by moving
--listinto the “core args” set of flags present on all Invoke-derived binstubs. Thanks to Jordon Mears for catch & patch.[Bug] #349: Display the string representation of
UnexpectedExitwhen handling it inside ofProgram(including regularinv), if any output was hidden during therunthat generated it.Previously, we only exited with the exception’s stored exit code, meaning failures of
run(..., hide=True)commands were unexpectedly silent. (Library-style use of the codebase didn’t have this problem, since tracebacks aren’t muted.)While implementing this change, we also tweaked the overall display of
UnexpectedExitso it’s a bit more consistent & useful:noting “hey, you ran with
pty=True, so there’s no stderr”;showing only the last 10 lines of captured output in the error message (users can, of course, always manually handle the error & access the full thing if desired);
only showing a given stream when it was not already printed to the user’s terminal (i.e. if
hide=False, no captured output is shown in the error text; ifhide='stdout', only stdout is shown in the error text; etc.)
Thanks to Patrick Massot for the original bug report.
0.13.0 2016-06-09
[Feature] #67: Added
shelloption torun, allowing control of the shell used when invoking commands. Previously,pty=Trueused/bin/bashandpty=False(the default) used/bin/sh; the new unified default value is/bin/bash.Thanks to Jochen Breuer for the report.
[Feature] #259: (also #280) Allow updating (or replacing) subprocess shell environments, via the
envandreplace_envkwargs torun. Thanks to Fotis Gimian for the report,@philtayfor an early version of the final patch, and Erich Heine & Vlad Frolov for feedback.[Feature] #114: Ripped off the band-aid and removed non-contextualized tasks as an option; all tasks must now be contextualized (defined as
def mytask(context, ...)- see 定义和运行任务函数) even if not using the context. This simplifies the implementation as well as users’ conceptual models. Thanks to Bay Grabowski for the patch.警告
This is a backwards incompatible change!
[Bug] #152: (also #251, #331) Correctly handle
KeyboardInterruptduringrun, re: both mirroring the interrupt signal to the subprocess and capturing the local exception within Invoke’s CLI handler (so there’s no messy traceback, just exiting with code130).Thanks to Peter Darrow for the report, and to Mika Eloranta & Máté Farkas for early versions of the patchset.
[Bug] #351: Protect against
rundeadlocks involving exceptions in I/O threads & nontrivial amounts of unread data in the corresponding subprocess pipe(s). This situation should now always result in exceptions instead of hangs.[Bug] #350: (also #274, #241, #262, #242, #321, #338) Clean up and reorganize encoding-related parts of the code to avoid some of the more common or egregious encode/decode errors surrounding clearly non-ASCII-compatible text. Bug reports, assistance, feedback and code examples courtesy of Paul Moore, Vlad Frolov, Christian Aichinger, Fotis Gimian, Daniel Nunes, and others.
[Support] #314: (Partial fix.) Update
MANIFEST.inso source distributions include some missing project-management files (e.g. our internaltasks.py). This makes unpacked sdists more useful for things like running the doc or build tasks.[Support] #319: Fixed an issue resulting from #255 which caused problems with how we generate release wheels (notably, some releases such as 0.12.1 fail when installing from wheels on Python 2).
备注
As part of this fix, the next release will distribute individual Python 2 and Python 3 wheels instead of one ‘universal’ wheel. This change should be transparent to users.
Thanks to
@ojosfor the initial report and Frazer McLean for some particularly useful feedback.
0.12.2 2016-02-07
[Bug] #303: Make sure
runwaits for its IO worker threads to cleanly exit (such as allowing afinallyblock to revert TTY settings) whenKeyboardInterrupt(or similar) aborts execution in the main thread. Thanks to Tony S Yu and Máté Farkas for the report.[Support] #314: (Partial fix.) Update
MANIFEST.inso source distributions include some missing project-management files (e.g. our internaltasks.py). This makes unpacked sdists more useful for things like running the doc or build tasks.
0.12.1 2016-02-03
[Bug] #289: Handful of issues, all fallout from #289, which failed to make it out the door for 0.12.0. More are on the way but these should address blockers for some users:
Windows support for the new stdin replication functionality (this was totally blocking Windows users, as reported in #302 - sorry!);
Stdin is now mirrored to stdout when no PTY is present, so you can see what you’re typing (plus a new
runoption and config param,echo_stdin, allowing user override of this behavior);Exposed the stdin read loop’s sleep time as
Runner.input_sleep;Sped up some tests a bit.
[Bug] #305: (also #306) Fix up some test-suite issues causing failures on Windows/Appveyor. Thanks to Paul Moore.
[Bug] #308: Earlier changes to TTY detection & its use in determining features such as stdin pass-through, were insufficient to handle edge cases such as nested Invoke sessions or piped stdin to Invoke processes. This manifested as hangs and
OSErrormessages about broken pipes.The issue has been fixed by overhauling all related code to use more specific and accurate checks (e.g. examining just
filenoand/or justisatty).Thanks to Tuukka Mustonen and Máté Farkas for the report (and for enduring the subsequent flood of the project maintainer’s stream-of-consciousness ticket updates).
0.12.0 2016-01-12
[Feature] #173: Overhauled top level CLI functionality to allow reusing Invoke for distinct binaries, optionally with bundled task namespaces as subcommands. As a side effect, this functionality is now much more extensible to boot. Thanks to Erich Heine for feedback/suggestions during development.
警告
This change is backwards incompatible if you imported anything from the
invoke.climodule (which is now rearchitected asProgram). It should be transparent to everybody else.[Feature] #228: (partial) Modified and expanded implementation of
Executor,TaskandCallto make implementing task parameterization easier.[Feature] #289: (also #263) Implement autoresponding for
run.[Feature] #68: Disable Python’s bytecode caching by default, as it complicates our typical use case (frequently-changing .py files) and offers little benefit for human-facing startup times. Bytecode caching can be explicitly re-enabled by specifying
--write-pycat runtime. Thanks to Jochen Breuer for feature request and@brutusfor initial patchset.[Bug]: Fixed a bug in the parser where
invoke --takes-optional-arg avalue --anotherflagwas incorrectly considering--anotherflagto be an ambiguity error (as ifavaluehad not been given to--takes-optional-arg.[Bug] #295: Make sure that
run’shide=Truealso disables echoing. Otherwise, “hidden” helperruncalls will still pollute output when run as e.g.invoke --echo ....[Bug] #296: Don’t mutate
sys.pathon collection load if task’s parent directory is already onsys.path.[Bug] #297: Ignore leading and trailing underscores when turning task arguments into CLI flag names.
[Bug] #257: Fix a RecursionError under Python 3 due to lack of
__deepcopy__onCallobjects. Thanks to Markus Zapke-Gründemann for initial report and Máté Farkas for the patch.[Support]: Fix incorrect changelog URL in package metadata.
[Support]: Removed the
-Hshort flag, leaving just--hide. This was done to avoid conflicts with Fabric’s host-oriented-Hflag. Favoritism is real! Apologies.警告
This change is backwards compatible if you used
-H.[Support]: Removed official Python 3.2 support; sibling projects also did this recently, it’s simply not worth the annoyance given the userbase size.
[Support] #144: Add code-coverage reporting to our CI builds (albeit CodeCov instead of coveralls.io). Includes rejiggering our project-specific coverage-generating tasks. Thanks to David Baumgold for the original request/PR and to Justin Abrahms for the tipoff re: CodeCov.
[Support] #254: Add an
excludeoption in oursetup.pyso setuptools doesn’t try loading our vendored PyYAML’s Python 2 sub-package under Python 3 (or vice versa - though all reports were from Python 3 users). Thanks to@yoshiya0503for catch & initial patch.[Support] #265: Update our Travis config to select its newer build infrastructure and also run on PyPy3. Thanks to Omer Katz.
0.11.1 2015-09-07
[Support]: Fix incorrect changelog URL in package metadata.
0.11.0 2015-09-07
[Feature] #235: Allow custom stream objects to be used in
runcalls, to be used instead of the defaults ofsys.stdout/sys.stderr.警告
This change required a major cleanup/rearchitecture of the command execution implementation. The vendored
pexpectmodule has been completely removed and the API of theRunnerclass has changed dramatically (though the API for run() itself has not).Be aware there may be edge-case terminal behaviors which have changed or broken as a result of removing
pexpect. Please report these as bugs! We expect to crib small bits of whatpexpectdoes but need concrete test cases first.[Feature]: Detect local controlling terminal size (
pty_size) and apply that information when creating pseudoterminals inrunwhenpty=True.[Feature]: Add a
.commandattribute toResultto preserve the command executed for post-execution introspection.[Bug] #238: (partial fix) Update the
zshcompletion script to account for use of the--collectioncore flag.[Bug] #239: Completion erroneously presented core flags instead of per-task flags when both are present in the invocation being completed (e.g.
inv --debug my_task -<tab>). This has been fixed.[Bug] #237: Completion output lacked “inverse” flag names (e.g.
--no-myoptionas a boolean negative version of a defaulting-to-True booleanmyoption). This has been corrected.[Bug] #234: (also #243) Preserve task-module load location when creating explicit collections with
from_module; when this was not done, project-local config files were not loading correctly. Thanks to@brutusand Jan Willems for initial report & troubleshooting, and to Greg Back for identifying the fix.[Bug]: Capture & reraise exceptions generated by command execution I/O threads, in the main thread, as a
ThreadException.[Bug]: Correctly handle situations where
sys.stdinhas been replaced with an object lacking.fileno(e.g., some advanced Python shells, headless code execution tools, etc). Previously, this situation resulted in anAttributeError.[Bug]: Display stdout instead of stderr in the
repr()ofFailureobjects, when a pseudo-terminal was used. Previously, failure display focused on the stderr stream, which is always empty under pseudo-terminals.[Support]: Tweak README to reflect recent(-ish) changes in
pipre: users who install the development version viapipinstead of using git.[Support] #224: Add a completion script for the
fishshell, courtesy of Jaime Marquínez Ferrándiz.[Support]: Additional rearranging of
run/Runnerrelated concerns for improved subclassing, organization, and use in other libraries, including:Changed the name of the
runnermodule torunners.Moved the top level
runfunction from its original home ininvoke.runnertoinvoke.__init__, to reflect the fact that it’s now simply a convenience wrapper aroundRunner.Tweaked the implementation of
Runnerso it can referenceContextobjects (useful for anticipated subclasses).
警告
These are backwards incompatible changes if your code was doing any imports from the
invoke.runnermodule (including especiallyinvoke.runner.run, which is now onlyinvoke.run). Function signatures have not changed.
0.10.1 2015-03-17
[Support]: Tweak README to reflect recent(-ish) changes in
pipre: users who install the development version viapipinstead of using git.
0.10.0 2015-03-17
[Feature] #147: Drastically overhaul/expand the configuration system to account for multiple configuration levels including (but not limited to) file paths, environment variables, and Python-level constructs (previously the only option). See 配置 for details. Thanks to Erich Heine for his copious feedback on this topic.
警告
This is technically a backwards incompatible change, though some existing user config-setting code may continue to work as-is. In addition, this system may see further updates before 1.0.
[Feature] #219: Fall back to non-PTY command execution in situations where
pty=Truebut no PTY appears present. SeeLocalfor details.[Feature] #104: Add core CLI flag
--completeto support shell tab completion scripts, and add some ‘blessed’ such scripts for bash (3 and 4) and zsh. Thanks to Ivan Malison and Andrew Roberts for providing discussion & early patchsets.[Bug] #175:
autoprintdid not function correctly for tasks stored in sub-collections; this has been fixed. Credit: Matthias Lehmann.[Bug] #180: Empty invocation (e.g. just
invokewith no flags or tasks, and when no default task is defined) no longer printed help output, instead complaining about the lack of default task. It now prints help again. Thanks to Brent O’Connor for the catch.[Bug] #183: Task docstrings whose first line started on the same line as the opening quote(s) were incorrectly presented in
invoke --help <task>. This has been fixed by usinginspect.getdoc. Thanks to Pekka Klärck for the catch & suggested fix.[Bug] #191: Bypass
pexpect’s automatic command splitting to avoid issues running complex nested/quoted commands under a pty. Credit to@mijikaifor noticing the problem.[Bug] #201: (also #211) Replace the old, first-draft gross monkeypatched Popen code used for
invoke.runner.runwith a non-monkeypatched approach that works better on non-POSIX platforms like Windows, and also attempts to handle encoding and locale issues more gracefully (meaning: at all gracefully).Specifically, the new approach uses threading instead of
select.select, and performs explicit encoding/decoding based on detected or explicitly expressed encodings.Major thanks to Paul Moore for an enormous amount of testing/experimentation/discussion, as well as the bulk of the code changes themselves.
警告
The top level
invoke.runner.runfunction has had a minor signature change: the sixth positional argument used to berunnerand is nowencoding(withrunnernow being the seventh positional argument).[Support] #215: (also #213, #214) Tweak tests & configuration sections of the code to include Windows compatibility. Thanks to Paul Moore.
[Support] #212: Implement basic linting support using
flake8, and apply formatting changes to satisfy said linting. As part of this shakeup, also changed all old-style (%s) string formatting to new-style ({0}). Thanks to Collin Anderson for the foundational patch.[Support]: Reorganize
Runner,Localandinvoke.runner.runfor improved distribution of responsibilities & downstream subclassing.警告
This includes backwards incompatible changes to the API signature of most members of the
invoke.runnermodule, includinginvoke.runner.run. (However, in the case ofinvoke.runner.run, the changes are mostly in the later, optional keyword arguments.)
0.9.0 2014-08-26
[Feature] #136: Added the
autoprintflag toinvoke.tasks.Task/@task, allowing users to set up tasks which act as both subroutines & “print a result” CLI tasks. Thanks to Matthias Lehmann for the original patch.[Bug]: Fixed a sub-case of the already-mostly-fixed #149 so the error message works usefully even with no explicit collection name given.
[Bug] #162: Adjust platform-sensitive imports so Windows users don’t encounter import-time exceptions. Thanks to Paul Moore for the patch.
[Bug] #119: (also #162, #113) Better handle platform-sensitive operations such as pty size detection or use, either replacing with platform-specific implementations or raising useful exceptions. Thanks to Gabi Davar and (especially) Paul Moore, for feedback & original versions of the final patchset.
[Bug] #167: Running the same task multiple times in one CLI session was horribly broken; it works now. Thanks to Erich Heine for the report.
[Bug] #165: Running
inv[oke]with no task names on a collection containing a default task should (intuitively) have run that default task, but instead did nothing. This has been fixed.[Support] #169: Overhaul the Sphinx docs into two trees, one for main project info and one for versioned API docs.
0.8.2 2014-06-15
[Bug] #142: The refactored Loader class failed to account for the behavior of
imp.find_modulewhen run against packages (vs modules) and was exploding at load time. This has been fixed. Thanks to David Baumgold for catch & patch.[Bug] #145: Ensure a useful message is displayed (instead of a confusing exception) when listing empty task collections.
[Bug] #149: Print a useful message to stderr when Invoke can’t find the requested collection/tasks file, instead of displaying a traceback.
0.8.1 2014-06-09
[Bug] #140: Revert incorrect changes to our
setup.pyregarding detection of sub-packages such as the vendor tree & the parser. Also add additional scripting to our Travis-CI config to catch this class of error in future. Thanks to Steven Loria and James Cox for the reports.
0.8.0 2014-06-08
[Feature] #125: Improve output of Failure exceptions when printed.
[Feature] #124: Add a
--debugflag to the core parser to enable easier debugging (on top of existingINVOKE_DEBUGenv var.)[Feature] #87: (also #92) Rework the loader module such that recursive filesystem searching is implemented, and is used instead of searching
sys.path.This adds the behavior most users expect or are familiar with from Fabric 1 or similar tools; and it avoids nasty surprise collisions with other installed packages containing files named
tasks.py.Thanks to Michael Hahn for the original report & PR, and to Matt Iversen for providing the discovery algorithm used in the final version of this change.
警告
This is technically a backwards incompatible change (reminder: we’re not at 1.0 yet!). You’ll only notice if you were relying on adding your tasks module to
sys.pathand then calling Invoke elsewhere on the filesystem.[Feature] #110: Add task docstrings’ 1st lines to
--listoutput. Thanks to Hiroki Kiyohara for the original PR (with assists from Robert Read and James Thigpen.)[Feature] #115: Make it easier to reuse Invoke’s primary CLI machinery in other (non-Invoke-distributed) bin-scripts. Thanks to Noah Kantrowitz.
[Feature] #135: (also bugs #120, #123) Implement post-tasks to match pre-tasks, and allow control over the arguments passed to both (via
invoke.tasks.call). For details, see Pre- and post-tasks.警告
Pre-tasks were overhauled a moderate amount to implement this feature; they now require references to task objects instead of task names. This is a backwards incompatible change.
[Bug] #127: Fill in tasks’ exposed
nameattribute with body name if explicit name not given.[Bug] #116: Ensure nested config overrides play nicely with default tasks and pre-tasks.
[Bug] #131: Make sure one’s local tasks module is always first in
sys.path, even if its parent directory was already somewhere else insys.path. This ensures that local tasks modules never become hidden by third-party ones. Thanks to@crccheckfor the early report and to Dorian Puła for assistance fixing.[Bug] #121: Add missing help output denoting inverse Boolean options (i.e.
--[no-]foofor a--fooflag whose value defaults to true.) Thanks to Andrew Roberts for catch & patch.[Bug] #128: Positional arguments containing underscores were not exporting to the parser correctly; this has been fixed. Thanks to J. Javier Maestro for catch & patch.
[Support]: Refactor the
invoke.runners.Runnermodule to differentiate what it means to run a command in the abstract, from execution specifics. Top level API is unaffected.[Support] #117: Tidy up
setup.pya bit, including axing the (broken)distutilssupport. Thanks to Matt Iversen for the original PR & followup discussion.[Support] #118: Update the bundled
sixplus other minor tweaks to support files. Thanks to Matt Iversen.[Support] #25: Trim a bunch of time off the test suite by using mocking and other tools instead of dogfooding a bunch of subprocess spawns.
0.7.0 2014.01.28
[Feature] #107: Update configuration merging behavior for more flexible reuse of imported task modules, such as parameterizing multiple copies of a module within a task tree.
[Feature] #108: Update
invoke.collection.Collection.from_moduleto accept useful shorthand arguments for tweaking theinvoke.collection.Collectionobjects it creates (e.g. name, configuration.)[Feature] #109: Add a
defaultkwarg toinvoke.collection.Collection.add_taskallowing per-collection control over default tasks.
0.6.1 2013.11.21
[Bug] #98: BACKWARDS INCOMPATIBLE CHANGE! Configuration merging has been reversed so outer collections’ config settings override inner collections. This makes distributing reusable modules significantly less silly.
[Bug] #96: Tasks in subcollections which set explicit names (via e.g.
@task(name='foo')) were not having those names honored. This is fixed. Thanks to Omer Katz for the report.
0.6.0 2013.11.21
[Feature] #89: Implemented configuration for distributed task modules: can set config options in
invoke.collection.Collectionobjects and they are made available to contextualized tasks.[Bug] #86: Task arguments named with an underscore broke the help feature; this is now fixed. Thanks to Stéphane Klein for the catch.
0.5.1 2013.09.15
[Bug] #83: Fix a bug preventing underscored keyword arguments from working correctly as CLI flags (e.g.
mytask --my-argwould not map back correctly tomytask(my_arg=...).) Credit:@akitada.[Bug] #81: Fall back to sane defaults for PTY sizes when autodetection gives insane results. Thanks to
@akitadafor the patch.
0.5.0 2013.08.16
[Feature] #57: Optional-value flags added - e.g.
--footells the parser to set thefoooption value to True;--foo myvalsets the value to “myval”. The built-in--helpoption now leverages this feature for per-task help (e.g.--helpdisplays global help,--help mytaskdisplays help formytaskonly.)[Bug] #55: A bug in our vendored copy of
pexpectclashed with a Python 2->3 change in import behavior to prevent Invoke from running on Python 3 unless thesixmodule was installed in one’s environment. This was fixed - our vendoredpexpectnow always loads its sibling vendoredsixcorrectly.