Skip to content
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

Have a unified way of showing info about installed plugins #87

Closed
obestwalter opened this issue Sep 11, 2017 · 15 comments
Closed

Have a unified way of showing info about installed plugins #87

obestwalter opened this issue Sep 11, 2017 · 15 comments
Milestone

Comments

@obestwalter
Copy link
Member

When implementing tox-dev/tox#544 a discussion arose about what it should look like when you output version information about the tool.

tox-dev/tox#628 (comment)

So I leave that suggestion here, that pluggy could provide a higher level API to output version information and maybe with different levels of exactness/verbosity (e.g. full paths, vs. just names and versions).

@goodboy
Copy link
Contributor

goodboy commented Sep 12, 2017

Huh, yeah I guess we don't have anything for that yet.

@RonnyPfannschmidt @obestwalter what were you thinking?

How bout

version, path = PluginManager.get_info(plugin_name)

@RonnyPfannschmidt
Copy link
Member

get_info is pretty much nonsaying, its not an acceptable api

@obestwalter
Copy link
Member Author

obestwalter commented Sep 12, 2017

I think we should figure out what in general a command line tool using pluggy should output when whatever --version is invoked.

tox current version (no pluggy information at all):

2.7.0 imported from /home/oliver/.virtualenvs/ubng/lib/python3.6/site-packages/tox/__init__.py

tox dev version (fetching pluggy info via):

https://github.com/tox-dev/tox/blob/aa05d0fd625322bad1fb451ef2e192523061d831/tox/config.py#L263-L272

tox --version
2.8.2.dev32 imported from /home/oliver/work/tox/tox/tox/__init__.py
registered plugins:
    tox-durations-0.1 at /home/oliver/.virtualenvs/tox/lib/python3.6/site-packages/tox_durations.py
    detox-0.11 at /home/oliver/.virtualenvs/tox/lib/python3.6/site-packages/detox/tox_proclimit.py

for pytest:

This is pytest version 3.1.0, imported from /home/oliver/.virtualenvs/ubng/lib/python3.6/site-packages/pytest.py
setuptools registered plugins:
  pytest-xdist-1.16.0 at /home/oliver/.virtualenvs/ubng/lib/python3.6/site-packages/xdist/plugin.py
  pytest-xdist-1.16.0 at /home/oliver/.virtualenvs/ubng/lib/python3.6/site-packages/xdist/boxed.py
  pytest-xdist-1.16.0 at /home/oliver/.virtualenvs/ubng/lib/python3.6/site-packages/xdist/looponfail.py
  pytest-cov-2.5.1 at /home/oliver/.virtualenvs/ubng/lib/python3.6/site-packages/pytest_cov/plugin.py

pytest also outputs the version info to stderr, which I find strange, but that is another topic.

Pluggy should offer a function that returns a string representation of all relevant information about what is installed through it and how (and maybe with different verbosity levels, if that makes sense). I do not know too much about pluggy yet, so I don't know what information is there and how it should be presented.

I am quite happy though with that comes back from list_plugin_distinfo() and having the full paths helps with debugging things, but maybe if it is always the same path it is enough to display it once for all setuptools installed plugins.

I also think that the info should say that those pugins are installed via pluggy (and then maybe more concrete info about the mechanism, e.g. setuptools).

@obestwalter
Copy link
Member Author

So, basically not much different of what we now construct from list_plugin_distinfo() but standardized with all the pugyy insider knowledge right from the source, so as an hypothetic example:

plugins registered via pluggy 0.8.7:
    - registered through setuptools entry point <path to wherever file modules are installed from>
        - super-plugin 1.2.3
        - other-plugin -3.4.a1
    - registered from outer space:
        - space-balls 2

@obestwalter
Copy link
Member Author

for good measure - here is what devpi does:

devpi --version
devpi-client 2.7.0

current devpi server: https://devpi.net/
    devpi-findlinks 2.0.0
    devpi-server 4.3.1rc1
    devpi-web 3.2.1rc1

@obestwalter
Copy link
Member Author

I still think it would be good to consolidate this functionality into pluggy instead of everybody baking their own thing.

@RonnyPfannschmidt
Copy link
Member

the main question is api
for example, a setuptools plugin cant tell pluggy if a plugin object added is part of it or not

until then i believe its fine just to have a helper that lists names and versions for setuptools plugins off a pluginmanager

@obestwalter
Copy link
Member Author

obestwalter commented Apr 17, 2018

Can you explain that problem further? I don't get it. From the perspective of a maintainer of a project using pluggy I would like to have a convenience method to give me a human readable version of the installed plugins. What I did in tox was simply:

def get_version_info(pm):
    out = ["%s imported from %s" % (tox.__version__, tox.__file__)]
    plugin_dist_info = pm.list_plugin_distinfo()
    if plugin_dist_info:
        out.append('registered plugins:')
        for mod, egg_info in plugin_dist_info:
            source = getattr(mod, '__file__', repr(mod))
            out.append("    %s-%s at %s" % (
                egg_info.project_name, egg_info.version, source))
    return '\n'.join(out)

This is running happily for quite a while now and I haven't seen any problems with it yet:

I am pretty sure that if we put our heads together we can come up with a bit more generalized version of that that catches some corner cases I might not have foreseen (which is another reason, why I would rather have a proper wrapper directly from pluggy rather then digging around in the guts).

Regarding API and naming things I could think of several ways: e.g. adding a human_readable parameter to list_plugin_distinfo that is False by default and if passed True gives back basically what I am putting together manually as a string.

Or make that parameter more versatile by passing in a string that asks for the info in one of several formats.

Or add a method display_plugin_distinfo that yields the human readable version. I don't really care TBH as long as it is documented :)

@obestwalter
Copy link
Member Author

obestwalter commented Apr 17, 2018

pytest: https://github.com/pytest-dev/pytest/blob/master/_pytest/helpconfig.py#L154

def getpluginversioninfo(config):
    lines = []
    plugininfo = config.pluginmanager.list_plugin_distinfo()
    if plugininfo:
        lines.append("setuptools registered plugins:")
        for plugin, dist in plugininfo:
            loc = getattr(plugin, '__file__', repr(plugin))
            content = "%s-%s at %s" % (dist.project_name, dist.version, loc)
            lines.append("  " + content)
	return lines

@obestwalter
Copy link
Member Author

looks like pytest even grew two ways of doing the same thing already? I did not look to closely but here it is: https://github.com/pytest-dev/pytest/blob/master/_pytest/terminal.py#L455

https://github.com/pytest-dev/pytest/blob/master/_pytest/terminal.py#L736

def _plugin_nameversions(plugininfo):
    values = []
    for plugin, dist in plugininfo:
        # gets us name and version!
        name = '{dist.project_name}-{dist.version}'.format(dist=dist)
        # questionable convenience, but it keeps things short
        if name.startswith("pytest-"):
            name = name[7:]
        # we decided to print python package names
        # they can have more than one plugin
        if name not in values:
            values.append(name)
return values

@obestwalter
Copy link
Member Author

devpi server does save the generated output in a dict and sorts the stuff (good idea), but not fundamentally different: https://github.com/devpi/devpi/blob/master/server/devpi_server/main.py#L309

         threadlog.info("Found plugin %s-%s (%s)." % (
                distinfo.project_name, distinfo.version, distinfo.location))
            key = (distinfo.project_name, distinfo.version)
            if key not in version_info:
                version_info.append(key)
        version_info.sort()
pyramid_config.registry['devpi_version_info'] = version_info

@RonnyPfannschmidt
Copy link
Member

i beleive an api getting a sorted by name list of unique setuptools plugins might be a nice point - it should be a helper function not part of the pluginmanager

@obestwalter
Copy link
Member Author

it should be a helper function not part of the pluginmanager

I think it should be part of the plugin manager, because pluginmanager.list_plugin_distinfo() is providing the same knowledge but in a different format. My ideal solution would actually be to enhance the function itself to provide the same knowledge in a human digestible format. I would have to feed the helper function the output of the function anyway, so this is just shoving data around unnecessarily. to clarify: as a programmer using pluggy I would find this a bit unwieldy for the job at hand:

pluggy.human_readable_version_info(pluginmanager.list_plugin_distinfo()

I would prefer something like this:

pluginmanager.list_plugin_distinfo(format='human_readable')

@RonnyPfannschmidt
Copy link
Member

@obestwalter depending on circumstances human readable is pain text, formatteddifferently, maybe html, maybe terminal encoded ^^ plus different implementation may choose to behave different in different circumstances (like list distributions vs list actual plugins) - there is a lot of choice possible and its all presentation logic thats completely unrelated to actual plugin management - as such i beleive its best experimented with and implemented with as an external consumer of pluginmanager, not as a part of it

@goodboy goodboy mentioned this issue Apr 30, 2018
@goodboy goodboy added this to the 1.0 milestone Nov 9, 2018
@obestwalter
Copy link
Member Author

Greetings. I am going through old issues and I think this can be closed as not really worth following up on.

As @RonnyPfannschmidt said:

... as such i beleive its best experimented with and implemented with as an external consumer of pluginmanager, not as a part of it

@RonnyPfannschmidt RonnyPfannschmidt closed this as not planned Won't fix, can't repro, duplicate, stale Jun 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants