Add pathfix.py into python-rpm-macros and update macros to use it
Resolves: RHEL-6107
This commit is contained in:
		
							parent
							
								
									c5599c235c
								
							
						
					
					
						commit
						c2a69948b3
					
				| @ -19,18 +19,12 @@ | |||||||
| %py_shbang_opts_nodash %(opts=%{py_shbang_opts}; echo ${opts#-}) | %py_shbang_opts_nodash %(opts=%{py_shbang_opts}; echo ${opts#-}) | ||||||
| %py_shebang_flags %(opts=%{py_shbang_opts}; echo ${opts#-}) | %py_shebang_flags %(opts=%{py_shbang_opts}; echo ${opts#-}) | ||||||
| %py_shebang_fix %{expand:\\\ | %py_shebang_fix %{expand:\\\ | ||||||
|   if [ -f /usr/bin/pathfix%{python_version}.py ]; then |  | ||||||
|     pathfix=/usr/bin/pathfix%{python_version}.py |  | ||||||
|   else |  | ||||||
|     # older versions of Python don't have it and must BR /usr/bin/pathfix.py from python3-devel explicitly |  | ||||||
|     pathfix=/usr/bin/pathfix.py |  | ||||||
|   fi |  | ||||||
|   if [ -z "%{?py_shebang_flags}" ]; then |   if [ -z "%{?py_shebang_flags}" ]; then | ||||||
|     shebang_flags="-k" |     shebang_flags="-k" | ||||||
|   else |   else | ||||||
|     shebang_flags="-ka%{py_shebang_flags}" |     shebang_flags="-ka%{py_shebang_flags}" | ||||||
|   fi |   fi | ||||||
|   $pathfix -pni %{__python} $shebang_flags} |   %{__python} -B %{_rpmconfigdir}/redhat/pathfix.py -pni %{__python} $shebang_flags} | ||||||
| 
 | 
 | ||||||
| # Use the slashes after expand so that the command starts on the same line as | # Use the slashes after expand so that the command starts on the same line as | ||||||
| # the macro | # the macro | ||||||
|  | |||||||
| @ -17,18 +17,12 @@ | |||||||
| %py3_shbang_opts_nodash %(opts=%{py3_shbang_opts}; echo ${opts#-}) | %py3_shbang_opts_nodash %(opts=%{py3_shbang_opts}; echo ${opts#-}) | ||||||
| %py3_shebang_flags %(opts=%{py3_shbang_opts}; echo ${opts#-}) | %py3_shebang_flags %(opts=%{py3_shbang_opts}; echo ${opts#-}) | ||||||
| %py3_shebang_fix %{expand:\\\ | %py3_shebang_fix %{expand:\\\ | ||||||
|   if [ -f /usr/bin/pathfix%{python3_version}.py ]; then |  | ||||||
|     pathfix=/usr/bin/pathfix%{python3_version}.py |  | ||||||
|   else |  | ||||||
|     # older versions of Python don't have it and must BR /usr/bin/pathfix.py from python3-devel explicitly |  | ||||||
|     pathfix=/usr/bin/pathfix.py |  | ||||||
|   fi |  | ||||||
|   if [ -z "%{?py3_shebang_flags}" ]; then |   if [ -z "%{?py3_shebang_flags}" ]; then | ||||||
|     shebang_flags="-k" |     shebang_flags="-k" | ||||||
|   else |   else | ||||||
|     shebang_flags="-ka%{py3_shebang_flags}" |     shebang_flags="-ka%{py3_shebang_flags}" | ||||||
|   fi |   fi | ||||||
|   $pathfix -pni %{__python3} $shebang_flags} |   %{__python3} -B %{_rpmconfigdir}/redhat/pathfix.py -pni %{__python3} $shebang_flags} | ||||||
| 
 | 
 | ||||||
| # Use the slashes after expand so that the command starts on the same line as | # Use the slashes after expand so that the command starts on the same line as | ||||||
| # the macro | # the macro | ||||||
|  | |||||||
							
								
								
									
										199
									
								
								pathfix.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								pathfix.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import sys | ||||||
|  | import os | ||||||
|  | from stat import * | ||||||
|  | import getopt | ||||||
|  | 
 | ||||||
|  | err = sys.stderr.write | ||||||
|  | dbg = err | ||||||
|  | rep = sys.stdout.write | ||||||
|  | 
 | ||||||
|  | new_interpreter = None | ||||||
|  | preserve_timestamps = False | ||||||
|  | create_backup = True | ||||||
|  | keep_flags = False | ||||||
|  | add_flags = b'' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def main(): | ||||||
|  |     global new_interpreter | ||||||
|  |     global preserve_timestamps | ||||||
|  |     global create_backup | ||||||
|  |     global keep_flags | ||||||
|  |     global add_flags | ||||||
|  | 
 | ||||||
|  |     usage = ('usage: %s -i /interpreter -p -n -k -a file-or-directory ...\n' % | ||||||
|  |              sys.argv[0]) | ||||||
|  |     try: | ||||||
|  |         opts, args = getopt.getopt(sys.argv[1:], 'i:a:kpn') | ||||||
|  |     except getopt.error as msg: | ||||||
|  |         err(str(msg) + '\n') | ||||||
|  |         err(usage) | ||||||
|  |         sys.exit(2) | ||||||
|  |     for o, a in opts: | ||||||
|  |         if o == '-i': | ||||||
|  |             new_interpreter = a.encode() | ||||||
|  |         if o == '-p': | ||||||
|  |             preserve_timestamps = True | ||||||
|  |         if o == '-n': | ||||||
|  |             create_backup = False | ||||||
|  |         if o == '-k': | ||||||
|  |             keep_flags = True | ||||||
|  |         if o == '-a': | ||||||
|  |             add_flags = a.encode() | ||||||
|  |             if b' ' in add_flags: | ||||||
|  |                 err("-a option doesn't support whitespaces") | ||||||
|  |                 sys.exit(2) | ||||||
|  |     if not new_interpreter or not new_interpreter.startswith(b'/') or \ | ||||||
|  |            not args: | ||||||
|  |         err('-i option or file-or-directory missing\n') | ||||||
|  |         err(usage) | ||||||
|  |         sys.exit(2) | ||||||
|  |     bad = 0 | ||||||
|  |     for arg in args: | ||||||
|  |         if os.path.isdir(arg): | ||||||
|  |             if recursedown(arg): bad = 1 | ||||||
|  |         elif os.path.islink(arg): | ||||||
|  |             err(arg + ': will not process symbolic links\n') | ||||||
|  |             bad = 1 | ||||||
|  |         else: | ||||||
|  |             if fix(arg): bad = 1 | ||||||
|  |     sys.exit(bad) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def ispython(name): | ||||||
|  |     return name.endswith('.py') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def recursedown(dirname): | ||||||
|  |     dbg('recursedown(%r)\n' % (dirname,)) | ||||||
|  |     bad = 0 | ||||||
|  |     try: | ||||||
|  |         names = os.listdir(dirname) | ||||||
|  |     except OSError as msg: | ||||||
|  |         err('%s: cannot list directory: %r\n' % (dirname, msg)) | ||||||
|  |         return 1 | ||||||
|  |     names.sort() | ||||||
|  |     subdirs = [] | ||||||
|  |     for name in names: | ||||||
|  |         if name in (os.curdir, os.pardir): continue | ||||||
|  |         fullname = os.path.join(dirname, name) | ||||||
|  |         if os.path.islink(fullname): pass | ||||||
|  |         elif os.path.isdir(fullname): | ||||||
|  |             subdirs.append(fullname) | ||||||
|  |         elif ispython(name): | ||||||
|  |             if fix(fullname): bad = 1 | ||||||
|  |     for fullname in subdirs: | ||||||
|  |         if recursedown(fullname): bad = 1 | ||||||
|  |     return bad | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def fix(filename): | ||||||
|  | ##  dbg('fix(%r)\n' % (filename,)) | ||||||
|  |     try: | ||||||
|  |         f = open(filename, 'rb') | ||||||
|  |     except IOError as msg: | ||||||
|  |         err('%s: cannot open: %r\n' % (filename, msg)) | ||||||
|  |         return 1 | ||||||
|  |     with f: | ||||||
|  |         line = f.readline() | ||||||
|  |         fixed = fixline(line) | ||||||
|  |         if line == fixed: | ||||||
|  |             rep(filename+': no change\n') | ||||||
|  |             return | ||||||
|  |         head, tail = os.path.split(filename) | ||||||
|  |         tempname = os.path.join(head, '@' + tail) | ||||||
|  |         try: | ||||||
|  |             g = open(tempname, 'wb') | ||||||
|  |         except IOError as msg: | ||||||
|  |             err('%s: cannot create: %r\n' % (tempname, msg)) | ||||||
|  |             return 1 | ||||||
|  |         with g: | ||||||
|  |             rep(filename + ': updating\n') | ||||||
|  |             g.write(fixed) | ||||||
|  |             BUFSIZE = 8*1024 | ||||||
|  |             while 1: | ||||||
|  |                 buf = f.read(BUFSIZE) | ||||||
|  |                 if not buf: break | ||||||
|  |                 g.write(buf) | ||||||
|  | 
 | ||||||
|  |     # Finishing touch -- move files | ||||||
|  | 
 | ||||||
|  |     mtime = None | ||||||
|  |     atime = None | ||||||
|  |     # First copy the file's mode to the temp file | ||||||
|  |     try: | ||||||
|  |         statbuf = os.stat(filename) | ||||||
|  |         mtime = statbuf.st_mtime | ||||||
|  |         atime = statbuf.st_atime | ||||||
|  |         os.chmod(tempname, statbuf[ST_MODE] & 0o7777) | ||||||
|  |     except OSError as msg: | ||||||
|  |         err('%s: warning: chmod failed (%r)\n' % (tempname, msg)) | ||||||
|  |     # Then make a backup of the original file as filename~ | ||||||
|  |     if create_backup: | ||||||
|  |         try: | ||||||
|  |             os.rename(filename, filename + '~') | ||||||
|  |         except OSError as msg: | ||||||
|  |             err('%s: warning: backup failed (%r)\n' % (filename, msg)) | ||||||
|  |     else: | ||||||
|  |         try: | ||||||
|  |             os.remove(filename) | ||||||
|  |         except OSError as msg: | ||||||
|  |             err('%s: warning: removing failed (%r)\n' % (filename, msg)) | ||||||
|  |     # Now move the temp file to the original file | ||||||
|  |     try: | ||||||
|  |         os.rename(tempname, filename) | ||||||
|  |     except OSError as msg: | ||||||
|  |         err('%s: rename failed (%r)\n' % (filename, msg)) | ||||||
|  |         return 1 | ||||||
|  |     if preserve_timestamps: | ||||||
|  |         if atime and mtime: | ||||||
|  |             try: | ||||||
|  |                 os.utime(filename, (atime, mtime)) | ||||||
|  |             except OSError as msg: | ||||||
|  |                 err('%s: reset of timestamp failed (%r)\n' % (filename, msg)) | ||||||
|  |                 return 1 | ||||||
|  |     # Return success | ||||||
|  |     return 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def parse_shebang(shebangline): | ||||||
|  |     shebangline = shebangline.rstrip(b'\n') | ||||||
|  |     start = shebangline.find(b' -') | ||||||
|  |     if start == -1: | ||||||
|  |         return b'' | ||||||
|  |     return shebangline[start:] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def populate_flags(shebangline): | ||||||
|  |     old_flags = b'' | ||||||
|  |     if keep_flags: | ||||||
|  |         old_flags = parse_shebang(shebangline) | ||||||
|  |         if old_flags: | ||||||
|  |             old_flags = old_flags[2:] | ||||||
|  |     if not (old_flags or add_flags): | ||||||
|  |         return b'' | ||||||
|  |     # On Linux, the entire string following the interpreter name | ||||||
|  |     # is passed as a single argument to the interpreter. | ||||||
|  |     # e.g. "#! /usr/bin/python3 -W Error -s" runs "/usr/bin/python3 "-W Error -s" | ||||||
|  |     # so shebang should have single '-' where flags are given and | ||||||
|  |     # flag might need argument for that reasons adding new flags is | ||||||
|  |     # between '-' and original flags | ||||||
|  |     # e.g. #! /usr/bin/python3 -sW Error | ||||||
|  |     return b' -' + add_flags + old_flags | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def fixline(line): | ||||||
|  |     if not line.startswith(b'#!'): | ||||||
|  |         return line | ||||||
|  | 
 | ||||||
|  |     if b"python" not in line: | ||||||
|  |         return line | ||||||
|  | 
 | ||||||
|  |     flags = populate_flags(line) | ||||||
|  |     return b'#! ' + new_interpreter + flags + b'\n' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     main() | ||||||
| @ -1,12 +1,13 @@ | |||||||
| Name:           python-rpm-macros | Name:           python-rpm-macros | ||||||
| Version:        3.9 | Version:        3.9 | ||||||
| Release:        52%{?dist} | Release:        53%{?dist} | ||||||
| Summary:        The common Python RPM macros | Summary:        The common Python RPM macros | ||||||
| URL:            https://src.fedoraproject.org/rpms/python-rpm-macros/ | URL:            https://src.fedoraproject.org/rpms/python-rpm-macros/ | ||||||
| 
 | 
 | ||||||
| # macros and lua: MIT | # macros and lua: MIT | ||||||
| # import_all_modules.py: MIT | # import_all_modules.py: MIT | ||||||
| # compileall2.py: PSFv2 | # compileall2.py: PSFv2 | ||||||
|  | # pathfix.py: PSFv2 | ||||||
| License:        MIT and Python | License:        MIT and Python | ||||||
| 
 | 
 | ||||||
| # Macros: | # Macros: | ||||||
| @ -22,6 +23,8 @@ Source201:      python.lua | |||||||
| %global compileall2_version 0.7.1 | %global compileall2_version 0.7.1 | ||||||
| Source301:      https://github.com/fedora-python/compileall2/raw/v%{compileall2_version}/compileall2.py | Source301:      https://github.com/fedora-python/compileall2/raw/v%{compileall2_version}/compileall2.py | ||||||
| Source302:      import_all_modules.py | Source302:      import_all_modules.py | ||||||
|  | %global pathfix_version 1.0.0 | ||||||
|  | Source303:      https://github.com/fedora-python/pathfix/raw/v%{pathfix_version}/pathfix.py | ||||||
| 
 | 
 | ||||||
| BuildArch:      noarch | BuildArch:      noarch | ||||||
| 
 | 
 | ||||||
| @ -83,6 +86,10 @@ RPM macros for building Python 3 packages. | |||||||
| %autosetup -c -T | %autosetup -c -T | ||||||
| cp -a %{sources} . | cp -a %{sources} . | ||||||
| 
 | 
 | ||||||
|  | # We want to have shebang in the script upstream but not here so | ||||||
|  | # the package with macros does not depend on Python. | ||||||
|  | sed -i '1s=^#!/usr/bin/env python3==' pathfix.py | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| %install | %install | ||||||
| mkdir -p %{buildroot}%{rpmmacrodir} | mkdir -p %{buildroot}%{rpmmacrodir} | ||||||
| @ -95,6 +102,8 @@ mkdir -p %{buildroot}%{_rpmconfigdir}/redhat | |||||||
| install -m 644 compileall2.py %{buildroot}%{_rpmconfigdir}/redhat/ | install -m 644 compileall2.py %{buildroot}%{_rpmconfigdir}/redhat/ | ||||||
| install -m 644 import_all_modules.py %{buildroot}%{_rpmconfigdir}/redhat/ | install -m 644 import_all_modules.py %{buildroot}%{_rpmconfigdir}/redhat/ | ||||||
| 
 | 
 | ||||||
|  | install -m 644 pathfix.py %{buildroot}%{_rpmconfigdir}/redhat/ | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| %check | %check | ||||||
| # no macros in comments | # no macros in comments | ||||||
| @ -105,6 +114,7 @@ install -m 644 import_all_modules.py %{buildroot}%{_rpmconfigdir}/redhat/ | |||||||
| %{rpmmacrodir}/macros.python | %{rpmmacrodir}/macros.python | ||||||
| %{rpmmacrodir}/macros.pybytecompile | %{rpmmacrodir}/macros.pybytecompile | ||||||
| %{_rpmconfigdir}/redhat/import_all_modules.py | %{_rpmconfigdir}/redhat/import_all_modules.py | ||||||
|  | %{_rpmconfigdir}/redhat/pathfix.py | ||||||
| 
 | 
 | ||||||
| %files -n python-srpm-macros | %files -n python-srpm-macros | ||||||
| %{rpmmacrodir}/macros.python-srpm | %{rpmmacrodir}/macros.python-srpm | ||||||
| @ -116,6 +126,10 @@ install -m 644 import_all_modules.py %{buildroot}%{_rpmconfigdir}/redhat/ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Thu Nov 02 2023 Tomas Orsava <torsava@redhat.com> - 3.9-53 | ||||||
|  | - Update macros from Fedora and add pathfix.py into python-rpm-macros | ||||||
|  | - Resolves: RHEL-6107 | ||||||
|  | 
 | ||||||
| * Tue Feb 08 2022 Tomas Orsava <torsava@redhat.com> - 3.9-52 | * Tue Feb 08 2022 Tomas Orsava <torsava@redhat.com> - 3.9-52 | ||||||
| - %%py_provides: Do not generate Obsoletes for names containing parentheses | - %%py_provides: Do not generate Obsoletes for names containing parentheses | ||||||
| - Related: rhbz#1990421 | - Related: rhbz#1990421 | ||||||
|  | |||||||
| @ -376,7 +376,7 @@ def test_pypi_source_explicit_tilde(): | |||||||
| 
 | 
 | ||||||
| def test_py3_shebang_fix(): | def test_py3_shebang_fix(): | ||||||
|     cmd = rpm_eval('%py3_shebang_fix arg1 arg2 arg3')[-1].strip() |     cmd = rpm_eval('%py3_shebang_fix arg1 arg2 arg3')[-1].strip() | ||||||
|     assert cmd == '$pathfix -pni /usr/bin/python3 $shebang_flags arg1 arg2 arg3' |     assert cmd == '/usr/bin/python3 -B /usr/lib/rpm/redhat/pathfix.py -pni /usr/bin/python3 $shebang_flags arg1 arg2 arg3' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_py3_shebang_fix_default_shebang_flags(): | def test_py3_shebang_fix_default_shebang_flags(): | ||||||
| @ -400,7 +400,7 @@ def test_py3_shebang_fix_no_shebang_flags(flags): | |||||||
| 
 | 
 | ||||||
| def test_py_shebang_fix_custom_python(): | def test_py_shebang_fix_custom_python(): | ||||||
|     cmd = rpm_eval('%py_shebang_fix arg1 arg2 arg3', __python='/usr/bin/pypy')[-1].strip() |     cmd = rpm_eval('%py_shebang_fix arg1 arg2 arg3', __python='/usr/bin/pypy')[-1].strip() | ||||||
|     assert cmd == '$pathfix -pni /usr/bin/pypy $shebang_flags arg1 arg2 arg3' |     assert cmd == '/usr/bin/pypy -B /usr/lib/rpm/redhat/pathfix.py -pni /usr/bin/pypy $shebang_flags arg1 arg2 arg3' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_pycached_in_sitelib(): | def test_pycached_in_sitelib(): | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user