Index: Mk/Uses/trigger.mk =================================================================== --- Mk/Uses/trigger.mk +++ Mk/Uses/trigger.mk @@ -10,20 +10,21 @@ .if !defined(_INCLUDE_USES_TRIGGER_MK) _INCLUDE_USES_TRIGGER_MK= yes -. if !empty(trigger_ARGS) -IGNORE= Incorrect 'USES+= trigger:${trigger_ARGS}' trigger takes no arguments +_flavored= # +. if !empty(trigger_ARGS:Mflavored) +_flavored= -${FLAVOR} . endif TRIGGERS?= ${PORTNAME} . for t in ${TRIGGERS} SUB_FILES+= ${t}.ucl -PLIST_FILES+= ${LOCALBASE}/share/pkg/triggers/$t.ucl +PLIST_FILES+= ${LOCALBASE}/share/pkg/triggers/$t${_flavored}.ucl . endfor _USES_install+= 601:trigger-post-install trigger-post-install: ${MKDIR} ${STAGEDIR}${LOCALBASE}/share/pkg/triggers . for t in ${TRIGGERS} - ${INSTALL_DATA} ${WRKDIR}/$t.ucl ${STAGEDIR}${LOCALBASE}/share/pkg/triggers/ + ${INSTALL_DATA} ${WRKDIR}/$t.ucl ${STAGEDIR}${LOCALBASE}/share/pkg/triggers/$t${_flavored}.ucl . endfor .endif Index: lang/Makefile =================================================================== --- lang/Makefile +++ lang/Makefile @@ -285,6 +285,7 @@ SUBDIR += python-doc-pdf-letter SUBDIR += python-doc-text SUBDIR += python-mode.el + SUBDIR += python-pycache SUBDIR += python-tools SUBDIR += python2 SUBDIR += python27 Index: lang/python-pycache/Makefile =================================================================== --- /dev/null +++ lang/python-pycache/Makefile @@ -0,0 +1,30 @@ +PORTNAME= python-pycache +PORTVERSION= 0.0.1 +PKGNAMESUFFIX= ${PYTHON_PKGNAMESUFFIX} + +CATEGORIES= lang + +MAINTAINER= portmgr@FreeBSD.org +COMMENT= Trigger to recreate python precompiled bytecode + +USES= metaport trigger:flavored python:env +USE_PYTHON= flavors +TRIGGERS= python-update-cache + +SUB_LIST= PYTHON_CMD=${PYTHON_CMD} \ + NEW_CACHE_CMD=${_NEW_CACHE_CMD} + +OPTIONS_DEFINE= VERBOSE +VERBOSE_DESC= Make the cache handling more verbose +VERBOSE_SUB_LIST= LUA_DEBUG="" +VERBOSE_SUB_LIST_OFF= LUA_DEBUG="-- " + +.include + +.if ${PYTHON_VER:M3.7} || ${PYTHON_VER:M3.8} +_NEW_CACHE_CMD= false +.else +_NEW_CACHE_CMD= true +.endif + +.include Index: lang/python-pycache/files/python-update-cache.ucl.in =================================================================== --- /dev/null +++ lang/python-pycache/files/python-update-cache.ucl.in @@ -0,0 +1,164 @@ +path_glob: "%%PYTHON_SITELIBDIR%%/*" + +trigger: { + type: lua + sandbox: false + script: < 32 then + error("Could not find top directory within 10 iterations. This is an error in the trigger.") + end + end +end + +function has_cache(directory) + local path = directory .. "/" .. "__pycache__" + local stat = pkg.stat(path) + + return stat and stat["type"] == "dir" +end + +function cachable(directory) + if string.find(directory, '__pycache__') or + string.find(directory, "[.]egg[-]info$") or + string.find(directory, "[.]dist[-]info$") then + return false + end + return true +end + +function cleanup(directory) + if not pkg.stat(directory) then + %%LUA_DEBUG%%print(" |---- " .. directory .. " does not exist (anymore)") + return + end + for _,d in ipairs(pkg.readdir(directory)) do + local full_path = directory .. "/" .. d + local stat = pkg.stat(full_path) + if stat and stat["type"] == "dir" then + if (not (d == "__pycache__")) then + cleanup(full_path) + else + -- check all files against the presence of their raw python file + for _,bytecode_file in ipairs(pkg.readdir(full_path)) do + local file_origin = string.gsub(bytecode_file, "[.]cpython[-]%d%d[.].*py[oc]", ".py") + if file_origin then + local origin_path = directory .. "/" .. file_origin + if (not pkg.stat(origin_path)) then + os.remove(full_path .. "/" .. bytecode_file) + end + end + end + -- if the directory itself is empty, it can be removed now + local res = pkg.readdir(full_path) + if res and #res == 0 then + %%LUA_DEBUG%%print(" |---- " .. directory .. " removed") + os.remove(full_path) + end + end + end + end + -- check wheter the directory itself has become stale + local items = pkg.readdir(directory) + if items and #items == 0 then + %%LUA_DEBUG%%print(" |---- " .. directory .. " removed") + os.remove(directory) + end +end + +function create_cache(item) + if %%NEW_CACHE_CMD%% then + pkg.exec({"%%PYTHON_CMD%%", "-m", "compileall", "-q", "-o", "0", "-o", "1", "-o", "2", item}) + else + pkg.exec({"%%PYTHON_CMD%%", "-m", "compileall", "-q", item}) + pkg.exec({"%%PYTHON_CMD%%", "-O", "-m", "compileall", "-q", item}) + pkg.exec({"%%PYTHON_CMD%%", "-OO", "-m", "compileall", "-q", item}) + end +end + +function create(item, recursive) + if not pkg.stat(item) then + %%LUA_DEBUG%%print(" |---- " .. item .. " does not exist (anymore)") + return + end + if recursive and has_cache(item) then + %%LUA_DEBUG%%print(" |---- " .. item .. " already has a __pycache__") + return + end + if recursive then + %%LUA_DEBUG%%print(" |---- " .. item .. " creating cache for directory") + create_cache(item) + else + for _,file in ipairs(pkg.readdir(item)) do + if string.find(file, "[.]py$") then + local path = item .. "/" .. file + %%LUA_DEBUG%%print(" |---- " .. path .. " creating cache for file") + create_cache(path) + end + end + end +end + +local to_clean = {} +local to_create = {} +-- filter the files passed by pkg to decide which paths to clean and to re-cache +-- for _, path in ipairs(arg) do +for _,item in ipairs(pkg.readdir("%%PYTHON_SITELIBDIR%%")) do + local path = "%%PYTHON_SITELIBDIR%%" .. "/" .. item + local added = false + directory = top_level(path) + local stat = pkg.stat(directory) + if stat then + if stat["type"] == "dir" and cachable(directory) then + if not to_clean[directory] then + to_clean[directory] = path + added = true + end + if not to_create[directory] then + to_create[directory] = path + added = true + end + end + end + --if not added then + -- %%LUA_DEBUG%%print(" +-[?] " .. path) + --end +end +-- re-create cache +print("Creating Python bytecode files...") +for path,_ in pairs(to_create) do + create(path, true) +end +-- cleanup and generate (per file) +create("%%PYTHON_SITELIBDIR%%", false) + +-- cleanup stale cache files +print("Cleaning Python bytecode files...") +for path,_ in pairs(to_clean) do + cleanup(path) +end +-- cleanup top-level pycache +cleanup("%%PYTHON_SITELIBDIR%%/__pycache__", false) + +EOS +} Index: lang/python-pycache/pkg-descr =================================================================== --- /dev/null +++ lang/python-pycache/pkg-descr @@ -0,0 +1 @@ +Recreates pycache on pkg registration. Index: lang/python310/Makefile =================================================================== --- lang/python310/Makefile +++ lang/python310/Makefile @@ -1,6 +1,6 @@ PORTNAME= python DISTVERSION= ${PYTHON_DISTVERSION} -PORTREVISION= 2 +PORTREVISION= 4 CATEGORIES= lang python MASTER_SITES= PYTHON/ftp/python/${DISTVERSION:C/[a-z].*//} PKGNAMESUFFIX= ${PYTHON_SUFFIX} @@ -14,6 +14,7 @@ LICENSE= PSFL LIB_DEPENDS= libffi.so:devel/libffi +RUN_DEPENDS= python-pycache${PYTHON_PKGNAMESUFFIX}>=0:lang/python-pycache@${PY_FLAVOR} USES= compiler:c11 cpe ncurses pathfix pkgconfig \ python:${PYTHON_DISTVERSION:R},env readline shebangfix ssl tar:xz Index: lang/python311/Makefile =================================================================== --- lang/python311/Makefile +++ lang/python311/Makefile @@ -1,6 +1,6 @@ PORTNAME= python DISTVERSION= ${PYTHON_DISTVERSION} -PORTREVISION= 2 +PORTREVISION= 4 CATEGORIES= lang python MASTER_SITES= PYTHON/ftp/python/${DISTVERSION:C/[a-z].*//} PKGNAMESUFFIX= ${PYTHON_SUFFIX} @@ -14,6 +14,7 @@ LICENSE= PSFL LIB_DEPENDS= libffi.so:devel/libffi +RUN_DEPENDS= python-pycache${PYTHON_PKGNAMESUFFIX}>=0:lang/python-pycache@${PY_FLAVOR} USES= compiler:c11 cpe ncurses pathfix pkgconfig \ python:${PYTHON_DISTVERSION:R},env readline shebangfix ssl tar:xz Index: lang/python37/Makefile =================================================================== --- lang/python37/Makefile +++ lang/python37/Makefile @@ -1,6 +1,6 @@ PORTNAME= python DISTVERSION= ${PYTHON_DISTVERSION} -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= lang python MASTER_SITES= PYTHON/ftp/python/${DISTVERSION} PKGNAMESUFFIX= ${PYTHON_SUFFIX} @@ -18,6 +18,7 @@ LIB_DEPENDS= libffi.so:devel/libffi \ libmpdec.so:math/mpdecimal +RUN_DEPENDS= python-pycache${PYTHON_PKGNAMESUFFIX}>=0:lang/python-pycache@${PY_FLAVOR} USES= cpe ncurses pathfix pkgconfig python:${PYTHON_DISTVERSION:R},env readline \ shebangfix ssl tar:xz Index: lang/python38/Makefile =================================================================== --- lang/python38/Makefile +++ lang/python38/Makefile @@ -1,6 +1,6 @@ PORTNAME= python DISTVERSION= ${PYTHON_DISTVERSION} -PORTREVISION= 2 +PORTREVISION= 4 CATEGORIES= lang python MASTER_SITES= PYTHON/ftp/python/${DISTVERSION} PKGNAMESUFFIX= ${PYTHON_SUFFIX} @@ -14,6 +14,7 @@ LICENSE= PSFL LIB_DEPENDS= libffi.so:devel/libffi +RUN_DEPENDS= python-pycache${PYTHON_PKGNAMESUFFIX}>=0:lang/python-pycache@${PY_FLAVOR} USES= cpe ncurses pathfix pkgconfig python:${PYTHON_DISTVERSION:R},env readline \ shebangfix ssl tar:xz Index: lang/python39/Makefile =================================================================== --- lang/python39/Makefile +++ lang/python39/Makefile @@ -1,6 +1,6 @@ PORTNAME= python DISTVERSION= ${PYTHON_DISTVERSION} -PORTREVISION= 2 +PORTREVISION= 4 CATEGORIES= lang python MASTER_SITES= PYTHON/ftp/python/${DISTVERSION} PKGNAMESUFFIX= ${PYTHON_SUFFIX} @@ -14,6 +14,7 @@ LICENSE= PSFL LIB_DEPENDS= libffi.so:devel/libffi +RUN_DEPENDS= python-pycache${PYTHON_PKGNAMESUFFIX}>=0:lang/python-pycache@${PY_FLAVOR} USES= compiler:c11 cpe ncurses pathfix pkgconfig \ python:${PYTHON_DISTVERSION:R},env readline shebangfix ssl tar:xz