Upgrading To Newer Releases

Click attempts the highest level of backwards compatibility but sometimesthis is not entirely possible. In case we need to break backwardscompatibility this document gives you information about how to upgrade orhandle backwards compatibility properly.

Upgrading to 3.2

Click 3.2 had to perform two changes to multi commands which weretriggered by a change between Click 2 and Click 3 that had biggerconsequences than anticipated.

Context Invokes

Click 3.2 contains a fix for the Context.invoke() function when usedwith other commands. The original intention of this function was toinvoke the other command as as if it came from the command line when itwas passed a context object instead of a function. This use was onlydocumented in a single place in the documentation before and there was noproper explanation for the method in the API documentation.

The core issue is that before 3.2 this call worked against intentions:

  1. ctx.invoke(other_command, 'arg1', 'arg2')

This was never intended to work as it does not allow Click to operate onthe parameters. Given that this pattern was never documented and illintended the decision was made to change this behavior in a bugfix releasebefore it spreads by accident and developers depend on it.

The correct invocation for the above command is the following:

  1. ctx.invoke(other_command, name_of_arg1='arg1', name_of_arg2='arg2')

This also allowed us to fix the issue that defaults were not handledproperly by this function.

Multicommand Chaining API

Click 3 introduced multicommand chaning. This required a change in howClick internally dispatches. Unfortunately this change was not correctlyimplemented and it appeared that it was possible to provide an API thatcan inform the super command about all the subcommands that will beinvoked.

This assumption however does not work with one of the API guarantees thathave been given in the past. As such this functionality has been removedin 3.2 as it was already broken. Instead the accidentally brokenfunctionality of the Context.invoked_subcommand attribute wasrestored.

If you do require the know which exact commands will be invoked there aredifferent ways to cope with this. The first one is to let the subcommandsall return functions and then to invoke the functions in aContext.resultcallback().

Upgrading to 2.0

Click 2.0 has one breaking change which is the signature for parametercallbacks. Before 2.0, the callback was invoked with (ctx, value)whereas now it's (ctx, param, value). This change was necessary as itotherwise made reusing callbacks too complicated.

To ease the transition Click will still accept old callbacks. Startingwith Click 3.0 it will start to issue a warning to stderr to encourage youto upgrade.

In case you want to support both Click 1.0 and Click 2.0, you can make asimple decorator that adjusts the signatures:

  1. import click
  2. from functools import update_wrapper
  3.  
  4. def compatcallback(f):
  5. # Click 1.0 does not have a version string stored, so we need to
  6. # use getattr here to be safe.
  7. if getattr(click, '__version__', '0.0') >= '2.0':
  8. return f
  9. return update_wrapper(lambda ctx, value: f(ctx, None, value), f)

With that helper you can then write something like this:

  1. @compatcallback
  2. def callback(ctx, param, value):
  3. return value.upper()

Note that because Click 1.0 did not pass a parameter, the param argumenthere would be None, so a compatibility callback could not use thatargument.