Summary: | Изменения в релизе 4.5.0-alt2 ломают сборку (тесты) zope.server | ||
---|---|---|---|
Product: | Sisyphus | Reporter: | Николай Костригин <nickel> |
Component: | python3-module-zope.contenttype | Assignee: | Grigory Ustinov <grenka> |
Status: | CLOSED FIXED | QA Contact: | qa-sisyphus |
Severity: | normal | ||
Priority: | P5 | CC: | antohami, cas, cow, evg, george, grenka, imz, kotopesutility, lav, nbr, qa_viy, rider, sem, shaba, sin, slev, toni, vitty, viy |
Version: | unstable | ||
Hardware: | x86_64 | ||
OS: | Linux |
Description
Николай Костригин
2022-08-13 15:29:16 MSK
Простите за тавтологию в предыдущем комментарии... По существу: заодно упомянутые изменения ломают тесты с такими же симптомами в 1. python3-module-zope.i18n [...] ---------------------------------------------------------------------- File "/usr/src/RPM/BUILD/python3-module-zope.i18n-4.8.0/src/zope/i18n/testing.py", line 48, in zope.i18n.testing.PlacelessSetup.setUp Failed example: from zope.publisher.browser import TestRequest Exception raised: Traceback (most recent call last): File "/usr/lib64/python3.10/doctest.py", line 1350, in __run exec(compile(example.source, filename, "single", File "<doctest zope.i18n.testing.PlacelessSetup.setUp[1]>", line 1, in <module> from zope.publisher.browser import TestRequest File "/usr/lib64/python3/site-packages/zope/publisher/browser.py", line 42, in <module> from zope.publisher.http import HTTPRequest File "/usr/lib64/python3/site-packages/zope/publisher/http.py", line 39, in <module> import zope.contenttype.parse ModuleNotFoundError: No module named 'zope.contenttype' [...] 2. python3-module-zope.publisher [...] ---------------------------------------------------------------------- File "/usr/src/RPM/BUILD/python3-module-zope.publisher-6.0.1/src/zope/publisher/tests/../paste.txt", line 49, in paste.txt Failed example: app_factory = pkg_resources.load_entry_point( 'zope.publisher', 'paste.app_factory', 'main') Exception raised: Traceback (most recent call last): File "/usr/lib64/python3.10/doctest.py", line 1350, in __run exec(compile(example.source, filename, "single", File "<doctest paste.txt[2]>", line 1, in <module> app_factory = pkg_resources.load_entry_point( File "/usr/lib64/python3/site-packages/pkg_resources/__init__.py", line 486, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "/usr/lib64/python3/site-packages/pkg_resources/__init__.py", line 2867, in load_entry_point return ep.load() File "/usr/lib64/python3/site-packages/pkg_resources/__init__.py", line 2471, in load return self.resolve() File "/usr/lib64/python3/site-packages/pkg_resources/__init__.py", line 2477, in resolve module = __import__(self.module_name, fromlist=['__name__'], level=0) File "/usr/src/RPM/BUILD/python3-module-zope.publisher-6.0.1/src/zope/publisher/paste.py", line 16, in <module> import zope.publisher.browser File "/usr/src/RPM/BUILD/python3-module-zope.publisher-6.0.1/src/zope/publisher/browser.py", line 42, in <module> from zope.publisher.http import HTTPRequest File "/usr/src/RPM/BUILD/python3-module-zope.publisher-6.0.1/src/zope/publisher/http.py", line 39, in <module> import zope.contenttype.parse ModuleNotFoundError: No module named 'zope.contenttype' [...] Если нет веских причин сохранять внесенные изменения, я предлагаю автору их откатить. Да, я прекрасно помню, что я это сломал. Надо разобраться в том, что же там такого архитектурозависимого. Ну то есть у нас много пакетов, которые собираются таким образом ошибочно, некоторые исправились хорошо, а вот этот сломал 3 пакета, если я не ошибаюсь. Исправлю в ближайшее время, а потом подумаю. (In reply to Николай Костригин from comment #0) > File "/usr/lib64/python3/site-packages/zope/publisher/http.py", line 39, > in <module> > import zope.contenttype.parse > ModuleNotFoundError: No module named 'zope.contenttype' > > > Откат к релизу alt1 делает возможность импорта соответствующего модуля > возможной. > Насколько я помню, виной всему перевод пакетов из архитектурозависимых в > noarch. Насколько я помню, это объясняется как-то так, что zope оформлен как модуль со своим __init__.py : /ALT/Sisyphus/x86_64/base/contents_index:/usr/lib64/python3/site-packages/zope/__init__.py python3-module-zope поэтому при import zope.contenttype.parse сначала ищется и находится этот модуль и загружается, и всё остальное может быть найдено только внутри него. В современном питоне, начиная с 3.x что-то, есть возможность, если я правильно помню, оформлять более настоящие namespaces, без __init__.py -- тогда поиск вложенных в namespace модулей должен быть по всем подходящим путям. Можно пофантазировать о каком-то автоматическом способе избежать таких ошибок с помощью зависимостей, но это как-то не так просто придумать, потому что в современном питоне есть два варианта, когда это будет работать, насолько я понимаю: требуется файл __init__.py на уровне выше /usr/lib/python3/site-packages/zope/__init__.py , или его отсутствие по всем путям, т.е. нет ни одного из: /usr/lib64/python3/site-packages/zope/__init__.py , /usr/lib/python3/site-packages/zope/__init__.py и прочих. (In reply to Ivan Zakharyaschev from comment #3) > В современном питоне, начиная с 3.x что-то, есть возможность, если я > правильно помню, оформлять более настоящие namespaces, без __init__.py -- > тогда поиск вложенных в namespace модулей должен быть по всем подходящим > путям. > > Можно пофантазировать о каком-то автоматическом способе избежать таких > ошибок с помощью зависимостей, но это как-то не так просто придумать, потому > что в современном питоне есть два варианта, когда это будет работать, > насолько я понимаю: требуется файл __init__.py на уровне выше > /usr/lib/python3/site-packages/zope/__init__.py , или его отсутствие по всем > путям, т.е. нет ни одного из: > /usr/lib64/python3/site-packages/zope/__init__.py , > /usr/lib/python3/site-packages/zope/__init__.py и прочих. Но у нас, мне кажется, поиск Provides как раз считает, что есть только первый вариант, поэтому при отсутствии __init__.py на уровень выше, будет отсутствовать Provides у пакета. И это могло бы быть способом обнаружения ошибки. В случае с zope.contenttype почему-то, правда, я такого эффекта не наблюдаю. Они на месте: $ rpm -qp /ALT/Sisyphus/noarch/RPMS.classic/python3-module-zope.contenttype-4.5.0-alt2.noarch.rpm --provides python3(zope.contenttype) python3(zope.contenttype.__main__) python3(zope.contenttype.parse) python3-module-zope.contenttype = 4.5.0-alt2:sisyphus+301404.100.1.1 Во время сборки была попытка создать такой файл, но вроде пропущена: Skipping installation of /usr/src/tmp/python3-module-zope.contenttype-buildroot/usr/lib/python3/site-packages/zope/__init__.py (namespace package) (In reply to Ivan Zakharyaschev from comment #3) > Можно пофантазировать о каком-то автоматическом способе избежать таких > ошибок с помощью зависимостей, но это как-то не так просто придумать, потому > что в современном питоне есть два варианта, когда это будет работать, > насолько я понимаю: требуется файл __init__.py на уровне выше > /usr/lib/python3/site-packages/zope/__init__.py и его отсутствие по всем остальным таким путям. > , или его отсутствие по всем > путям, т.е. нет ни одного из: > /usr/lib64/python3/site-packages/zope/__init__.py , > /usr/lib/python3/site-packages/zope/__init__.py и прочих. python3-module-zope.contenttype-4.5.0-alt3 -> sisyphus: Wed Aug 17 2022 Grigory Ustinov <grenka@altlinux> 4.5.0-alt3 - Make package arch dependent back (Closes: #43521). TL;DR Все файловые руты namespaсe package должны быть в python3-module-zope (и архитектурно-зависимые, и архитектурно-независимые). Сама идея namespace пакета подразумевает возможность разнесения частей одного пакета по различным файловым иерархиям (хотя это может быть и не только файловая система) с возможными *вложенными* namespace пакетами: https://docs.python.org/3/reference/import.html#namespace-packages zope - это namespace package, у которого есть как архитектурно-зависимые подпакеты, так и архитектурно-независимые. Upstream zope выбрал pkg_resources-style для namespace packages: https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#creating-a-namespace-package Это буквально означает, что *каждый* возможный устанавливаемый рут для подпакета *должен* иметь __init__.py cо следующим содержимым: > __import__('pkg_resources').declare_namespace(__name__) В текущей схеме пакетирования zope в ALT distro количество возможных рутов ограничено одним. Реализовано это как принудительное заархитектуривание *всех* подпакетов zope, то есть все такие подпакеты *должны* устанавливаться в /usr/lib64/python3/site-packages/zope/ (для x86_64). В противном случае, импорт таких подпакетов может не работать (зависит от многих факторов). Например, разберем проблему сборки данного пакета (zope.server). На файловой системе лежат: [user@host dir]# ls -1 /usr/lib{,64}/python3/site-packages/zope/ /usr/lib/python3/site-packages/zope/: __pycache__ contenttype /usr/lib64/python3/site-packages/zope/: __init__.py __pycache__ browser component configuration deferredimport deprecation event exceptions hookable i18n i18nmessageid interface location proxy publisher schema security testing testrunner Что происходит при импорте zope: [root@localhost .in]# echo -e "import sys\nfor f in sys.meta_path:\n spec = f.find_spec('zope', path=None)\n if spec is not None:\n print(f, spec.submodule_search_locations)\n break" | python3 - <class '_frozen_importlib_external.PathFinder'> ['/usr/lib64/python3/site-packages/zope'] то есть path-based finder (https://docs.python.org/3/reference/import.html#the-path-based-finder) находит нам спек для zope. При этом и path entry finder для архитектурно-зависимых sitepackages, и path entry finder для архитектурно-независимых sitepackages могут найти спек для zope: [root@localhost .in]# python3 -c 'import sys, zope; print(sys.path_importer_cache["/usr/lib/python3/site-packages"].find_spec("zope")); print(sys.path_importer_cache["/usr/lib64/python3/site-packages"].find_spec("zope"))' ModuleSpec(name='zope', loader=None, submodule_search_locations=['/usr/lib/python3/site-packages/zope']) ModuleSpec(name='zope', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f70b478ab60>, origin='/usr/lib64/python3/site-packages/zope/__init__.py', submodule_search_locations=['/usr/lib64/python3/site-packages/zope']) Но так как согласно https://peps.python.org/pep-0420/#specification > During import processing, the import machinery will continue to iterate over each directory in the parent path as it does in Python 3.2. While looking for a module or package named “foo”, for each directory in the parent path: > If <directory>/foo/__init__.py is found, a regular package is imported and returned. > If not, but <directory>/foo.{py,pyc,so,pyd} is found, a module is imported and returned. The exact list of extension varies by platform and whether the -O flag is specified. The list here is representative. > If not, but <directory>/foo is found and is a directory, it is recorded and the scan continues with the next directory in the parent path. > Otherwise the scan continues with the next directory in the parent path. > If the scan completes without returning a module or package, and at least one directory was recorded, then a namespace package is created. (детали тут: importlib/_bootstrap_external.py::FileFinder::find_spec) native namespace package ("/usr/lib/python3/site-packages/zope") и все его содержимое игнорируется. С точки зрения Python zope - это регулярный пакет (наличие zope/__init__.py), но инициализация этого пакета создает имитацию namespace пакета с помощью pkg_resources. pkg_resources.declare_namespace из /usr/lib64/python3/site-packages/zope/__init__.py, о котором говорилось ранее, патчит __path__ пакета zope: https://github.com/pypa/setuptools/blob/d03da04e024ad4289342077eef6de40013630a44/pkg_resources/__init__.py#L2289 [user@host dir]# python3 -c "import zope, sys; print(sys.modules['zope'].__path__)" ['/usr/lib64/python3/site-packages/zope'] Поэтому, если эта *обязательная* инициализация отсутствует во всех возможных рутах namespace пакета zope, то импорты могу не работать. Какие варианты пакетирования: - упаковать два рута, перевести все на native namespacе, удалив zope.__init__.py, и следить, чтобы никто и никогда не упаковал zope/__init__.py. - упаковать два рута, использовать схему upstream c pkg_resources, сделав зависимость обязательной |