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
Deprecation of distutils
- slated for Python 3.12
#127
Comments
I am well aware of this issue and I have started working on this in the background. As you correctly mentioned, this is a deal breaker for py2exe, but we also have plenty of time to react. |
Hi @albertosottile, just a note that Versioneer hooks into py2exe like so: if 'py2exe' in sys.modules: # py2exe enabled?
from py2exe.distutils_buildexe import py2exe as _py2exe
class cmd_py2exe(_py2exe):
def run(self):
root = get_root()
cfg = get_config_from_root(root)
versions = get_versions()
target_versionfile = cfg.versionfile_source
print("UPDATING %s" % target_versionfile)
write_to_version_file(target_versionfile, versions)
_py2exe.run(self)
os.unlink(target_versionfile)
with open(cfg.versionfile_source, "w") as f:
LONG = LONG_VERSION_PY[cfg.VCS]
f.write(LONG %
{"DOLLAR": "$",
"STYLE": cfg.style,
"TAG_PREFIX": cfg.tag_prefix,
"PARENTDIR_PREFIX": cfg.parentdir_prefix,
"VERSIONFILE_SOURCE": cfg.versionfile_source,
})
cmds["py2exe"] = cmd_py2exe I'm following this thread, but please feel free to ping me if any changes related to moving away from distutils are going to affect us. |
Interesting, I was not aware of this. It is too early for me to know exactly how this will change, but I could imagine that your interface will be affected. I will report here progresses on this topic, once I start working on it. |
The setuptools branch contains code that does not explicitly depends on I would say this serves as an initial implementation idea on how I plan to overcome the deprecation. Further things that I would like to do before actually merging this are:
TIL that
(source: last line here) This actually poses a serious threat to the current py2exe code base that I am currently unsure how to tackle. @effigies If you inspect the branch, you might notice that the interface for your use case should be relatively unchanged, with the exception that now you have to import |
I finally thought to try building that To be sure, was this the correct way to build?
Result was: 0$ python setup.py py2exe
C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\_distutils\dist.py:262: UserWarning: Unknown distribution option: 'windows'
warnings.warn(msg)
C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\_distutils\dist.py:262: UserWarning: Unknown distribution option: 'console'
warnings.warn(msg)
C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\dist.py:530: UserWarning: Normalizing '5.4.2-alpha0+b78a2742' to '5.4.2a0+b78a2742'
warnings.warn(tmpl.format(**locals()))
Git short hash: b78a2742
running py2exe
Traceback (most recent call last):
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\setup.py", line 241, in <module>
setup(
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\_distutils\core.py", line 185, in setup
return run_commands(dist)
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\_distutils\core.py", line 201, in run_commands
dist.run_commands()
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\_distutils\dist.py", line 973, in run_commands
self.run_command(cmd)
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\dist.py", line 1217, in run_command
super().run_command(command)
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\setuptools\_distutils\dist.py", line 992, in run_command
cmd_obj.run()
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\py2exe\setuptools_buildexe.py", line 151, in run
self._run()
File "C:\Users\Athan\Documents\Devel\EDMarketConnector\venv\lib\site-packages\py2exe\setuptools_buildexe.py", line 169, in _run
dist.console = runtime.fixup_targets(dist.console, "script")
AttributeError: 'Distribution' object has no attribute 'console' So, presumably I need to adjust our |
Aha! I had a look through your tests, and found the simple change of: from distutils.core import setup to: from py2exe import setup That's now built EDMarketConnector properly, and the .exe appears to be working. |
I apologize, I thought I had provided a link to the wheels, but it turns out I forgot to do that. Those were in the Actions artifacts, as usual, here: https://github.com/py2exe/py2exe/actions/runs/2700339964
I am glad you found it. Of course this interface change would have to be communicated clearly, most likely in the README. However, I am afraid it would not be the only one (see #127 (comment)).
That's great news! Thank you for having tested this. I am taking some time to think about how to solve the "stop invoking setup.py" issue, before moving this forward. Up to now the likely alternatives are to:
Those are both quite disruptive changes, but I am afraid I do not have any other choice. Would you have any preference? |
Our setup.py does more than just invoke py2exe, but the rest of that could be moved to another script if needs be (it's an .msi build, including poking translations into that). We have a We currently pass in things like:
So, we'd at least need to be able to pass in some "dynamic" customisation to the invocation of Relevant parts of our It would be quite the retooling to have a script instead edit just the correct section of |
Of course, py2exe would have its own
So, do I interpret this right that you would prefer a solution based on the |
If it would make the dynamic parts of our py2exe setup more difficult, then no. The script option would make for less work converting that over. |
Ok, but then I misunderstood your sentence entirely and so you would prefer a Python script to configure
The thing is, I am not so sure that either of the approaches would be specifically better for you, as both of them will most likely require to decouple the py2exe-related part from your script and invoke a new command (e.g. Because of what |
Except "recipe in the script" can easily be dynamic (e.g. importing current git HEAD short hash). Other than the script editing the pyproject.toml (possibly causing issues with preferred ordering of sections, and comments, depending on the tooling used to achieve this), I don't see how pyproject.toml would support this. Or am I ignorant of a method for a .toml file to have dynamic "call out to another program" / "also import this other file" abilities here ? |
Ah, I just found https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#dynamic-metadata ... I'll have a good look at that and see if I still forsee any problems with the pyproject.toml scenario. |
I see your problem now. Honestly, I have always perceived the I see you found Dynamic Metadata, which could be a solution, but I think the best solution would be to avoid the need for |
I somewhat prefer the dynamic way of things because then you only have to maintain the expression of that, rather than updating the same meta-data in many different places for a complete build. It was only in the last year or so that I got around to making our WiX .wxs file be dynamically generated, in order to ensure it always picked up all of the necessary files, particularly when To give another example, our 'appname' is both used in the It is sounding like, whatever solution you decide on, we'll end up needing our wrapper script to create/change some file dynamically, whether that's a recipe.py or pyproject.toml. In that scenario I'd prefer the former, as then it's a file used only by py2exe, whereas pyproject.toml will always have non-py2exe/setuptools things in it that we want preserved both in terms of data and ordering/comments. |
Thanks! I've opened a PR to smooth the transition at python-versioneer/python-versioneer#319. I wonder if it makes sense to keep around a import warnings
warnings.warn("py2exe.distutils_buildexe is deprecated; please import from py2exe.setuptools_buildexe",
DeprecationWarning)
from py2exe.setuptools_buildexe import * It might help with people who don't upgrade everything in quite the right order. |
@effigies I actually expect the vast majority of users will use the setup scripts and whatever interface |
@albertosottile My concern is for people with old versioneer. If they upgrade py2exe but not versioneer, then they'll get an |
@effigies I have been having second thoughts at all this, as it appears evident that setuptools wants to drop their I am asking this because I am debating whether I should deprecate this interface now and drop it entirely in the next major version that removes |
From the versioneer perspective, the commands I don't really understand the path forward for py2exe. I can say that if your command calls out to |
Well, I am trying to draft one. Because we cannot rely on the Therefore, I was now thinking of dropping the command extension entirely in favor of a new API that could look e.g. like this:
and has to be invoked e.g. like this
from any Python script. Something like this would simplify both the codebase and the migration for users that currently rely on |
I wonder if the cleanest thing would be for you to:
If that fits into your plans, then there's no real need for us to patch py2exe. People with a setuptools backend with versioneer hooks will give you an sdist/wheel with the dynamic bits already swapped out. And other build backends and version injection hacks would also be none of your problem. So from a user perspective, I'd probably want a pyproject.toml table like: [tool.py2exe]
console = [...]
... And then the build just becomes: python -m py2exe |
This goes in the opposite direction of what @Athanasius suggested a few posts above, which is to not put freezing information in the
I really like this and I have full intention of going towards this direction, as you may have noticed from the proposed Regarding this:
I am afraid this would require a lot of effort and so, for the moment, I do not intend to do so nor to make I have prepared a branch with this new @Athanasius
and then called as a regular Python script, no @effigies The API implementation is defined in |
A basic test shows that
However...
So something has caused Then I remembered we have a So, what should I be adding to the invocation in order to get more in the way of diagnostics as to why it chose to not include those packages ? |
Thank you very much for having tested this.
I realized this as well this morning and pushed a new build and edited the URL, but perhaps you still installed the old one. Could you try again with wheels from here: https://github.com/py2exe/py2exe/actions/runs/2998629292 ? Thanks
This is actually the only "general" attribute from |
It showed it had been edited, and it shows the same URL up in that comment as this one, yet ... to be clear that URL includes a This is still ignoring |
Interesting... could you add |
That made no difference. Of course if somehow the rebuild didn't pick up that small patch to actually use the py2exe options then nothing in there will be used and that would explain both the issues I'm seeing and tthe lack of thise verbose flag working. The Am I being blind and missing something ?
|
|
OK, I'm not going mad, and I must have been using that build artifact. I've gone and 26 print('Checking for global py2exe options key...')
27 if 'py2exe' in options:
28 print('Setting options to found py2exe options')
29 options = options['py2exe']
30 print(f'Options are now:\n{options=}') Using the resulting .whl from that I get:
And yet still:
|
Aha! This is because the code still has e.g. |
And with that change for all those arguments my |
Yeah I was just figuring that out, I used |
See py2exe/py2exe#127 for context This filename is still open to change, I don't want to just use `freeze.py`, as that seems too potentially ambiguous.
New wheels available here: https://github.com/py2exe/py2exe/actions/runs/3002400251 . Could you test the fix? Also, I would be glad if you could test the wheels against the former This endeavor showed me something interesting though: ALL the functional tests can work without any |
Once I remembered the download is a .zip file that I need to extract the .whl from ....
|
Great news! I think this is the preferred solution to this issue for direct users of
That constantly bothers me as well but... -> actions/upload-artifact#3 (comment) |
Hi, sorry about the slowness. Should probably confess that I neither use Windows nor py2exe. I'm just trying not to break things for projects that do. Would it be possible to get a project set up with I've forked https://github.com/pypa/sampleproject to https://github.com/effigies/sample-py2exe-versioneer and will set up versioneer on it when I get a few minutes. Would either of you be able to guide me in setting up py2exe on a Windows CI runner? |
The workflow we use for EDMC is here: https://github.com/EDCD/EDMarketConnector/blob/main/.github/workflows/windows-build.yml - it also includes extra stuff, but has the necessary setup steps. |
I see. You can give a look at what is done in the configuration of GitHub Actions of this repository: py2exe/.github/workflows/CI.yml Line 110 in 4301ec7
I gave a look in how versioneer works, in general, and it seems to me the dropping of the |
Hi @albertosottile @Athanasius I'm really not figuring this out. I've tried to create a module that's versioned by versioneer and use py2exe to turn a script into an exe. If I include https://github.com/effigies/sample-py2exe-versioneer/blob/main/setup.py Hopefully I'm making an error that will be very obvious to you. |
@effigies py2exe does not easily support the In this case, I would suggest you to adapt your test project as it follows:
try:
import sample
except ImportError:
from src import sample I tried these changes and I can build the sample project, though when the frozen code runs I get this: Hope this helps, let me know if you have any further issues. |
Thanks for the pointer! I think it's unlikely that people currently using versioneer+py2exe are doing it that way, if it's so painful, so I got rid of the That worked for On the other hand, if py2exe is looking in the Python path for modules to $ pip install .
$ python build_exe.py The two-step may not be entirely pleasing, but it does mean that |
I was not even able to get the version with Thank you @effigies and @Athanasius for your effort! |
Fixed in 0.12.0.0 |
See py2exe/py2exe#127 for context This filename is still open to change, I don't want to just use `freeze.py`, as that seems too potentially ambiguous.
I've been noticing this... probably since I first started using Python 3.10:
Do you have any plans for migrating py2exe itself away from using
distutils
?I have a vague memory of you deprecating use of
build_exe.exe
, but even if that's correct then it's still installed along with py2exe and will output a setup.py that usesdistutils
:Obivously there's currently plenty of time. Python 3.12 will likely be available around October 2023, so still 19 months to go yet. But it would still be better to address this sooner rather than later.
The text was updated successfully, but these errors were encountered: