Skip to content

Commit

Permalink
Use modern Python import features for product enumeration (#1240)
Browse files Browse the repository at this point in the history
* Use modern Python import features for product enumeration

* Apply pre-commit code formatting

* - fix linting issue

---------

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Jens Vagelpohl <jens@plyp.com>
  • Loading branch information
3 people authored Nov 27, 2024
1 parent 04b75cf commit c647a3a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 39 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst
in ``constraints.txt``.
(`#1234 <https://github.com/zopefoundation/Zope/pull/1234>`_)

- Use modern Python import features for product enumeration
(`#1239 <https://github.com/zopefoundation/Zope/issues/1239>`_).


5.11.1 (2024-11-03)
-------------------
Expand Down
54 changes: 15 additions & 39 deletions src/OFS/Application.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"""Application support
"""

import os
import pkgutil
import sys
from logging import getLogger
from urllib.parse import urlparse
Expand Down Expand Up @@ -378,15 +378,15 @@ def install_products(app=None):
folder_permissions = get_folder_permissions()
meta_types = []
done = {}
for priority, product_name, index, product_dir in get_products():
for priority, product_name, index, finder in get_products():
# For each product, we will import it and try to call the
# intialize() method in the product __init__ module. If
# the method doesnt exist, we put the old-style information
# together and do a default initialization.
if product_name in done:
continue
done[product_name] = 1
install_product(app, product_dir, product_name, meta_types,
install_product(app, finder, product_name, meta_types,
folder_permissions)

# Delayed install of packages-as-products
Expand All @@ -397,55 +397,34 @@ def install_products(app=None):
InitializeClass(Folder.Folder)


def _is_package(product_dir, product_name):
package_dir = os.path.join(product_dir, product_name)
if not os.path.isdir(package_dir):
return False

init_py = os.path.join(package_dir, '__init__.py')
if not os.path.exists(init_py) and \
not os.path.exists(init_py + 'c') and \
not os.path.exists(init_py + 'o'):
return False
return True


def get_products():
""" Return a list of tuples in the form:
[(priority, dir_name, index, base_dir), ...] for each Product directory
[(priority, product_name, index, finder), ...] for each Product directory
found, sort before returning """
products = []
for index, product_dir in enumerate(Products.__path__):
product_names = os.listdir(product_dir)
for product_name in product_names:
if _is_package(product_dir, product_name):
# i is used as sort ordering in case a conflict exists
# between Product names. Products will be found as
# per the ordering of Products.__path__
products.append((0, product_name, index, product_dir))
for index, modinfo in enumerate(pkgutil.iter_modules(Products.__path__)):
if modinfo.ispkg:
products.append((0, modinfo.name, index, modinfo.module_finder))
products.sort()
return products


def import_products():
done = {}
for priority, product_name, index, product_dir in get_products():
for priority, product_name, index, finder in get_products():
if product_name in done:
LOG.warning(
'Duplicate Product name: '
'After loading Product %r from %r, '
'I skipped the one in %r.' % (
product_name, done[product_name], product_dir))
'After loading Product %s from %s, '
'I skipped the one in %s.' % (
product_name, done[product_name], finder))
continue
done[product_name] = product_dir
import_product(product_dir, product_name)
done[product_name] = finder
import_product(finder, product_name)
return list(done.keys())


def import_product(product_dir, product_name, raise_exc=None):
if not _is_package(product_dir, product_name):
return

def import_product(finder, product_name, raise_exc=None):
global_dict = globals()
product = __import__("Products.%s" % product_name,
global_dict, global_dict, ('__doc__', ))
Expand All @@ -465,11 +444,8 @@ def get_folder_permissions():
return folder_permissions


def install_product(app, product_dir, product_name, meta_types,
def install_product(app, finder, product_name, meta_types,
folder_permissions, raise_exc=None):
if not _is_package(product_dir, product_name):
return

__traceback_info__ = product_name
global_dict = globals()
product = __import__("Products.%s" % product_name,
Expand Down

0 comments on commit c647a3a

Please sign in to comment.