Skip to content

Commit

Permalink
Workaround for setuptools distribution autodiscovery
Browse files Browse the repository at this point in the history
This introduces a ``setuptools.finalize_distribution_options``
that sets the *name* and *py_modules* attributes of the
distribution in a way that is compatible with py2app's regular
calculation of these attributes.

This avoid problems with setuptools 61.0.0 or later that
use autodiscovery to set these attributes to values that may
not be compatible with py2app.

Issue #414
  • Loading branch information
ronaldoussoren committed Apr 7, 2022
1 parent d2423cc commit 55eb236
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 12 deletions.
25 changes: 15 additions & 10 deletions doc/changelog.rst
Expand Up @@ -4,20 +4,25 @@ Release history
py2app 0.28
-----------

.. warning:: incompatibility with setuptools 61.0
* #414 Workaround for autodiscovery in setuptools 61.0

Setuptools 61.0 introduces autodiscovery of distribution
attributes, and this might affect users of py2app. Two
related error scenario's are:
Setuptools 61.0 introduces autodiscovery of distribution
attributes, and that broke py2app. This version introduces
a ``setuptools.finalize_distribution_options`` entrypoint
in py2app that will set the distributions's *name* and
*py_modules* attributes in a way that is compatible with
the main code of py2app when they are not yet set (before
autodiscovery kicks in).

- The name of the generated application is not based on
the script name, but some other value.
In older versions of py2app buildin an app can fail in two
ways with setuptools 61.0 or later:

- Calling ``python setup.py py2app`` results in an error
mentioning ``Multiple top-level modules discovered``.
- The name of the generated application is not based on
the script name, but some other value.

- Calling ``python setup.py py2app`` results in an error
mentioning ``Multiple top-level modules discovered``.

To disable autodiscovery by setuptools update the setup.py
file and add ``name=`` and ``py_modules=[]`` to the call to setup().

* PR #418: Add recipe for black

Expand Down
38 changes: 36 additions & 2 deletions py2app/build_app.py
Expand Up @@ -90,6 +90,36 @@
else:
sys_base_prefix = sys.prefix

def finalize_distribution_options(dist):
"""
setuptools.finalize_distribution_options extension
point for py2app, to deail with autodiscovery in
setuptools 61.
This addin will set the name and py_modules attributes
when a py2app distribution is detected that does not
yet have these attributes.
are not already set
"""
if (getattr(dist, "app", None) is None and
getattr(dist, "plugin", None) is None):
return

if getattr(dist.metadata, "py_modules", None) is None:
dist.py_modules = []

name = getattr(dist.metadata, "name", None)
if name is None or name == "UNKNOWN":
if dist.app:
targets = FixupTargets(dist.app, "script")
else:
targets = FixupTargets(dist.plugin, "script")

base = targets[0].get_dest_base()
name = os.path.basename(base)

dist.metadata.name = name


def loader_paths(sourcefn, destfn):
# Yield (sourcefn, destfn) pairs for all
Expand All @@ -107,7 +137,6 @@ def loader_paths(sourcefn, destfn):


def rewrite_tkinter_load_commands(tkinter_path):
print("rewrite_tk", tkinter_path)
m = macholib.MachO.MachO(tkinter_path)
tcl_path = None
tk_path = None
Expand Down Expand Up @@ -280,6 +309,9 @@ def __init__(self, **kw):
if m and isinstance(m, basestring):
self.modules = [m]

def __repr__(self):
return "<Target %s>"%(self.__dict__,)

def get_dest_base(self):
dest_base = getattr(self, "dest_base", None)
if dest_base:
Expand Down Expand Up @@ -1154,6 +1186,7 @@ def process_recipes(self, mf, filters, flatpackages, loader_files):
else:
break


def _run(self):
try:
if self.alias:
Expand Down Expand Up @@ -1533,6 +1566,7 @@ def packagefilter(mod, pkgdirs=pkgdirs):
if dist_info_path is None and (fn.endswith(".pyc") or fn.endswith(".pyo")):
dist_info_path = metadata_infos.get(fn[:-1], None)
if dist_info_path is not None:
print("ADD INFO", dist_info_path)
included_metadata.add(dist_info_path)

def files_in_dir(toplevel):
Expand Down Expand Up @@ -1592,11 +1626,11 @@ def files_in_dir(toplevel):
continue
src = os.path.join(pkg_info_path, fn)
dst = os.path.join(base, fn)

if os.path.isdir(src):
self.copy_tree(src, dst, preserve_symlinks=False)
else:
self.copy_file(src, dst)

self.lib_files = []
self.app_files = []

Expand Down
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -351,6 +351,7 @@ def run(self):
],
},
entry_points={
"setuptools.finalize_distribution_options": ["py2app = py2app.build_app:finalize_distribution_options"],
"distutils.commands": ["py2app = py2app.build_app:py2app"],
"distutils.setup_keywords": [
"app = py2app.build_app:validate_target",
Expand Down

0 comments on commit 55eb236

Please sign in to comment.