New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin-specified PyB API version constraints #257

Closed
arcivanov opened this Issue Nov 19, 2015 · 9 comments

Comments

Projects
None yet
2 participants
@arcivanov
Contributor

arcivanov commented Nov 19, 2015

Plugins should be able to specify which versions of PyB they are compatible with. If there are breaking changes in the internal PyB APIs, PyB should be able to warn the user that plugin does not support the currently running version of PyB and should discontinue operation.

PyB should use SemVer to indicate compatibility:

  • <major> - revolutionary incompatible changes in major areas (extremely rare)
  • <minor> - evolutionary incompatible changes in some areas
  • <revision> - compatible revisions/bug fixes
@arcivanov

This comment has been minimized.

Show comment
Hide comment
@arcivanov

arcivanov Nov 19, 2015

Contributor

@mriehl feedback please

Contributor

arcivanov commented Nov 19, 2015

@mriehl feedback please

@mriehl

This comment has been minimized.

Show comment
Hide comment
@mriehl

mriehl Nov 19, 2015

Member

Yes agreed. But I'd try to start optimistically and only have plugins indicate a minimum version of PyBuilder (if they so wish).

I don't think a plugin should break by default because there was a major version increment since the incompatible change(s) might not affect the plugin at all.

A minimal version should be enforced though.

I guess some kind of static function that plugins can call à la

from pybuilder.core import declare_plugin

declare_plugin.for_api_version("0.14.0").and_greater()

# plugin code

would be a good start. Also we need to handle the case where PyBuilder is bootstrapping itself and has not replaced the ${version} (this happens during filter_resources).

Member

mriehl commented Nov 19, 2015

Yes agreed. But I'd try to start optimistically and only have plugins indicate a minimum version of PyBuilder (if they so wish).

I don't think a plugin should break by default because there was a major version increment since the incompatible change(s) might not affect the plugin at all.

A minimal version should be enforced though.

I guess some kind of static function that plugins can call à la

from pybuilder.core import declare_plugin

declare_plugin.for_api_version("0.14.0").and_greater()

# plugin code

would be a good start. Also we need to handle the case where PyBuilder is bootstrapping itself and has not replaced the ${version} (this happens during filter_resources).

@arcivanov

This comment has been minimized.

Show comment
Hide comment
@arcivanov

arcivanov Nov 19, 2015

Contributor

But I'd try to start optimistically and only have plugins indicate a minimum version of PyBuilder (if they so wish).

Agree.

I guess some kind of static function that plugins can call à la

I was thinking more along the lines of

pyb_version="<[PEP 0440](https://www.python.org/dev/peps/pep-0440/) version constraint>"

in __init__.py of the plugin package or in plugin module.

If no version is specified there is no check.

Contributor

arcivanov commented Nov 19, 2015

But I'd try to start optimistically and only have plugins indicate a minimum version of PyBuilder (if they so wish).

Agree.

I guess some kind of static function that plugins can call à la

I was thinking more along the lines of

pyb_version="<[PEP 0440](https://www.python.org/dev/peps/pep-0440/) version constraint>"

in __init__.py of the plugin package or in plugin module.

If no version is specified there is no check.

@mriehl

This comment has been minimized.

Show comment
Hide comment
@mriehl

mriehl Nov 19, 2015

Member

I am not sure I like the complexity this inversion of control introduces.

A library function would allow me as a plugin author to:

  • Handle the constraint failing (fallback to some code that does not take advantage of the newest API for example)
  • Decide when the constraint should be enforced - maybe I have 5 tasks but only one has an API version constraint. A library function would allow me to run it at plugin load time, initializer time or task runtime.

These things are important but hard to achieve with declarative style constraints like setting a local in the module toplevel.

Member

mriehl commented Nov 19, 2015

I am not sure I like the complexity this inversion of control introduces.

A library function would allow me as a plugin author to:

  • Handle the constraint failing (fallback to some code that does not take advantage of the newest API for example)
  • Decide when the constraint should be enforced - maybe I have 5 tasks but only one has an API version constraint. A library function would allow me to run it at plugin load time, initializer time or task runtime.

These things are important but hard to achieve with declarative style constraints like setting a local in the module toplevel.

@arcivanov

This comment has been minimized.

Show comment
Hide comment
@arcivanov

arcivanov Nov 19, 2015

Contributor

I'm not sure where you see the inversion of control here.

The plugin has access to pybuilder package and can look up and interpret pybuilder.__version__ anywhere in the init module, including @init already.

The case I'm targeting is whether the plugin should be at all initialized within the current build given the running PyB.
Example 1: A user upgrades PyB but some of the plugins are not compatible with the new version. Example 2: The owner of the plugin builds a new version that targets N+1 minor of PyB and user specifies use_plugin without plugin version specification or targeting a "latest" branch. PyB API ver N should not allow silent loading of a plugin declaring minimum of ver N+1 compatibility to load.

Having PEP 0440-style enforcement prevents any of the code (beyond module/package initializer) from running. If the plugin owner decides to use ostrich version checking (i.e. not using pyb_version) no check will be performed and the current behavior (load and use come hell or high water) is maintained.

Contributor

arcivanov commented Nov 19, 2015

I'm not sure where you see the inversion of control here.

The plugin has access to pybuilder package and can look up and interpret pybuilder.__version__ anywhere in the init module, including @init already.

The case I'm targeting is whether the plugin should be at all initialized within the current build given the running PyB.
Example 1: A user upgrades PyB but some of the plugins are not compatible with the new version. Example 2: The owner of the plugin builds a new version that targets N+1 minor of PyB and user specifies use_plugin without plugin version specification or targeting a "latest" branch. PyB API ver N should not allow silent loading of a plugin declaring minimum of ver N+1 compatibility to load.

Having PEP 0440-style enforcement prevents any of the code (beyond module/package initializer) from running. If the plugin owner decides to use ostrich version checking (i.e. not using pyb_version) no check will be performed and the current behavior (load and use come hell or high water) is maintained.

@arcivanov

This comment has been minimized.

Show comment
Hide comment
@arcivanov

arcivanov Nov 19, 2015

Contributor

To take a lesson from Mozilla Thunderbird plugins, for example, this is a common situation:

My plugin supports PyB versions 0.13.x but not 0.14.y, therefore pyb_version="~=0.13.0" and that's it.

I, as a plugin owner, decide that my plugin will not load with PyB 0.14 cause I have no clue what API changes might come there and don't want to risk incompliant or nonsensical behavior.

Contributor

arcivanov commented Nov 19, 2015

To take a lesson from Mozilla Thunderbird plugins, for example, this is a common situation:

My plugin supports PyB versions 0.13.x but not 0.14.y, therefore pyb_version="~=0.13.0" and that's it.

I, as a plugin owner, decide that my plugin will not load with PyB 0.14 cause I have no clue what API changes might come there and don't want to risk incompliant or nonsensical behavior.

@arcivanov

This comment has been minimized.

Show comment
Hide comment
@arcivanov

arcivanov Nov 19, 2015

Contributor

@locolupo @esc thoughts?

Contributor

arcivanov commented Nov 19, 2015

@locolupo @esc thoughts?

@mriehl

This comment has been minimized.

Show comment
Hide comment
@mriehl

mriehl Nov 19, 2015

Member

Yeah I gave it some more thought and you're right. The library function approach has the showstopper that it's not backwards compatible, whereas declaring a local at the module level is.

I guess I wanted to avoid look-before-you-leap constraints in plugin that lead to build crashes when the plugin would actually work fine, but at this point it's not much more than a crystal ball guess.

Agreed for the pep constraint in __init__.py.

Member

mriehl commented Nov 19, 2015

Yeah I gave it some more thought and you're right. The library function approach has the showstopper that it's not backwards compatible, whereas declaring a local at the module level is.

I guess I wanted to avoid look-before-you-leap constraints in plugin that lead to build crashes when the plugin would actually work fine, but at this point it's not much more than a crystal ball guess.

Agreed for the pep constraint in __init__.py.

@arcivanov

This comment has been minimized.

Show comment
Hide comment
@arcivanov

arcivanov Nov 20, 2015

Contributor

👍

Contributor

arcivanov commented Nov 20, 2015

👍

@arcivanov arcivanov self-assigned this Nov 20, 2015

@arcivanov arcivanov added this to the v0.11.3 milestone Nov 20, 2015

arcivanov added a commit to arcivanov/pybuilder that referenced this issue Nov 24, 2015

arcivanov added a commit to arcivanov/pybuilder that referenced this issue Nov 24, 2015

arcivanov added a commit to arcivanov/pybuilder that referenced this issue Nov 24, 2015

@arcivanov arcivanov closed this in #271 Nov 27, 2015

@arcivanov arcivanov removed the in progress label Nov 27, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment