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

[RFC] [PoC] [WIP] Implement dynamic (SCM) version loader #672

Closed

Conversation

webknjaz
Copy link

@webknjaz webknjaz commented Nov 25, 2018

This PR provides a sketch of how the developed dist version hardcoding could be avoided.
It is not a final implementation, but rather a request for comments.

I'd like to identify:

  • Where is the right place to place this architecturally
  • What should be the public API to this feature.
    Currently it's a setup.cfg-like "attr: " tag referencing to an importable callable, which gives users a lot of flexibility while preserving poetry's built-in validation mechanisms
  • Should it rely on one version getter implementation or be flexibe?
  • Should it vendor some implementations or just have external/optional dependencies?
  • What should be user experience when they use this feature?
  • How does it influence the metadata?

Pull Request Check List

  • Added tests for changed code.
  • Updated documentation for changed code.

@webknjaz
Copy link
Author

cc @kevinkjt2000 @madig @escaped @RonnyPfannschmidt @glehmann @seglberg @whoiswes @psafont ^^

@@ -1,6 +1,6 @@
[tool.poetry]
name = "poetry"
version = "0.12.8"
version = "attr: setuptools_scm.get_version"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would there be a way to enable setuptools_scm to provide the version more directly?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, version arg is read unconditionally + I didn't notice any hooks in poetry

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course calling setuptools_scm could be hardcoded in python source, but that's a question about flexibility

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is meant by this question? It looks to me like the setuptools_scm library is directly responsible for providing the version in this example.

Copy link
Author

@webknjaz webknjaz Nov 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinkjt2000 This example only shows that users can refer to any callable they want. setuptools_scm has been chosen as a common example but any function will work. That's flexibility.
OTOH @RonnyPfannschmidt seems to want smth like use_version scm = True to work without having to refer to the function explicitly.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinkjt2000 for example in the setuptools integration we trigger the integration and the file finder via the setuptools plugin system

for the poetry integration something similar could be thinkable

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a mediocre dev at best and can't intelligently comment, but I would prefer to pass a callable to the config versus offering any integrations. That seems to offer the most flexibility and least complexity in my book.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may have a lack of understanding here, but to trigger the integration and the file finder via the setuptools plugin system is that not what the get_version function does?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinkjt2000 setuptools has entry_point-based hook system. Other packages can specify their entry points with those name to "register" their hook implementations and setuptools then automatically knows it can use them. Example: https://github.com/pypa/setuptools_scm/blob/master/setup.py#L69

Copy link

@kevinkjt2000 kevinkjt2000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it. Accepting a callable function should allow users to do what they want 😄
Still needs tests, of course.

@@ -8,6 +8,23 @@

class ProjectPackage(Package):
def __init__(self, name, version, pretty_version=None):
if isinstance(version, str) and version.startswith('attr:'):
version_pkg, _, version_attr = (
version[6:].strip().rpartition('.')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should "attr:function_name" be allowed, without a space after the colon?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? It's harmless and it's how it works in setuptools.

@@ -8,6 +8,23 @@

class ProjectPackage(Package):
def __init__(self, name, version, pretty_version=None):
if isinstance(version, str) and version.startswith('attr:'):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The init code would look a little cleaner by moving this code into a new function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it's just a PoC.

if version is None:
raise RuntimeError(
'The version getter callable must return a string '
'or a Version instance'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message here does not match what the conditional is checking.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this should be fixed.

__import__(version_pkg, fromlist=(version_pkg, )),
version_attr,
)
version = version_getter()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People may want to import a variable instead of a function. The setuptools_scm documentation shows an example in the programmatic usage section https://github.com/pypa/setuptools_scm#programmatic-usage
Checking if the attribute is callable would allow for this. https://docs.python.org/3/library/functions.html#callable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's different. Also the callable may as well return that constant.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constant declaration is already supported by setting it in pyproject.toml. There should be only one way to do it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable is dynamically determined; I do not think this is already supported by pyproject.toml. I think adding a small function wrapper that returns a variable is an acceptable thing. But a small if check for whether or not it is callable would support both. Tiny quality of life thing that saves writing a tiny function for people who copy/paste from setuptools_scm docs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're suggesting to put import-time evaluation in place, which is exactly what doomed setuptools. And now because of backwards compat they cannot fix this.
That's why I'm -1 here.
If one wants to access the installed version info from their code we could provide them a helper function to do so but let's not do import-time version detection. After all, app needs the version retrieved from pkg_resources in installed mode, it shouldn't invoke version-guessing flows in this case.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference in what is accomplished between a variable that holds the version, and a function that evaluates to a variable that holds the version? I was suggesting this:

if callable(version_getter):
    version = version_getter()
else:
    version = version_getter

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is that it encourages users to have

version = blah_blah()

called on during the module import, which is bad.

@glehmann
Copy link
Contributor

@warner, the python-versioneer author, might also be interested in this discussion :)

@webknjaz
Copy link
Author

@RonnyPfannschmidt would it make sense to reuse setuptools' entry points to retrieve the version getter from integrations? Do you think this'll make existing ones "just work"?

@RonnyPfannschmidt
Copy link

@webknjaz it would be highly problematic to try and replicate any of the hook systems of setuptools with sanity - it would never amount to more than a really ugly hack - i strongly advise towards having own integration points that match the design of poetry

@webknjaz
Copy link
Author

Good point. Let's see what @sdispater thinks...

@webknjaz webknjaz changed the title [PoC] [WIP] Implement dynamic (SCM) version loader [RFC] [PoC] [WIP] Implement dynamic (SCM) version loader Nov 25, 2018
@webknjaz
Copy link
Author

It looks like poetry has a similar plugin system: https://poetry.eustace.io/docs/pyproject/#plugins

@webknjaz
Copy link
Author

@sdispater what do you think?

@RonnyPfannschmidt
Copy link

@webknjaz as far as i understood, what you linked is how poetry declares entry-points - thats not yet an actual extension system, just metadata that pkg_resources or the entrypoints package may consume

@webknjaz
Copy link
Author

webknjaz commented Nov 30, 2018

@RonnyPfannschmidt it seems you're right, but it's the closest I've managed to google

@psafont
Copy link

psafont commented Nov 30, 2018

I'd also change the behaviour of poetry version to avoid conflicts with this feature.

Consider showing a message on how to tag the commit with the scm when a function is detected on the version field.

@webknjaz
Copy link
Author

Good catch!

@webknjaz
Copy link
Author

I won't make any changes to PR until I hear from @sdispater to avoid having to remake everything multiple times :)

@sdispater
Copy link
Member

Thanks for taking the time to make this PR.

I will hold off this feature for now though. This is until Poetry can provide a proper plugin system so that people can opt in this behavior by installing the correct plugin.

I can't give you an ETA since implementing a plugin system might take some time.

@webknjaz
Copy link
Author

webknjaz commented Nov 30, 2018

Sad to hear. Can we help with this somehow? This is one of the features which is holding me from switching to Poetry completely.

@webknjaz
Copy link
Author

webknjaz commented Dec 1, 2018

Is there any architectural vision on plugins at all, currently?

Ref #658

@webknjaz
Copy link
Author

webknjaz commented Dec 1, 2018

I thought I'd raise an actual issue about the plugin system: #693.

@zeebonk
Copy link

zeebonk commented Jan 6, 2019

@webjnjaz thanks for putting the time in this. This is also holding me back from using poetry.

@webknjaz
Copy link
Author

webknjaz commented Jan 6, 2019

@zeebonk
Copy link

zeebonk commented Jan 7, 2019

@webknjaz that's great news! Subscribed :)

@sdispater
Copy link
Member

Closing this for now. I'll ping you when the plugin system is implemented.

@sdispater sdispater closed this Mar 6, 2019
@webknjaz
Copy link
Author

webknjaz commented Mar 6, 2019

Okay, thanks

Copy link

github-actions bot commented Mar 1, 2024

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants