rpm-build-python3-0.1.7/000075500000000000000000000000001213161274200150115ustar00rootroot00000000000000rpm-build-python3-0.1.7/brp-bytecompile_python3000075500000000000000000000043451213161274200215260ustar00rootroot00000000000000#!/bin/sh -e # # brp-bytecompile_python3 - compile python3 modules. # based on brp-bytecompile_python3 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # . /usr/lib/rpm/functions ValidateBuildRoot if [ -z "$RPM_PYTHON3" ]; then RPM_PYTHON3=/usr/bin/python3 fi if [ -z "$RPM_PYTHON3_VERSION" ]; then RPM_PYTHON3_VERSION=`LC_ALL=C $RPM_PYTHON3 -c 'import sys; print("{0}.{1}".format(sys.version_info[0],sys.version_info[1]))' 2>/dev/null || echo unknown` fi if [ -z "$RPM_PYTHON3_COMPILE_DEEP" ]; then RPM_PYTHON3_COMPILE_DEEP=20 fi if [ -z "$RPM_PYTHON3_COMPILE_INCLUDE" ]; then RPM_PYTHON3_COMPILE_INCLUDE="/usr/lib/python$RPM_PYTHON3_VERSION" if [ `arch` = "x86_64" ] && [ -d $RPM_BUILD_ROOT/usr/lib64/python$RPM_PYTHON3_VERSION] ; then RPM_PYTHON3_COMPILE_INCLUDE="$RPM_PYTHON3_COMPILE_INCLUDE /usr/lib64/python$RPM_PYTHON3_VERSION" fi fi cd $RPM_BUILD_ROOT if [ `find -type f -name \*.py |wc -l` -gt 0 ]; then echo "Bytecompiling python3 modules in $PWD using $RPM_PYTHON3" $RPM_PYTHON3 /usr/lib/rpm/python3.compileall.py "--exclude=$RPM_PYTHON3_COMPILE_EXCLUDE" "--include=$RPM_PYTHON3_COMPILE_INCLUDE" "--deep=$RPM_PYTHON3_COMPILE_DEEP" ${RPM_PYTHON3_COMPILE_SKIP_X:+--skip_x} ${RPM_PYTHON3_COMPILE_CLEAN:+--clean} "--prefix=$RPM_BUILD_ROOT" echo "Bytecompiling python3 modules with optimization in $PWD using $RPM_PYTHON3 -O" $RPM_PYTHON3 -O /usr/lib/rpm/python3.compileall.py "--exclude=$RPM_PYTHON3_COMPILE_EXCLUDE" "--include=$RPM_PYTHON3_COMPILE_INCLUDE" "--deep=$RPM_PYTHON3_COMPILE_DEEP" ${RPM_PYTHON3_COMPILE_SKIP_X:+--skip_x} ${RPM_PYTHON3_COMPILE_CLEAN:+--clean} "--prefix=$RPM_BUILD_ROOT" fi rpm-build-python3-0.1.7/python3000064400000000000000000000100311213161274200163330ustar00rootroot00000000000000%__python3 python3 %__python3_version %(LC_ALL=C %__python3 -c 'import sys; print("{0}.{1}".format(sys.version_info[0],sys.version_info[1]))' 2>/dev/null || echo unknown) %_python3_abiflags %(%__python3-config --abiflags 2>/dev/null || echo unknown) %_python3_extension_suffix %(%__python3-config --extension-suffix 2>/dev/null || echo .so) %_python3_version %__python3_version %_python3_libdir %_target_libdir/python%_python3_version %_target_python3_libdir %_target_libdir %python3_dynlibdir %python3_libdir/lib-dynload %python3_tooldir %python3_libdir/tools # traditional build/install macros %python3_build \ CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ; \ CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ; \ FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ; \ %__python3 setup.py build %python3_build_debug \ CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ; \ CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ; \ FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ; \ %__python3 setup.py build --debug %python3_install \ %__python3 setup.py install --skip-build --root=%buildroot %python3_build_install \ CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ; \ CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ; \ FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ; \ %__python3 setup.py install --root=%buildroot %_python3_path %_target_libdir/python%_python3_version %_target_libdir_noarch/python%_python3_version %add_python3_path() %global _python3_path %_python3_path %* \ %global _python_compile_exclude %_python_compile_exclude %* # python3_req_hier # # Включить поиск иерархических зависимостей # %python3_req_hier %global _python3_req_hier yes %_python3_set_noarch() %global _target_python3_libdir %_target_libdir_noarch %_python3_set_arch() %global _target_python3_libdir %_target_libdir %_python3_lib_path "" %_python3_req_method slight %_python3_req_skip "" %_python3_compile_exclude %_defaultdocdir %_python3_compile_include %_python3_path %_python3_compile_deep 20 %_python3_compile_skip_x 1 %_python3_compile_clean 1 %set_python3_req_method() %global _python3_req_method %1 %add_python3_req_skip() %global _python3_req_skip %_python3_req_skip %* %add_python3_lib_path() %global _python3_lib_path %_python3_lib_path %* %add_python3_compile_exclude() %global _python3_compile_exclude %_python3_compile_exclude %* %add_python3_compile_include() %global _python3_compile_include %_python3_compile_include %* # Заголовочные файлы для компиляции расширений на C %python3_includedir %_includedir/python%__python3_version # Модули Python3, включенные в официальный релиз %python3_libdir %_target_python3_libdir/python%__python3_version # Модули Python3, установленные в дополнение к официальному релизу %python3_sitelibdir %python3_libdir/site-packages # архитектурно-независимые модули Python3, установленные в дополнение к официальному релизу %python3_sitelibdir_noarch %_target_libdir_noarch/python%__python3_version/site-packages %__python3_deps_internal() \ for mod in %{*}; do \ echo -n "python%__python3_version($mod) "; \ done; unset mod;\ %nil # py3_requires <имя_модуля1> [<имя_модуля2> ...] # # Добавляет зависимость на указанные модули Python3. Формируемые # зависимости имеют вид: python3.X(имя_модуля1) [python3.X(имя_модуля2)...] # %py3_requires() \ %(echo -n "Requires:"; %{expand: %%__python3_deps_internal %{*}}) \ %nil # py3_provides <имя_модуля1> [<имя_модуля2> ...] # # Позволяет принудительно указать предоставляемые модули Python3. Формируемые # "provides" имеют вид: python3.X(имя_модуля1) [python3.X(имя_модуля2)...] # %py3_provides() \ %(echo -n "Provides:"; %{expand: %%__python3_deps_internal %{*}}) \ %nil rpm-build-python3-0.1.7/python3.buildreq000064400000000000000000000001721213161274200201460ustar00rootroot00000000000000^/usr/.*/python3.*/encodings/__init__\.py ^/usr/.*/python3.*/encodings/aliases\.py ^/usr/.*/python3.*/encodings/ascii\.py rpm-build-python3-0.1.7/python3.compileall.py000075500000000000000000000074041213161274200211170ustar00rootroot00000000000000#! /usr/bin/python3 __doc__ = """\ RPM Build Python3 / Compileall Converted from RPM Build Python / Compile All by 2to3 script Description: This application is intendent to byte compile python3 modules Call: compileall.py Switches: --exclude= -- List of paths to be excluded from byte compilation; --include= -- List of paths to be included into byte compilation; --deep= -- Deep of search down into directory tree; --skip_x -- Skip executable files from byte compilation; --clean -- Clean not-comileable modules; --prefix= -- Install prefix; Warranty: There is no warranty of any kind, either expressed or implied TODO: Nothing """ def _(s) : return s import sys, os, py_compile prefix = "python%u.%u" % sys.version_info[0:2] ALL = 1 ALREADY = 2 BOTH = 3 SUFFIX = __debug__ and 'c' or 'o' def join_prefix(prefix,path) : return os.path.abspath(os.path.join(prefix,os.path.abspath(path)[1:])) def executable(file): import stat if stat.S_IEXEC & (os.stat(file)[stat.ST_MODE]) : header = open(file, 'rb').read(2) if b'#!' == header : return True def compile_all(path,exclude=['/usr/share/doc'],deep=20,skip_x=False,clean=False,prefix='') : if path not in exclude and deep > 0 : try: lp = os.listdir(path) except os.error: print(_("Can't list '%s'") % path) else : lp.sort() lp = [ os.path.join(path,p) for p in lp ] if clean : for p in lp : if os.path.isfile(p) and os.path.splitext(p)[1] == ('.py' + SUFFIX) : print(_('unlink'),p) os.unlink(p) for p in lp : if os.path.isdir(p) : compile_all(p,exclude,deep-1,skip_x,clean,prefix) elif os.path.isfile(p) : if os.path.splitext(p)[1] == '.py' : if not (skip_x and executable(p)) : try : print(_('compile'),p) py_compile.compile(p, doraise=True) except py_compile.PyCompileError as msg: print(_("%s can't be compiled : %s") % (p,msg)) def compile_path(include=sys.path[2:],exclude=[],deep=10,skip_x=False,clean=False,prefix='/') : for item in set(include) : compile_all(join_prefix(prefix,item),[join_prefix(prefix,x) for x in exclude],deep,skip_x,clean,prefix) def main() : """Script main program.""" import getopt,re lopt = ['exclude=','include=','deep=','skip_x','clean','prefix='] cut = re.compile("^-*([^=]*)=?$").match lenv = [ ('python_bc_%s' % cut(x).group(1)) for x in lopt ] dopt = dict([ (x[0:10],y) for x,y in list(os.environ.items()) if x in lenv]) try: opts, args = getopt.getopt(sys.argv[1:], 'h',lopt) except getopt.error as msg: print(msg) print(__doc__) sys.exit(2) else : dopt.update(dict([ (cut(x).group(1),y) for x,y in opts])) if 'h' in dopt : print(__doc__) else : if 'exclude' in dopt : dopt['exclude'] = dopt['exclude'].split() if 'include' in dopt and dopt['include'] : dopt['include'] = dopt['include'].split() if 'skip_x' in dopt : dopt['skip_x'] = True if 'clean' in dopt : dopt['clean'] = True if 'deep' in dopt : dopt['deep'] = int(dopt['deep']) if args : dopt['include'] = args return compile_path(**dopt) if __name__ == '__main__' : exit_status = bool(main()) sys.exit(exit_status) rpm-build-python3-0.1.7/python3.env000064400000000000000000000017451213161274200171360ustar00rootroot00000000000000%{?_python3_version:export RPM_PYTHON3_VERSION="%_python3_version"} %{?_python3_path:export RPM_PYTHON3_PATH="%_python3_path"} %{?_python3_lib_path:export RPM_PYTHON3_LIB_PATH="%_python3_lib_path"} %{?_python3_module_declared:export RPM_PYTHON3_MODULE_DECLARED="%_python3_module_declared"} %{?_python3_req_hier:export RPM_PYTHON3_REQ_HIER="%_python3_req_hier"} %{?_python3_req_method:export RPM_PYTHON3_REQ_METHOD="%_python3_req_method"} %{?_python3_req_skip:export RPM_PYTHON3_REQ_SKIP="%_python3_req_skip"} %{?_python3_compile_exclude:export RPM_PYTHON3_COMPILE_EXCLUDE="%_python3_compile_exclude"} %{?_python3_compile_include:export RPM_PYTHON3_COMPILE_INCLUDE="%_python3_compile_include"} %{?_python3_compile_deep:export RPM_PYTHON3_COMPILE_DEEP="%_python3_compile_deep"} %{?_python3_compile_skip_x:export RPM_PYTHON3_COMPILE_SKIP_X="%_python3_compile_skip_x"} %{?_python3_compile_clean:export RPM_PYTHON3_COMPILE_CLEAN="%_python3_compile_clean"} %{?__python3:export RPM_PYTHON3="%__python3"} rpm-build-python3-0.1.7/python3.prov000075500000000000000000000001151213161274200173250ustar00rootroot00000000000000#!/bin/sh LC_ALL=C exec "${RPM_PYTHON3:-/usr/bin/python3}" "$0".py ${1+"$@"} rpm-build-python3-0.1.7/python3.prov.files000075500000000000000000000030341213161274200204310ustar00rootroot00000000000000#!/bin/sh -efu LC_ALL=C; export LC_ALL is_python3_path() { local f p f="$1"; shift for p in ${RPM_PYTHON3_PATH-} ${RPM_PYTHON3_COMPILE_INCLUDE-}; do if [ -z "${f##${RPM_BUILD_ROOT-}${p%%/}/*}" ]; then return 0 fi done return 1 } while IFS=$'\t' read -r f t; do # skip all from %_libdir/python2 case "$f" in ${RPM_BUILD_ROOT-}/usr/lib*/python2*) continue ;; esac # skip all that cannot be provided due to rpmbuild restrictions case "${f##*/}" in [^_[:alnum:]]*) continue ;; *[[:space:]]*) continue ;; esac t="${t## }" t="${t%% }" case "$t" in # skip python2 files "python script text executable") continue ;; # shortcut for real python scripts "python3 script text executable") echo "$f" continue ;; # shortcut for possible python extensions *ELF*" shared object"*) case "$f" in ${RPM_BUILD_ROOT-}*/python3*/*.so) echo "$f" ;; esac continue ;; esac case "$f" in *.py) [ -f "$f" ] || continue ;; *) continue ;; esac # the rest is to deal with *.py and *.pth files is_python3_path "$f" || continue case "$f" in # __init__.py can be empty - no need for filetype check */__init__.py) echo "$f" continue ;; esac case "$t" in *" text"*) echo "$f" ;; # file(1) check for text files is not quite reliable # I use perl for '-T $f' heuristic check (see perlfunc for details) *) if perl -e '$f=shift; exit( -T $f ? 0 : 1 )' "$f"; then echo "${0##*/}: $f: $t (PASS)" >&2 echo "$f" else echo "${0##*/}: $f: $t (IGNORE)" >&2 fi ;; esac done rpm-build-python3-0.1.7/python3.prov.py000075500000000000000000000142741213161274200177670ustar00rootroot00000000000000#! /usr/bin/python3 # import os import sys import sysconfig verbosity = int(os.getenv('RPM_SCRIPTS_DEBUG', 0)) prog = 'python3.prov' extension_suffix = sysconfig.get_config_var('EXT_SUFFIX') if extension_suffix is None : extension_suffix = sysconfig.get_config_var('SO') def normpath(f) : if not f.startswith('/') : f = os.getcwd() + f return os.path.normpath(f) def get_buildroot() : buildroot = os.getenv('RPM_BUILD_ROOT','') if buildroot in ['','/'] : return None return normpath(buildroot) buildroot = get_buildroot() def get_path() : "get the list of standard python directories" # we assume that the first sys.path element is "" which stands for current directory, # and that sys.path entries are already normalized. path = sys.path[1:] if buildroot : # it is possible that sys.path already has RPM_BUILD_ROOT entries # e.g. if we build python itself and RPM_PYTHON is redefined l = len(buildroot) def strip_buildroot(p) : if p.startswith(buildroot+'/') : return p[l:] return p path = [ strip_buildroot(p) for p in path ] # handle RPM_PYTHON3_LIB_PATH which can be exported with rpm macros rpm_path = os.getenv('RPM_PYTHON3_LIB_PATH','').split() rpm_path = [p for p in rpm_path if p.startswith('/')] path = rpm_path + path # now we can prepend RPM_BUILD_ROOT if buildroot : br_path = [ buildroot + p for p in path ] path = br_path + path return path def get_pth_path() : "get the list of additional python directories from site-packages/*.pth" # cf. site.py:addsitedir() def glob_pth(dir) : try : files = os.listdir(dir) except : return [] return [ f for f in files if f.endswith('.pth') ] def read_pth(f) : try : fp = open(f) except : return [] subdirs = [] for line in fp : if line.startswith("#"): continue if line.startswith("import"): continue line = line.rstrip() if len(line) == 0: continue subdirs.append(line) return subdirs # okay, here we go sitedirs = [ p for p in get_path() if p.endswith('/site-packages') ] pth_path = [] for sitedir in sitedirs : for pth in glob_pth(sitedir) : for subdir in read_pth(sitedir+'/'+pth) : dir = normpath(sitedir+'/'+subdir) pth_path.append(dir) if buildroot : l = len(buildroot) def strip_buildroot(p) : if p.startswith(buildroot+'/') : return p[l:] return p pth_path = [ strip_buildroot(p) for p in pth_path ] br_pth_path = [ buildroot + p for p in pth_path ] pth_path = br_pth_path + pth_path #print >>sys.stderr, "%s: pth_path=" % prog, pth_path return pth_path path = get_path() + get_pth_path() path = [ p for p in path if os.path.exists(p) ] # it is essential to sort path entries descending by their length, # so that "most specific" entries are tried first; e.g. # /usr/lib/python2.5/site-packages should go before /usr/lib/python2.5 def psort(s): return len(s) path.sort(key=psort) path.reverse() # debug if __name__ == '__main__' and verbosity > 1 : print("%s: path=" % prog, path, file=sys.stderr) def explode(f) : "split filename into std-dir + subdir/basename" for p in path : if f.startswith(p+'/') : l = len(p) return f[:l],f[l+1:] return None, None def prov1db(d,b) : "list of modules provided by the file, split into std-dir + subdir/basename" b = b.replace(extension_suffix,".so") # Python syntax does not allow modules with dashes. # Also note that this will exclude e.g. b="site-packages/foo.py". if b.find("-") >= 0 : return m,e = os.path.splitext(b) if not e in ['.py','.so'] : return if not '/' in m : # the file is a simple module if m == '__init__' : return prov = [ m ] if e == '.so' and len(m) > 6 and m[-6:] == 'module' : # e.g. rpmmodule.so provides rpm prov.append(m[0:-6]) return prov # hierarchical module parts = m.split('/') if parts[-1] == '__init__' : # e.g. foo/bar/__init__.py provides foo.bar return [ '.'.join(parts[:-1]) ] # for/bar.py provides foo.bar if foo/__init__.py is present if os.path.exists(d+'/'+os.path.dirname(b)+'/__init__.py') : m = '.'.join(parts) prov = [ m ] if e == '.so' and len(m) > 6 and m[-6:] == 'module' : prov.append(m[0:-6]) return prov def prov1(f) : "returns list of modules provided by the file" d,b = explode(f) if not d : return prov = prov1db(d,b) # Sometimes a module can be loaded by its full name, e.g. PIL.Image, # while PIL.pth adds PIL subdir to std-dirs, so that the module can be # loaded simply as Image. We provide limited support for this feature. # Note that, since PIL.pth provides the longest std-dir, the b=Image case # has just been handled. Now we check d to see if we need to recombine # std-dir + subdir/basename and run prov1db(d,b) again. if os.path.exists(d+'/__init__.py') and os.path.dirname(d) in path : b = os.path.basename(d)+'/'+b d = os.path.dirname(d) xprov = prov1db(d,b) if xprov : if prov : prov += xprov else : prov = xprov return prov def verbose(msg) : if verbosity > 0 : print("%s: %s" % (prog,msg), file=sys.stderr) def provides(f,m) : prefix = "python%u.%u" % sys.version_info[0:2] prov = "%s(%s)" % (prefix,m) verbose("%s provides %s" % (f,prov)) print(prov) def main(files, provides=provides, verbose=verbose) : for f in files : prov = prov1(f) if prov : for p in prov : provides(f,p) else : verbose("%s provides nothing" % f) if __name__ == '__main__': files = sys.argv[1:] or [ x.strip() for x in sys.stdin.readlines() ] main(files) # ex: set ts=8 sts=4 sw=4 et: rpm-build-python3-0.1.7/python3.req000075500000000000000000000001151213161274200171260ustar00rootroot00000000000000#!/bin/sh LC_ALL=C exec "${RPM_PYTHON3:-/usr/bin/python3}" "$0".py ${1+"$@"} rpm-build-python3-0.1.7/python3.req.files000075500000000000000000000026531213161274200202400ustar00rootroot00000000000000#!/bin/sh -efu is_python3_path() { local f p f="$1"; shift for p in ${RPM_PYTHON3_PATH-} ${RPM_PYTHON3_COMPILE_INCLUDE-}; do if [ -z "${f##${RPM_BUILD_ROOT-}${p%%/}/*}" ]; then return 0 fi done return 1 } while IFS=$'\t' read -r f t; do # skip all from %_libdir/python2 case "$f" in ${RPM_BUILD_ROOT-}/usr/lib*/python2*) continue ;; esac t="${t## }" t="${t%% }" case "$t" in # skip python2 files "python script text executable") continue ;; # shortcut for real python3 scripts "python3 script text executable") echo "$f" continue ;; # shortcut for possible python3 extensions *ELF*" shared object"*) case "$f" in ${RPM_BUILD_ROOT-}*/python3*/*.so) echo "$f" ;; esac continue ;; # symbolic links not needed here? *"symbolic link to "*) continue ;; esac case "$f" in *.py) [ -f "$f" ] || continue ;; *) continue ;; esac # the rest is to deal with *.py files is_python3_path "$f" || continue case "$f" in # __init__.py can be empty - no need for filetype check */__init__.py) echo "$f" continue ;; esac case "$t" in *" text"*) echo "$f" ;; # file(1) check for text files is not quite reliable # I use perl for '-T $f' heuristic check (see perlfunc for details) *) if perl -e '$f=shift; exit( -T $f ? 0 : 1 )' "$f"; then echo "${0##*/}: $f: $t (PASS)" >&2 echo "$f" else echo "${0##*/}: $f: $t (IGNORE)" >&2 fi ;; esac done rpm-build-python3-0.1.7/python3.req.py000075500000000000000000000210731213161274200175630ustar00rootroot00000000000000#! /usr/bin/python3 try : import sys, os from os.path import basename, dirname import parser, symbol, token, types import subprocess except : raise else : def _(s) : return s prefix = "python%u.%u" % sys.version_info[0:2] symbol_skip = [symbol.encoding_decl, symbol.classdef] def pro(x) : return x[1] def namelist(import_node) : return [x for x in import_node[2][1:] if x[0] != 12 ] # Provides: from python3-base package base_modules = [] # disabling for bootstrap # base_provides = subprocess.check_output(['rpmquery','--provides', 'python3-base']).split(b'\n') # for module in base_provides: # if module.strip()[:9] == prefix : # base_modules.append(module.strip()[10:][:-1]) def ignore(module) : if module in dict([ (x,1) for x in list(os.getenv('RPM_PYTHON3_REQ_SKIP',"").split()) + list(sys.builtin_module_names)]) : return True else : return False REQ=os.getenv('RPM_PYTHON3_REQ_METHOD','strict') IS_HIER = os.getenv('RPM_PYTHON3_REQ_HIER',None) src = None def match(tree,deep=0) : if tree[0] not in symbol_skip : deep += 1 for node in tree : if type(node) in [list, tuple] : if node[0] == symbol.import_stmt : line = 0 deps = [] node = pro(node) if node[1][1] == 'import' : line = node[1][2] for name in namelist(node) : if IS_HIER is None : deps.append(name[1][1][1]) else : deps.append(".".join( [ i[1] for i in name[1][1:] if i[0]==1 ])) elif node[1][1] == 'from' : line = node[1][2] if type(node[2][1]) is list: if IS_HIER is None : deps.append(node[2][1][1]) else : deps.append(".".join( [ i[1] for i in node[2][1:] if i[0]==1 ])) else: # XXX temporary 2.5 PEP 328 workaround print("%s: %s: line=%d possible relative import from %s, UNIMPLEMENTED" % (sys.argv[0], src, line, node[2][1]), file=sys.stderr) if REQ not in ['slight','relaxed'] or deep == 4 : for dep in deps : yield dep else : for dep in deps: print("%s: %s: line=%d IGNORE module=%s" % (sys.argv[0], src, line, dep), file=sys.stderr) for item in match(node,deep) : yield item if __name__ == '__main__' : files = sys.argv[1:] or [ x.strip() for x in sys.stdin.readlines() ] reqs = {} prov = {} for src in files : prov.setdefault(dirname(src),[]).append(os.path.splitext(basename(src))[0]) if basename(src) == "__init__.py" : prov.setdefault(dirname(dirname(src)),[]).append(basename(dirname(src))) prov_new = {} for d,reqs in list(prov.items()) : l = [] r = d.split("/") while r : item = r.pop() l.insert(0,item) for req in reqs : prov_new.setdefault("/".join(r),[]).append(".".join(l + [req])) for path,reqs in list(prov_new.items()) : prov.setdefault(path,[]).extend(reqs) #for d,reqs in prov.items() : # print d # for req in reqs : # print "\t",req all_prov_items = [] list(map(lambda items: all_prov_items.extend(items), list(prov.values()))) import re # Parser/tokenizer.c:get_coding_spec() re_coding = re.compile(r'^\s*#.*?coding[:=]\s*([\w._-]+)') def get_raw_encoding(line) : enc = re_coding.search(line) if enc : return enc.group(1) # Parser/tokenizer.c:get_normal_name() def get_enc_normal_name(enc) : enc = enc.lower().replace('_','-') if enc.startswith('utf-8') : return 'utf-8' for alias in ['latin-1','iso-8859-1','iso-latin-1'] : if enc.startswith(alias) : return 'iso-8859-1' return enc missing_encodings = None def get_encoding_module(enc) : mod = 'encodings' try : from encodings import search_function except : global missing_encodings missing_encodings = True return mod try : mod = search_function(enc)[1].__self__.__class__.__module__ print("python.req: %s: encoding=%s module=%s" % (src,enc,mod), file=sys.stderr) except : pass return mod def need_encoding_module(line): enc = get_raw_encoding(line) if enc : enc = get_enc_normal_name(enc) if enc not in ['utf-8','iso-8859-1'] : print("python.req: %s: non-standard encoding: %s" % (src,enc), file=sys.stderr) mod = get_encoding_module(enc) return mod found_deps = [] for src in files : ext = os.path.splitext(basename(src))[1] if ext not in ['.so','.pyc','.pyo','.pth'] : try: lines = [ line.rstrip().replace('\r','') for line in open(src, encoding="utf-8").readlines() ] except: lines = [] encmod = None if len(lines) > 0 : encmod = need_encoding_module(lines[0]) if not encmod and len(lines) > 1 : encmod = need_encoding_module(lines[1]) if encmod : print("%s(%s)" % (prefix,encmod)) def must_fail() : if ext == '.py' : return True if len(lines) > 0 and lines[0].startswith('#!') : return True try : lis = parser.suite('\n'.join(lines)+'\n').tolist(line_info=1) except Exception as msg : print('python.req: ERROR: %s: %s' % (src,msg), file=sys.stderr) if encmod and missing_encodings : print("python.req: maybe you need python-modules-encodings", file=sys.stderr) if must_fail() : raise else : print("python.req: %s: possibly not pythonish file" % src, file=sys.stderr) continue for item in match(lis) : #if not item in prov[dirname(src)] : if not item in all_prov_items : if not ignore(item) : # generating all (including python3-base) dependencies, maybe check against base_modules in future found_deps.append("%s(%s)" % (prefix,item)) for dep in found_deps : print(dep) rpm_br=os.path.normpath(os.getenv('RPM_BUILD_ROOT',"")) if rpm_br in ['','/','.'] : br_len = 0 else : br_len = len(rpm_br) #print rpm_br modules = [ os.path.normpath(x) for x in os.getenv('RPM_PYTHON3_MODULE_DECLARED','').split() ] #print modules # it's better to use set here # it's better to remove pythons with version < 2.4 HA XEP to use set here and arround dirs = {} for src in files : #print 1,src if os.path.splitext(basename(src))[1] in ['.py',''] : src = dirname(os.path.normpath(src)) #print 2,br_len,src[br_len:] if src[br_len:] in modules: dirs[src] = 1 #print dirs # collected [unique] directories which are marked as separate packages. # now filter them to keep only those which don't have __init__.py (in this package) # and finally print required dependencies def print_func(a): print(a) list(map(lambda finit: print_func(finit[br_len:]), # print path to __init__.py w/o buildroot [init for init in [os.path.join(dir, '__init__.py') for dir in list(dirs.keys())] if not init in files])) # ex: set ts=8 sts=4 sw=4 et: rpm-build-python3-0.1.7/test.sh000075500000000000000000000011641213161274200163310ustar00rootroot00000000000000#!/bin/sh -efu RC=0 TestReq() { code="$1" modules="$2" echo "$code" >.tmp.py out=$(RPM_BUILD_ROOT="$PWD" RPM_PYTHON3_PATH=/ ./python3.req .tmp.py) out=`echo $out | tr -s '\n' ' ' | sed -e 's,python3.[0-9],python3,g' | sed -e 's, $,,g'` if [ "$out" != "$modules" ]; then echo FAIL code="'$code'" expected="'$modules'" got="'$out'" RC=1 else echo OK code="'$code'" result="'$out'" fi } TestReq 'import m1, m2' 'python3(m1) python3(m2)' #TestReq 'import os, m1' 'python-base python3(m1)' #TestReq 'import os, urllib2, m1' 'python-modules python3(m1)' TestReq '# coding: cp1251' 'python3(encodings.cp1251)' exit $RC