Mercurial > hg
changeset 49005:12adf8c695ed
merge: stable into default
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Tue, 05 Apr 2022 11:09:03 +0200 |
parents | 20c6c9e43397 (diff) 9dcfd1d05e6e (current diff) |
children | 82dbe3a2920d |
files | mercurial/dispatch.py rust/Cargo.lock rust/hg-core/Cargo.toml rust/hg-core/src/dirstate_tree/dirstate_map.rs rust/hg-core/src/repo.rs |
diffstat | 687 files changed, 2601 insertions(+), 7437 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Tue Apr 05 10:55:28 2022 +0200 +++ b/.hgignore Tue Apr 05 11:09:03 2022 +0200 @@ -22,6 +22,8 @@ tests/artifacts/cache/big-file-churn.hg tests/.coverage* tests/.testtimes* +# the file is written in the CWD when run-tests is run. +.testtimes tests/.hypothesis tests/hypothesis-generated tests/annotated
--- a/Makefile Tue Apr 05 10:55:28 2022 +0200 +++ b/Makefile Tue Apr 05 11:09:03 2022 +0200 @@ -151,12 +151,9 @@ $(MAKE) -f $(HGROOT)/contrib/Makefile.python PYTHONVER=$* PREFIX=$(HGPYTHONS)/$* python ) cd tests && $(HGPYTHONS)/$*/bin/python run-tests.py $(TESTFLAGS) -rust-tests: py_feature = $(shell $(PYTHON) -c \ - 'import sys; print(["python27-bin", "python3-bin"][sys.version_info[0] >= 3])') rust-tests: cd $(HGROOT)/rust/hg-cpython \ - && $(CARGO) test --quiet --all \ - --no-default-features --features "$(py_feature) $(HG_RUST_FEATURES)" + && $(CARGO) test --quiet --all --features "$(HG_RUST_FEATURES)" check-code: hg manifest | xargs python contrib/check-code.py @@ -238,16 +235,6 @@ # Place a bogon .DS_Store file in the target dir so we can be # sure it doesn't get included in the final package. touch build/mercurial/.DS_Store - # install zsh completions - this location appears to be - # searched by default as of macOS Sierra. - install -d build/mercurial/usr/local/share/zsh/site-functions/ - install -m 0644 contrib/zsh_completion build/mercurial/usr/local/share/zsh/site-functions/_hg - # install bash completions - there doesn't appear to be a - # place that's searched by default for bash, so we'll follow - # the lead of Apple's git install and just put it in a - # location of our own. - install -d build/mercurial/usr/local/hg/contrib/ - install -m 0644 contrib/bash_completion build/mercurial/usr/local/hg/contrib/hg-completion.bash make -C contrib/chg \ HGPATH=/usr/local/bin/hg \ PYTHON=/usr/bin/python2.7 \
--- a/contrib/automation/hgautomation/aws.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/automation/hgautomation/aws.py Tue Apr 05 11:09:03 2022 +0200 @@ -919,17 +919,12 @@ 'SecurityGroupIds': [c.security_groups['linux-dev-1'].id], } - requirements2_path = ( - pathlib.Path(__file__).parent.parent / 'linux-requirements-py2.txt' - ) requirements3_path = ( pathlib.Path(__file__).parent.parent / 'linux-requirements-py3.txt' ) requirements35_path = ( pathlib.Path(__file__).parent.parent / 'linux-requirements-py3.5.txt' ) - with requirements2_path.open('r', encoding='utf-8') as fh: - requirements2 = fh.read() with requirements3_path.open('r', encoding='utf-8') as fh: requirements3 = fh.read() with requirements35_path.open('r', encoding='utf-8') as fh: @@ -941,7 +936,6 @@ { 'instance_config': config, 'bootstrap_script': BOOTSTRAP_DEBIAN, - 'requirements_py2': requirements2, 'requirements_py3': requirements3, 'requirements_py35': requirements35, } @@ -977,10 +971,6 @@ fh.write(BOOTSTRAP_DEBIAN) fh.chmod(0o0700) - with sftp.open('%s/requirements-py2.txt' % home, 'wb') as fh: - fh.write(requirements2) - fh.chmod(0o0700) - with sftp.open('%s/requirements-py3.txt' % home, 'wb') as fh: fh.write(requirements3) fh.chmod(0o0700)
--- a/contrib/automation/hgautomation/cli.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/automation/hgautomation/cli.py Tue Apr 05 11:09:03 2022 +0200 @@ -65,7 +65,6 @@ def build_inno( hga: HGAutomation, aws_region, - python_version, arch, revision, version, @@ -80,21 +79,18 @@ windows.synchronize_hg(SOURCE_ROOT, revision, instance) - for py_version in python_version: - for a in arch: - windows.build_inno_installer( - instance.winrm_client, - py_version, - a, - DIST_PATH, - version=version, - ) + for a in arch: + windows.build_inno_installer( + instance.winrm_client, + a, + DIST_PATH, + version=version, + ) def build_wix( hga: HGAutomation, aws_region, - python_version, arch, revision, version, @@ -109,15 +105,13 @@ windows.synchronize_hg(SOURCE_ROOT, revision, instance) - for py_version in python_version: - for a in arch: - windows.build_wix_installer( - instance.winrm_client, - py_version, - a, - DIST_PATH, - version=version, - ) + for a in arch: + windows.build_wix_installer( + instance.winrm_client, + a, + DIST_PATH, + version=version, + ) def build_windows_wheel( @@ -158,7 +152,7 @@ windows.synchronize_hg(SOURCE_ROOT, revision, instance) - for py_version in ("2.7", "3.7", "3.8", "3.9", "3.10"): + for py_version in ("3.7", "3.8", "3.9", "3.10"): for arch in ("x86", "x64"): windows.purge_hg(winrm_client) windows.build_wheel( @@ -168,15 +162,14 @@ dest_path=DIST_PATH, ) - for py_version in (2, 3): - for arch in ('x86', 'x64'): - windows.purge_hg(winrm_client) - windows.build_inno_installer( - winrm_client, py_version, arch, DIST_PATH, version=version - ) - windows.build_wix_installer( - winrm_client, py_version, arch, DIST_PATH, version=version - ) + for arch in ('x86', 'x64'): + windows.purge_hg(winrm_client) + windows.build_inno_installer( + winrm_client, arch, DIST_PATH, version=version + ) + windows.build_wix_installer( + winrm_client, arch, DIST_PATH, version=version + ) def terminate_ec2_instances(hga: HGAutomation, aws_region): @@ -340,14 +333,6 @@ help='Build Inno Setup installer(s)', ) sp.add_argument( - '--python-version', - help='Which version of Python to target', - choices={2, 3}, - type=int, - nargs='*', - default=[3], - ) - sp.add_argument( '--arch', help='Architecture to build for', choices={'x86', 'x64'}, @@ -377,7 +362,7 @@ sp.add_argument( '--python-version', help='Python version to build for', - choices={'2.7', '3.7', '3.8', '3.9', '3.10'}, + choices={'3.7', '3.8', '3.9', '3.10'}, nargs='*', default=['3.8'], ) @@ -402,14 +387,6 @@ sp = subparsers.add_parser('build-wix', help='Build WiX installer(s)') sp.add_argument( - '--python-version', - help='Which version of Python to target', - choices={2, 3}, - type=int, - nargs='*', - default=[3], - ) - sp.add_argument( '--arch', help='Architecture to build for', choices={'x86', 'x64'}, @@ -469,9 +446,7 @@ '--python-version', help='Python version to use', choices={ - 'system2', 'system3', - '2.7', '3.5', '3.6', '3.7', @@ -480,7 +455,7 @@ 'pypy3.5', 'pypy3.6', }, - default='system2', + default='system3', ) sp.add_argument( 'test_flags', @@ -501,8 +476,8 @@ sp.add_argument( '--python-version', help='Python version to use', - choices={'2.7', '3.5', '3.6', '3.7', '3.8', '3.9', '3.10'}, - default='2.7', + choices={'3.5', '3.6', '3.7', '3.8', '3.9', '3.10'}, + default='3.9', ) sp.add_argument( '--arch',
--- a/contrib/automation/hgautomation/linux.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/automation/hgautomation/linux.py Tue Apr 05 11:09:03 2022 +0200 @@ -25,7 +25,6 @@ } INSTALL_PYTHONS = r''' -PYENV2_VERSIONS="2.7.17 pypy2.7-7.2.0" PYENV3_VERSIONS="3.5.10 3.6.13 3.7.10 3.8.10 3.9.5 pypy3.5-7.0.0 pypy3.6-7.3.3 pypy3.7-7.3.3" git clone https://github.com/pyenv/pyenv.git /hgdev/pyenv @@ -46,13 +45,6 @@ wget -O ${VIRTUALENV_TARBALL} --progress dot:mega https://files.pythonhosted.org/packages/66/f0/6867af06d2e2f511e4e1d7094ff663acdebc4f15d4a0cb0fed1007395124/${VIRTUALENV_TARBALL} echo "${VIRTUALENV_SHA256} ${VIRTUALENV_TARBALL}" | sha256sum --check - -for v in ${PYENV2_VERSIONS}; do - pyenv install -v ${v} - ${PYENV_ROOT}/versions/${v}/bin/python get-pip.py - ${PYENV_ROOT}/versions/${v}/bin/pip install ${VIRTUALENV_TARBALL} - ${PYENV_ROOT}/versions/${v}/bin/pip install -r /hgdev/requirements-py2.txt -done - for v in ${PYENV3_VERSIONS}; do pyenv install -v ${v} ${PYENV_ROOT}/versions/${v}/bin/python get-pip.py @@ -72,7 +64,7 @@ ${PYENV_ROOT}/versions/${v}/bin/pip install -r /hgdev/${REQUIREMENTS} done -pyenv global ${PYENV2_VERSIONS} ${PYENV3_VERSIONS} system +pyenv global ${PYENV3_VERSIONS} system '''.lstrip().replace( '\r\n', '\n' ) @@ -274,17 +266,8 @@ netbase \ ntfs-3g \ nvme-cli \ - pyflakes \ pyflakes3 \ - pylint \ pylint3 \ - python-all-dev \ - python-dev \ - python-docutils \ - python-fuzzywuzzy \ - python-pygments \ - python-subversion \ - python-vcr \ python3-boto3 \ python3-dev \ python3-docutils \ @@ -532,7 +515,7 @@ hg_bin = source_path / 'hg' res = subprocess.run( - ['python2.7', str(hg_bin), 'log', '-r', revision, '-T', '{node}'], + ['python3', str(hg_bin), 'log', '-r', revision, '-T', '{node}'], cwd=str(source_path), env=env, check=True, @@ -542,7 +525,7 @@ full_revision = res.stdout.decode('ascii') args = [ - 'python2.7', + 'python3', str(hg_bin), '--config', 'ui.ssh=ssh -F %s' % ssh_config, @@ -595,9 +578,7 @@ print('running tests') - if python_version == 'system2': - python = '/usr/bin/python2' - elif python_version == 'system3': + if python_version == 'system3': python = '/usr/bin/python3' elif python_version.startswith('pypy'): python = '/hgdev/pyenv/shims/%s' % python_version
--- a/contrib/automation/hgautomation/windows.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/automation/hgautomation/windows.py Tue Apr 05 11:09:03 2022 +0200 @@ -19,30 +19,6 @@ from .winrm import run_powershell -# PowerShell commands to activate a Visual Studio 2008 environment. -# This is essentially a port of vcvarsall.bat to PowerShell. -ACTIVATE_VC9_AMD64 = r''' -Write-Output "activating Visual Studio 2008 environment for AMD64" -$root = "$env:LOCALAPPDATA\Programs\Common\Microsoft\Visual C++ for Python\9.0" -$Env:VCINSTALLDIR = "${root}\VC\" -$Env:WindowsSdkDir = "${root}\WinSDK\" -$Env:PATH = "${root}\VC\Bin\amd64;${root}\WinSDK\Bin\x64;${root}\WinSDK\Bin;$Env:PATH" -$Env:INCLUDE = "${root}\VC\Include;${root}\WinSDK\Include;$Env:PATH" -$Env:LIB = "${root}\VC\Lib\amd64;${root}\WinSDK\Lib\x64;$Env:LIB" -$Env:LIBPATH = "${root}\VC\Lib\amd64;${root}\WinSDK\Lib\x64;$Env:LIBPATH" -'''.lstrip() - -ACTIVATE_VC9_X86 = r''' -Write-Output "activating Visual Studio 2008 environment for x86" -$root = "$env:LOCALAPPDATA\Programs\Common\Microsoft\Visual C++ for Python\9.0" -$Env:VCINSTALLDIR = "${root}\VC\" -$Env:WindowsSdkDir = "${root}\WinSDK\" -$Env:PATH = "${root}\VC\Bin;${root}\WinSDK\Bin;$Env:PATH" -$Env:INCLUDE = "${root}\VC\Include;${root}\WinSDK\Include;$Env:INCLUDE" -$Env:LIB = "${root}\VC\Lib;${root}\WinSDK\Lib;$Env:LIB" -$Env:LIBPATH = "${root}\VC\lib;${root}\WinSDK\Lib;$Env:LIBPATH" -'''.lstrip() - HG_PURGE = r''' $Env:PATH = "C:\hgdev\venv-bootstrap\Scripts;$Env:PATH" Set-Location C:\hgdev\src @@ -78,14 +54,6 @@ }} ''' -BUILD_INNO_PYTHON2 = r''' -Set-Location C:\hgdev\src -$python = "C:\hgdev\python27-{arch}\python.exe" -C:\hgdev\python37-x64\python.exe contrib\packaging\packaging.py inno --python $python {extra_args} -if ($LASTEXITCODE -ne 0) {{ - throw "process exited non-0: $LASTEXITCODE" -}} -'''.lstrip() BUILD_WHEEL = r''' Set-Location C:\hgdev\src @@ -105,14 +73,6 @@ }} ''' -BUILD_WIX_PYTHON2 = r''' -Set-Location C:\hgdev\src -$python = "C:\hgdev\python27-{arch}\python.exe" -C:\hgdev\python37-x64\python.exe contrib\packaging\packaging.py wix --python $python {extra_args} -if ($LASTEXITCODE -ne 0) {{ - throw "process exited non-0: $LASTEXITCODE" -}} -''' RUN_TESTS = r''' C:\hgdev\MinGW\msys\1.0\bin\sh.exe --login -c "cd /c/hgdev/src/tests && /c/hgdev/{python_path}/python.exe run-tests.py {test_flags}" @@ -121,8 +81,7 @@ }} ''' -WHEEL_FILENAME_PYTHON27_X86 = 'mercurial-{version}-cp27-cp27m-win32.whl' -WHEEL_FILENAME_PYTHON27_X64 = 'mercurial-{version}-cp27-cp27m-win_amd64.whl' + WHEEL_FILENAME_PYTHON37_X86 = 'mercurial-{version}-cp37-cp37m-win32.whl' WHEEL_FILENAME_PYTHON37_X64 = 'mercurial-{version}-cp37-cp37m-win_amd64.whl' WHEEL_FILENAME_PYTHON38_X86 = 'mercurial-{version}-cp38-cp38-win32.whl' @@ -132,13 +91,9 @@ WHEEL_FILENAME_PYTHON310_X86 = 'mercurial-{version}-cp310-cp310-win32.whl' WHEEL_FILENAME_PYTHON310_X64 = 'mercurial-{version}-cp310-cp310-win_amd64.whl' -EXE_FILENAME_PYTHON2_X86 = 'Mercurial-{version}-x86-python2.exe' -EXE_FILENAME_PYTHON2_X64 = 'Mercurial-{version}-x64-python2.exe' EXE_FILENAME_PYTHON3_X86 = 'Mercurial-{version}-x86.exe' EXE_FILENAME_PYTHON3_X64 = 'Mercurial-{version}-x64.exe' -MSI_FILENAME_PYTHON2_X86 = 'mercurial-{version}-x86-python2.msi' -MSI_FILENAME_PYTHON2_X64 = 'mercurial-{version}-x64-python2.msi' MSI_FILENAME_PYTHON3_X86 = 'mercurial-{version}-x86.msi' MSI_FILENAME_PYTHON3_X64 = 'mercurial-{version}-x64.msi' @@ -147,14 +102,6 @@ X86_USER_AGENT_PATTERN = '.*Windows.*' X64_USER_AGENT_PATTERN = '.*Windows.*(WOW|x)64.*' -EXE_PYTHON2_X86_DESCRIPTION = ( - 'Mercurial {version} Inno Setup installer - x86 Windows (Python 2) ' - '- does not require admin rights' -) -EXE_PYTHON2_X64_DESCRIPTION = ( - 'Mercurial {version} Inno Setup installer - x64 Windows (Python 2) ' - '- does not require admin rights' -) # TODO remove Python version once Python 2 is dropped. EXE_PYTHON3_X86_DESCRIPTION = ( 'Mercurial {version} Inno Setup installer - x86 Windows (Python 3) ' @@ -164,14 +111,6 @@ 'Mercurial {version} Inno Setup installer - x64 Windows (Python 3) ' '- does not require admin rights' ) -MSI_PYTHON2_X86_DESCRIPTION = ( - 'Mercurial {version} MSI installer - x86 Windows (Python 2) ' - '- requires admin rights' -) -MSI_PYTHON2_X64_DESCRIPTION = ( - 'Mercurial {version} MSI installer - x64 Windows (Python 2) ' - '- requires admin rights' -) MSI_PYTHON3_X86_DESCRIPTION = ( 'Mercurial {version} MSI installer - x86 Windows (Python 3) ' '- requires admin rights' @@ -182,15 +121,6 @@ ) -def get_vc_prefix(arch): - if arch == 'x86': - return ACTIVATE_VC9_X86 - elif arch == 'x64': - return ACTIVATE_VC9_AMD64 - else: - raise ValueError('illegal arch: %s; must be x86 or x64' % arch) - - def fix_authorized_keys_permissions(winrm_client, path): commands = [ '$ErrorActionPreference = "Stop"', @@ -261,7 +191,7 @@ hg_bin = hg_repo / 'hg' res = subprocess.run( - ['python2.7', str(hg_bin), 'log', '-r', revision, '-T', '{node}'], + ['python3', str(hg_bin), 'log', '-r', revision, '-T', '{node}'], cwd=str(hg_repo), env=env, check=True, @@ -271,7 +201,7 @@ full_revision = res.stdout.decode('ascii') args = [ - 'python2.7', + 'python3', hg_bin, '--config', 'ui.ssh=ssh -F %s' % ssh_config, @@ -334,7 +264,6 @@ def build_inno_installer( winrm_client, - python_version: int, arch: str, dest_path: pathlib.Path, version=None, @@ -344,37 +273,23 @@ Using a WinRM client, remote commands are executed to build a Mercurial Inno Setup installer. """ - print( - 'building Inno Setup installer for Python %d %s' - % (python_version, arch) - ) + print('building Inno Setup installer for %s' % arch) - if python_version == 3: - # TODO fix this limitation in packaging code - if not version: - raise Exception( - "version string is required when building for Python 3" - ) + # TODO fix this limitation in packaging code + if not version: + raise Exception("version string is required when building for Python 3") - if arch == "x86": - target_triple = "i686-pc-windows-msvc" - elif arch == "x64": - target_triple = "x86_64-pc-windows-msvc" - else: - raise Exception("unhandled arch: %s" % arch) + if arch == "x86": + target_triple = "i686-pc-windows-msvc" + elif arch == "x64": + target_triple = "x86_64-pc-windows-msvc" + else: + raise Exception("unhandled arch: %s" % arch) - ps = BUILD_INNO_PYTHON3.format( - pyoxidizer_target=target_triple, - version=version, - ) - else: - extra_args = [] - if version: - extra_args.extend(['--version', version]) - - ps = get_vc_prefix(arch) + BUILD_INNO_PYTHON2.format( - arch=arch, extra_args=' '.join(extra_args) - ) + ps = BUILD_INNO_PYTHON3.format( + pyoxidizer_target=target_triple, + version=version, + ) run_powershell(winrm_client, ps) copy_latest_dist(winrm_client, '*.exe', dest_path) @@ -394,17 +309,12 @@ python_version=python_version.replace(".", ""), arch=arch ) - # Python 2.7 requires an activated environment. - if python_version == "2.7": - ps = get_vc_prefix(arch) + ps - run_powershell(winrm_client, ps) copy_latest_dist(winrm_client, '*.whl', dest_path) def build_wix_installer( winrm_client, - python_version: int, arch: str, dest_path: pathlib.Path, version=None, @@ -413,34 +323,23 @@ Using a WinRM client, remote commands are executed to build a WiX installer. """ - print('Building WiX installer for Python %d %s' % (python_version, arch)) + print('Building WiX installer for %s' % arch) - if python_version == 3: - # TODO fix this limitation in packaging code - if not version: - raise Exception( - "version string is required when building for Python 3" - ) + # TODO fix this limitation in packaging code + if not version: + raise Exception("version string is required when building for Python 3") - if arch == "x86": - target_triple = "i686-pc-windows-msvc" - elif arch == "x64": - target_triple = "x86_64-pc-windows-msvc" - else: - raise Exception("unhandled arch: %s" % arch) + if arch == "x86": + target_triple = "i686-pc-windows-msvc" + elif arch == "x64": + target_triple = "x86_64-pc-windows-msvc" + else: + raise Exception("unhandled arch: %s" % arch) - ps = BUILD_WIX_PYTHON3.format( - pyoxidizer_target=target_triple, - version=version, - ) - else: - extra_args = [] - if version: - extra_args.extend(['--version', version]) - - ps = get_vc_prefix(arch) + BUILD_WIX_PYTHON2.format( - arch=arch, extra_args=' '.join(extra_args) - ) + ps = BUILD_WIX_PYTHON3.format( + pyoxidizer_target=target_triple, + version=version, + ) run_powershell(winrm_client, ps) copy_latest_dist(winrm_client, '*.msi', dest_path) @@ -474,8 +373,6 @@ def resolve_wheel_artifacts(dist_path: pathlib.Path, version: str): return ( - dist_path / WHEEL_FILENAME_PYTHON27_X86.format(version=version), - dist_path / WHEEL_FILENAME_PYTHON27_X64.format(version=version), dist_path / WHEEL_FILENAME_PYTHON37_X86.format(version=version), dist_path / WHEEL_FILENAME_PYTHON37_X64.format(version=version), dist_path / WHEEL_FILENAME_PYTHON38_X86.format(version=version), @@ -489,8 +386,6 @@ def resolve_all_artifacts(dist_path: pathlib.Path, version: str): return ( - dist_path / WHEEL_FILENAME_PYTHON27_X86.format(version=version), - dist_path / WHEEL_FILENAME_PYTHON27_X64.format(version=version), dist_path / WHEEL_FILENAME_PYTHON37_X86.format(version=version), dist_path / WHEEL_FILENAME_PYTHON37_X64.format(version=version), dist_path / WHEEL_FILENAME_PYTHON38_X86.format(version=version), @@ -499,24 +394,16 @@ dist_path / WHEEL_FILENAME_PYTHON39_X64.format(version=version), dist_path / WHEEL_FILENAME_PYTHON310_X86.format(version=version), dist_path / WHEEL_FILENAME_PYTHON310_X64.format(version=version), - dist_path / EXE_FILENAME_PYTHON2_X86.format(version=version), - dist_path / EXE_FILENAME_PYTHON2_X64.format(version=version), dist_path / EXE_FILENAME_PYTHON3_X86.format(version=version), dist_path / EXE_FILENAME_PYTHON3_X64.format(version=version), - dist_path / MSI_FILENAME_PYTHON2_X86.format(version=version), - dist_path / MSI_FILENAME_PYTHON2_X64.format(version=version), dist_path / MSI_FILENAME_PYTHON3_X86.format(version=version), dist_path / MSI_FILENAME_PYTHON3_X64.format(version=version), ) def generate_latest_dat(version: str): - python2_x86_exe_filename = EXE_FILENAME_PYTHON2_X86.format(version=version) - python2_x64_exe_filename = EXE_FILENAME_PYTHON2_X64.format(version=version) python3_x86_exe_filename = EXE_FILENAME_PYTHON3_X86.format(version=version) python3_x64_exe_filename = EXE_FILENAME_PYTHON3_X64.format(version=version) - python2_x86_msi_filename = MSI_FILENAME_PYTHON2_X86.format(version=version) - python2_x64_msi_filename = MSI_FILENAME_PYTHON2_X64.format(version=version) python3_x86_msi_filename = MSI_FILENAME_PYTHON3_X86.format(version=version) python3_x64_msi_filename = MSI_FILENAME_PYTHON3_X64.format(version=version) @@ -536,20 +423,6 @@ EXE_PYTHON3_X64_DESCRIPTION.format(version=version), ), ( - '9', - version, - X86_USER_AGENT_PATTERN, - '%s/%s' % (MERCURIAL_SCM_BASE_URL, python2_x86_exe_filename), - EXE_PYTHON2_X86_DESCRIPTION.format(version=version), - ), - ( - '9', - version, - X64_USER_AGENT_PATTERN, - '%s/%s' % (MERCURIAL_SCM_BASE_URL, python2_x64_exe_filename), - EXE_PYTHON2_X64_DESCRIPTION.format(version=version), - ), - ( '10', version, X86_USER_AGENT_PATTERN, @@ -563,20 +436,6 @@ '%s/%s' % (MERCURIAL_SCM_BASE_URL, python3_x64_msi_filename), MSI_PYTHON3_X64_DESCRIPTION.format(version=version), ), - ( - '9', - version, - X86_USER_AGENT_PATTERN, - '%s/%s' % (MERCURIAL_SCM_BASE_URL, python2_x86_msi_filename), - MSI_PYTHON2_X86_DESCRIPTION.format(version=version), - ), - ( - '9', - version, - X64_USER_AGENT_PATTERN, - '%s/%s' % (MERCURIAL_SCM_BASE_URL, python2_x64_msi_filename), - MSI_PYTHON2_X64_DESCRIPTION.format(version=version), - ), ) lines = ['\t'.join(e) for e in entries]
--- a/contrib/automation/linux-requirements-py2.txt Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile --generate-hashes --output-file=contrib/automation/linux-requirements-py2.txt contrib/automation/linux-requirements.txt.in -# -astroid==1.6.6 \ - --hash=sha256:87de48a92e29cedf7210ffa853d11441e7ad94cb47bacd91b023499b51cbc756 \ - --hash=sha256:d25869fc7f44f1d9fb7d24fd7ea0639656f5355fc3089cd1f3d18c6ec6b124c7 \ - # via pylint -backports.functools-lru-cache==1.6.1 \ - --hash=sha256:0bada4c2f8a43d533e4ecb7a12214d9420e66eb206d54bf2d682581ca4b80848 \ - --hash=sha256:8fde5f188da2d593bd5bc0be98d9abc46c95bb8a9dde93429570192ee6cc2d4a \ - # via astroid, isort, pylint -bzr==2.7.0 ; python_version <= "2.7" and platform_python_implementation == "CPython" \ - --hash=sha256:c9f6bbe0a50201dadc5fddadd94ba50174193c6cf6e39e16f6dd0ad98a1df338 \ - # via -r contrib/automation/linux-requirements.txt.in -configparser==4.0.2 \ - --hash=sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c \ - --hash=sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df \ - # via pylint -contextlib2==0.6.0.post1 \ - --hash=sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e \ - --hash=sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b \ - # via vcrpy -docutils==0.16 \ - --hash=sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af \ - --hash=sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc \ - # via -r contrib/automation/linux-requirements.txt.in -enum34==1.1.10 \ - --hash=sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53 \ - --hash=sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328 \ - --hash=sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248 \ - # via astroid -funcsigs==1.0.2 \ - --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \ - --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50 \ - # via mock -futures==3.3.0 \ - --hash=sha256:49b3f5b064b6e3afc3316421a3f25f66c137ae88f068abbf72830170033c5e16 \ - --hash=sha256:7e033af76a5e35f58e56da7a91e687706faf4e7bdfb2cbc3f2cca6b9bcda9794 \ - # via isort -fuzzywuzzy==0.18.0 \ - --hash=sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8 \ - --hash=sha256:928244b28db720d1e0ee7587acf660ea49d7e4c632569cad4f1cd7e68a5f0993 \ - # via -r contrib/automation/linux-requirements.txt.in -isort==4.3.21 \ - --hash=sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1 \ - --hash=sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd \ - # via pylint -lazy-object-proxy==1.5.1 \ - --hash=sha256:00b78a97a79d0dfefa584d44dd1aba9668d3de7ec82335ba0ff51d53ef107143 \ - --hash=sha256:042b54fd71c2092e6d10e5e66fa60f65c5954f8145e809f5d9f394c9b13d32ee \ - --hash=sha256:11f87dc06eb5f376cc6d5f0c19a1b4dca202035622777c4ce8e5b72c87b035d6 \ - --hash=sha256:19ae6f6511a02008ef3554e158c41bb2a8e5c8455935b98d6da076d9f152fd7c \ - --hash=sha256:22c1935c6f8e3d6ea2e169eb03928adbdb8a2251d2890f8689368d65e70aa176 \ - --hash=sha256:30ef2068f4f94660144515380ef04b93d15add2214eab8be4cd46ebc900d681c \ - --hash=sha256:33da47ba3a581860ddd3d38c950a5fe950ca389f7123edd0d6ab0bc473499fe7 \ - --hash=sha256:3e8698dc384857413580012f4ca322d89e63ef20fc3d4635a5b606d6d4b61f6a \ - --hash=sha256:4fdd7113fc5143c72dacf415079eec42fcbe69cc9d3d291b4ca742e3a9455807 \ - --hash=sha256:63b6d9a5077d54db271fcc6772440f7380ec3fa559d0e2497dbfae2f47c2c814 \ - --hash=sha256:8133b63b05f12751cddd8e3e7f02ba39dc7cfa7d2ba99d80d7436f0ba26d6b75 \ - --hash=sha256:89b8e5780e49753e2b4cd5aab45d3df092ddcbba3de2c4d4492a029588fe1758 \ - --hash=sha256:8d82e27cbbea6edb8821751806f39f5dcfd7b46a5e23d27b98d6d8c8ec751df8 \ - --hash=sha256:92cedd6e26712505adb1c17fab64651a498cc0102a80ba562ff4a2451088f57a \ - --hash=sha256:9723364577b79ad9958a68851fe2acb94da6fd25170c595516a8289e6a129043 \ - --hash=sha256:c484020ad26973a14a7cb1e1d2e0bfe97cf6803273ae9bd154e0213cc74bad49 \ - --hash=sha256:c697bd1b333b3e6abdff04ef9f5fb4b1936633d9cc4e28d90606705c9083254c \ - --hash=sha256:d0f7e14ff3424639d33e6bc449e77e4b345e52c21bbd6f6004a1d219196e2664 \ - --hash=sha256:db2df3eff7ed3e6813638686f1bb5934d1a0662d9d3b4196b5164a86be3a1e8f \ - --hash=sha256:edbcb4c5efabd93ede05b272296a5a78a67e9b6e82ba7f51a07b8103db06ce01 \ - --hash=sha256:ef355fb3802e0fc5a71dadb65a3c317bfc9bdf567d357f8e0b1900b432ffe486 \ - --hash=sha256:fe2f61fed5817bf8db01d9a72309ed5990c478a077e9585b58740c26774bce39 \ - # via astroid -mccabe==0.6.1 \ - --hash=sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42 \ - --hash=sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f \ - # via pylint -mock==3.0.5 \ - --hash=sha256:83657d894c90d5681d62155c82bda9c1187827525880eda8ff5df4ec813437c3 \ - --hash=sha256:d157e52d4e5b938c550f39eb2fd15610db062441a9c2747d3dbfa9298211d0f8 \ - # via vcrpy -pyflakes==2.2.0 \ - --hash=sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92 \ - --hash=sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8 \ - # via -r contrib/automation/linux-requirements.txt.in -pygments==2.5.2 \ - --hash=sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b \ - --hash=sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe \ - # via -r contrib/automation/linux-requirements.txt.in -pylint==1.9.5 \ - --hash=sha256:367e3d49813d349a905390ac27989eff82ab84958731c5ef0bef867452cfdc42 \ - --hash=sha256:97a42df23d436c70132971d1dcb9efad2fe5c0c6add55b90161e773caf729300 \ - # via -r contrib/automation/linux-requirements.txt.in -python-levenshtein==0.12.0 \ - --hash=sha256:033a11de5e3d19ea25c9302d11224e1a1898fe5abd23c61c7c360c25195e3eb1 \ - # via -r contrib/automation/linux-requirements.txt.in -pyyaml==5.3.1 \ - --hash=sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97 \ - --hash=sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76 \ - --hash=sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2 \ - --hash=sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648 \ - --hash=sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf \ - --hash=sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f \ - --hash=sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2 \ - --hash=sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee \ - --hash=sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d \ - --hash=sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c \ - --hash=sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a \ - # via vcrpy -singledispatch==3.4.0.3 \ - --hash=sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c \ - --hash=sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8 \ - # via astroid, pylint -six==1.15.0 \ - --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ - --hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced \ - # via astroid, mock, pylint, singledispatch, vcrpy -vcrpy==3.0.0 \ - --hash=sha256:21168d5ae14263a833d4b71acfd8278d8841114f24be1b4ab4a5719d0c7f07bc \ - --hash=sha256:a2e6b653a627f9f3d6ded4d68587e470b91e4c1444e7dae939510dfeacb65276 \ - # via -r contrib/automation/linux-requirements.txt.in -wrapt==1.12.1 \ - --hash=sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7 \ - # via astroid, vcrpy - -# WARNING: The following packages were not pinned, but pip requires them to be -# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag. -# setuptools
--- a/contrib/bdiff-torture.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/bdiff-torture.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # Randomized torture test generation for bdiff -from __future__ import absolute_import, print_function import random import sys
--- a/contrib/benchmarks/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/benchmarks/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -31,7 +31,6 @@ $ asv --config contrib/asv.conf.json preview ''' -from __future__ import absolute_import import functools import os
--- a/contrib/benchmarks/perf.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/benchmarks/perf.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from . import perfbench
--- a/contrib/benchmarks/revset.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/benchmarks/revset.py Tue Apr 05 11:09:03 2022 +0200 @@ -10,7 +10,6 @@ Each revset benchmark is parameterized with variants (first, last, sort, ...) ''' -from __future__ import absolute_import import os import string
--- a/contrib/byteify-strings.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/byteify-strings.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import argparse import contextlib
--- a/contrib/casesmash.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/casesmash.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import __builtin__ import os from mercurial import util
--- a/contrib/catapipe.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/catapipe.py Tue Apr 05 11:09:03 2022 +0200 @@ -34,7 +34,6 @@ HGCATAPULTSERVERPIPE environment variable, which both run-tests and hg understand. To trace *only* run-tests, use HGTESTCATAPULTSERVERPIPE instead. """ -from __future__ import absolute_import, print_function import argparse import json
--- a/contrib/check-code.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/check-code.py Tue Apr 05 11:09:03 2022 +0200 @@ -19,7 +19,6 @@ * ONLY use no--check-code for skipping entire files from external sources """ -from __future__ import absolute_import, print_function import glob import keyword import optparse @@ -344,16 +343,6 @@ "linebreak after :", ), ( - r'class\s[^( \n]+:', - "old-style class, use class foo(object)", - r'#.*old-style', - ), - ( - r'class\s[^( \n]+\(\):', - "class foo() creates old style object, use class foo(object)", - r'#.*old-style', - ), - ( r'\b(%s)\(' % '|'.join(k for k in keyword.kwlist if k not in ('print', 'exec')), "Python keyword is not a function", @@ -431,26 +420,6 @@ "module-level @cachefunc is risky, please avoid", ), ( - r'^import Queue', - "don't use Queue, use pycompat.queue.Queue + " - "pycompat.queue.Empty", - ), - ( - r'^import cStringIO', - "don't use cStringIO.StringIO, use util.stringio", - ), - (r'^import urllib', "don't use urllib, use util.urlreq/util.urlerr"), - ( - r'^import SocketServer', - "don't use SockerServer, use util.socketserver", - ), - (r'^import urlparse', "don't use urlparse, use util.urlreq"), - (r'^import xmlrpclib', "don't use xmlrpclib, use util.xmlrpclib"), - (r'^import cPickle', "don't use cPickle, use util.pickle"), - (r'^import pickle', "don't use pickle, use util.pickle"), - (r'^import httplib', "don't use httplib, use util.httplib"), - (r'^import BaseHTTPServer', "use util.httpserver instead"), - ( r'^(from|import) mercurial\.(cext|pure|cffi)', "use mercurial.policy.importmod instead", ), @@ -789,7 +758,7 @@ preparefilters(filters) -class norepeatlogger(object): +class norepeatlogger: def __init__(self): self._lastseen = None
--- a/contrib/check-commit Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/check-commit Tue Apr 05 11:09:03 2022 +0200 @@ -15,7 +15,6 @@ # # See also: https://mercurial-scm.org/wiki/ContributingChanges -from __future__ import absolute_import, print_function import os import re
--- a/contrib/check-config.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/check-config.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import re import sys
--- a/contrib/check-py3-compat.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/check-py3-compat.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import ast import importlib @@ -17,31 +16,6 @@ import warnings -def check_compat_py2(f): - """Check Python 3 compatibility for a file with Python 2""" - with open(f, 'rb') as fh: - content = fh.read() - root = ast.parse(content) - - # Ignore empty files. - if not root.body: - return - - futures = set() - haveprint = False - for node in ast.walk(root): - if isinstance(node, ast.ImportFrom): - if node.module == '__future__': - futures |= {n.name for n in node.names} - elif isinstance(node, ast.Print): - haveprint = True - - if 'absolute_import' not in futures: - print('%s not using absolute_import' % f) - if haveprint and 'print_function' not in futures: - print('%s requires print_function' % f) - - def check_compat_py3(f): """Check Python 3 compatibility of a file with Python 3.""" with open(f, 'rb') as fh: @@ -94,23 +68,19 @@ if __name__ == '__main__': - if sys.version_info[0] == 2: - fn = check_compat_py2 - else: - # check_compat_py3 will import every filename we specify as long as it - # starts with one of a few prefixes. It does this by converting - # specified filenames like 'mercurial/foo.py' to 'mercurial.foo' and - # importing that. When running standalone (not as part of a test), this - # means we actually import the installed versions, not the files we just - # specified. When running as test-check-py3-compat.t, we technically - # would import the correct paths, but it's cleaner to have both cases - # use the same import logic. - sys.path.insert(0, '.') - fn = check_compat_py3 + # check_compat_py3 will import every filename we specify as long as it + # starts with one of a few prefixes. It does this by converting + # specified filenames like 'mercurial/foo.py' to 'mercurial.foo' and + # importing that. When running standalone (not as part of a test), this + # means we actually import the installed versions, not the files we just + # specified. When running as test-check-py3-compat.t, we technically + # would import the correct paths, but it's cleaner to have both cases + # use the same import logic. + sys.path.insert(0, '.') for f in sys.argv[1:]: with warnings.catch_warnings(record=True) as warns: - fn(f) + check_compat_py3(f) for w in warns: print(
--- a/contrib/debugcmdserver.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/debugcmdserver.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # $ ./hg serve --cmds pipe | ./contrib/debugcmdserver.py - # o, 52 -> 'capabilities: getencoding runcommand\nencoding: UTF-8' -from __future__ import absolute_import, print_function import struct import sys
--- a/contrib/debugshell.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/debugshell.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ # debugshell extension """a python shell with repo, changelog & manifest objects""" -from __future__ import absolute_import import code import mercurial import sys
--- a/contrib/dumprevlog Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/dumprevlog Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # Dump revlogs as raw data stream # $ find .hg/store/ -name "*.i" | xargs dumprevlog > repo.dump -from __future__ import absolute_import, print_function import sys from mercurial.node import hex
--- a/contrib/fuzz/dirs_corpus.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/fuzz/dirs_corpus.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import argparse import zipfile
--- a/contrib/fuzz/dirstate_corpus.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/fuzz/dirstate_corpus.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import argparse import os import zipfile
--- a/contrib/fuzz/fm1readmarkers_corpus.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/fuzz/fm1readmarkers_corpus.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import argparse import zipfile
--- a/contrib/fuzz/manifest_corpus.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/fuzz/manifest_corpus.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import argparse import zipfile
--- a/contrib/fuzz/mpatch_corpus.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/fuzz/mpatch_corpus.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import argparse import os import struct @@ -22,7 +20,7 @@ if sys.version_info[0] < 3: - class py2reprhack(object): + class py2reprhack: def __repr__(self): """Py2 calls __repr__ for `bytes(foo)`, forward to __bytes__""" return self.__bytes__() @@ -30,7 +28,7 @@ else: - class py2reprhack(object): + class py2reprhack: """Not needed on py3."""
--- a/contrib/fuzz/revlog_corpus.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/fuzz/revlog_corpus.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import argparse import os import zipfile
--- a/contrib/genosxversion.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/genosxversion.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ #!/usr/bin/env python2 -from __future__ import absolute_import, print_function import argparse import os
--- a/contrib/heptapod-ci.yml Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/heptapod-ci.yml Tue Apr 05 11:09:03 2022 +0200 @@ -30,27 +30,17 @@ - echo "$RUNTEST_ARGS" - HGTESTS_ALLOW_NETIO="$TEST_HGTESTS_ALLOW_NETIO" HGMODULEPOLICY="$TEST_HGMODULEPOLICY" "$PYTHON" tests/run-tests.py --color=always $RUNTEST_ARGS -checks-py2: - <<: *runtests - variables: - RUNTEST_ARGS: "--time --test-list /tmp/check-tests.txt" - -checks-py3: +checks: <<: *runtests variables: RUNTEST_ARGS: "--time --test-list /tmp/check-tests.txt" PYTHON: python3 -rust-cargo-test-py2: &rust_cargo_test - <<: *all +rust-cargo-test: stage: tests script: - echo "python used, $PYTHON" - make rust-tests - -rust-cargo-test-py3: - stage: tests - <<: *rust_cargo_test variables: PYTHON: python3 @@ -72,14 +62,7 @@ ./contrib/phab-refresh-stack.sh --comment "$DEFAULT_COMMENT"; fi -test-py2: - <<: *runtests - variables: - RUNTEST_ARGS: " --no-rust --blacklist /tmp/check-tests.txt" - TEST_HGMODULEPOLICY: "c" - TEST_HGTESTS_ALLOW_NETIO: "1" - -test-py3: +test-c: <<: *runtests variables: RUNTEST_ARGS: " --no-rust --blacklist /tmp/check-tests.txt" @@ -87,27 +70,14 @@ TEST_HGMODULEPOLICY: "c" TEST_HGTESTS_ALLOW_NETIO: "1" -test-py2-pure: - <<: *runtests - variables: - RUNTEST_ARGS: "--pure --blacklist /tmp/check-tests.txt" - TEST_HGMODULEPOLICY: "py" - -test-py3-pure: +test-pure: <<: *runtests variables: RUNTEST_ARGS: "--pure --blacklist /tmp/check-tests.txt" PYTHON: python3 TEST_HGMODULEPOLICY: "py" -test-py2-rust: - <<: *runtests - variables: - HGWITHRUSTEXT: cpython - RUNTEST_ARGS: "--rust --blacklist /tmp/check-tests.txt" - TEST_HGMODULEPOLICY: "rust+c" - -test-py3-rust: +test-rust: <<: *runtests variables: HGWITHRUSTEXT: cpython @@ -115,7 +85,7 @@ PYTHON: python3 TEST_HGMODULEPOLICY: "rust+c" -test-py3-rhg: +test-rhg: <<: *runtests variables: HGWITHRUSTEXT: cpython @@ -123,20 +93,14 @@ PYTHON: python3 TEST_HGMODULEPOLICY: "rust+c" -test-py2-chg: - <<: *runtests - variables: - RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt --chg" - TEST_HGMODULEPOLICY: "c" - -test-py3-chg: +test-chg: <<: *runtests variables: PYTHON: python3 RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt --chg" TEST_HGMODULEPOLICY: "c" -check-pytype-py3: +check-pytype: extends: .runtests_template before_script: - hg clone . /tmp/mercurial-ci/ --noupdate --config phases.publish=no @@ -174,7 +138,7 @@ - C:/MinGW/msys/1.0/bin/sh.exe --login -c 'cd "$OLDPWD" && HGTESTS_ALLOW_NETIO="$TEST_HGTESTS_ALLOW_NETIO" HGMODULEPOLICY="$TEST_HGMODULEPOLICY" $PYTHON tests/run-tests.py --color=always $RUNTEST_ARGS' -windows-py3: +windows: <<: *windows_runtests tags: - windows @@ -183,7 +147,7 @@ RUNTEST_ARGS: "--blacklist C:/Temp/check-tests.txt" PYTHON: py -3 -windows-py3-pyox: +windows-pyox: <<: *windows_runtests tags: - windows
--- a/contrib/hg-ssh Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/hg-ssh Tue Apr 05 11:09:03 2022 +0200 @@ -28,7 +28,6 @@ You can also add a --read-only flag to allow read-only access to a key, e.g.: command="hg-ssh --read-only repos/*" """ -from __future__ import absolute_import import os import re
--- a/contrib/hgclient.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/hgclient.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # A minimal client for Mercurial's command server -from __future__ import absolute_import, print_function import io import os @@ -50,7 +49,7 @@ return server -class unixconnection(object): +class unixconnection: def __init__(self, sockpath): self.sock = sock = socket.socket(socket.AF_UNIX) sock.connect(sockpath) @@ -63,7 +62,7 @@ self.sock.close() -class unixserver(object): +class unixserver: def __init__(self, sockpath, logpath=None, repopath=None): self.sockpath = sockpath cmdline = [b'hg', b'serve', b'--cmdserver', b'unix', b'-a', sockpath]
--- a/contrib/import-checker.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/import-checker.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -from __future__ import absolute_import, print_function import ast import collections @@ -20,10 +19,11 @@ import testparseutil -# Whitelist of modules that symbols can be directly imported from. +# Allow list of modules that symbols can be directly imported from. allowsymbolimports = ( '__future__', 'breezy', + 'concurrent', 'hgclient', 'mercurial', 'mercurial.hgweb.common', @@ -46,9 +46,10 @@ 'mercurial.thirdparty.attr', 'mercurial.thirdparty.zope', 'mercurial.thirdparty.zope.interface', + 'typing', ) -# Whitelist of symbols that can be directly imported. +# Allow list of symbols that can be directly imported. directsymbols = ('demandimport',) # Modules that must be aliased because they are commonly confused with @@ -58,21 +59,6 @@ } -def usingabsolute(root): - """Whether absolute imports are being used.""" - if sys.version_info[0] >= 3: - return True - - for node in ast.walk(root): - if isinstance(node, ast.ImportFrom): - if node.module == '__future__': - for n in node.names: - if n.name == 'absolute_import': - return True - - return False - - def walklocal(root): """Recursively yield all descendant nodes but not in a different scope""" todo = collections.deque(ast.iter_child_nodes(root)) @@ -402,21 +388,10 @@ def verify_import_convention(module, source, localmods): - """Verify imports match our established coding convention. - - We have 2 conventions: legacy and modern. The modern convention is in - effect when using absolute imports. + """Verify imports match our established coding convention.""" + root = ast.parse(source) - The legacy convention only looks for mixed imports. The modern convention - is much more thorough. - """ - root = ast.parse(source) - absolute = usingabsolute(root) - - if absolute: - return verify_modern_convention(module, root, localmods) - else: - return verify_stdlib_on_own_line(root) + return verify_modern_convention(module, root, localmods) def verify_modern_convention(module, root, localmods, root_col_offset=0): @@ -617,33 +592,6 @@ ) -def verify_stdlib_on_own_line(root): - """Given some python source, verify that stdlib imports are done - in separate statements from relative local module imports. - - >>> list(verify_stdlib_on_own_line(ast.parse('import sys, foo'))) - [('mixed imports\\n stdlib: sys\\n relative: foo', 1)] - >>> list(verify_stdlib_on_own_line(ast.parse('import sys, os'))) - [] - >>> list(verify_stdlib_on_own_line(ast.parse('import foo, bar'))) - [] - """ - for node in ast.walk(root): - if isinstance(node, ast.Import): - from_stdlib = {False: [], True: []} - for n in node.names: - from_stdlib[n.name in stdlib_modules].append(n.name) - if from_stdlib[True] and from_stdlib[False]: - yield ( - 'mixed imports\n stdlib: %s\n relative: %s' - % ( - ', '.join(sorted(from_stdlib[True])), - ', '.join(sorted(from_stdlib[False])), - ), - node.lineno, - ) - - class CircularImport(Exception): pass @@ -679,7 +627,6 @@ All module names recorded in `imports` should be absolute one. - >>> from __future__ import print_function >>> imports = {'top.foo': ['top.bar', 'os.path', 'top.qux'], ... 'top.bar': ['top.baz', 'sys'], ... 'top.baz': ['top.foo'],
--- a/contrib/memory.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/memory.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,8 +11,6 @@ prints it to ``stderr`` on exit. ''' -from __future__ import absolute_import - def memusage(ui): """Report memory usage of the current process."""
--- a/contrib/packaging/debian/rules Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/debian/rules Tue Apr 05 11:09:03 2022 +0200 @@ -92,10 +92,8 @@ mkdir -p "$(CURDIR)"/debian/mercurial/etc/mercurial/hgrc.d/ cp contrib/packaging/debian/*.rc "$(CURDIR)"/debian/mercurial/etc/mercurial/hgrc.d/ # completions - mkdir -p "$(CURDIR)"/debian/mercurial/usr/share/bash-completion/completions - cp contrib/bash_completion "$(CURDIR)"/debian/mercurial/usr/share/bash-completion/completions/hg mkdir -p "$(CURDIR)"/debian/mercurial/usr/share/zsh/vendor-completions - cp contrib/zsh_completion "$(CURDIR)"/debian/mercurial/usr/share/zsh/vendor-completions/_hg + mv "$(CURDIR)"/debian/mercurial/usr/share/zsh/site-functions/_hg "$(CURDIR)"/debian/mercurial/usr/share/zsh/vendor-completions/_hg if [ "$(DEB_HG_CHG_BY_DEFAULT)" -eq 1 ]; then \ mkdir -p "$(CURDIR)"/debian/mercurial/usr/lib/mercurial; \ mv "$(CURDIR)"/debian/mercurial/usr/bin/hg "$(CURDIR)"/debian/mercurial/usr/lib/mercurial/hg; \
--- a/contrib/packaging/hgpackaging/cli.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/hgpackaging/cli.py Tue Apr 05 11:09:03 2022 +0200 @@ -20,13 +20,7 @@ SOURCE_DIR = HERE.parent.parent.parent -def build_inno(pyoxidizer_target=None, python=None, iscc=None, version=None): - if not pyoxidizer_target and not python: - raise Exception("--python required unless building with PyOxidizer") - - if python and not os.path.isabs(python): - raise Exception("--python arg must be an absolute path") - +def build_inno(pyoxidizer_target, iscc=None, version=None): if iscc: iscc = pathlib.Path(iscc) else: @@ -38,59 +32,30 @@ build_dir = SOURCE_DIR / "build" - if pyoxidizer_target: - inno.build_with_pyoxidizer( - SOURCE_DIR, build_dir, pyoxidizer_target, iscc, version=version - ) - else: - inno.build_with_py2exe( - SOURCE_DIR, - build_dir, - pathlib.Path(python), - iscc, - version=version, - ) + inno.build_with_pyoxidizer( + SOURCE_DIR, build_dir, pyoxidizer_target, iscc, version=version + ) def build_wix( + pyoxidizer_target, name=None, - pyoxidizer_target=None, - python=None, version=None, sign_sn=None, sign_cert=None, sign_password=None, sign_timestamp_url=None, - extra_packages_script=None, extra_wxs=None, extra_features=None, extra_pyoxidizer_vars=None, ): - if not pyoxidizer_target and not python: - raise Exception("--python required unless building with PyOxidizer") - - if python and not os.path.isabs(python): - raise Exception("--python arg must be an absolute path") - kwargs = { "source_dir": SOURCE_DIR, "version": version, + "target_triple": pyoxidizer_target, + "extra_pyoxidizer_vars": extra_pyoxidizer_vars, } - if pyoxidizer_target: - fn = wix.build_installer_pyoxidizer - kwargs["target_triple"] = pyoxidizer_target - kwargs["extra_pyoxidizer_vars"] = extra_pyoxidizer_vars - else: - fn = wix.build_installer_py2exe - kwargs["python_exe"] = pathlib.Path(python) - - if extra_packages_script: - if pyoxidizer_target: - raise Exception( - "pyoxidizer does not support --extra-packages-script" - ) - kwargs["extra_packages_script"] = extra_packages_script if extra_wxs: kwargs["extra_wxs"] = dict( thing.split("=") for thing in extra_wxs.split(",") @@ -107,7 +72,7 @@ "timestamp_url": sign_timestamp_url, } - fn(**kwargs) + wix.build_installer_pyoxidizer(**kwargs) def get_parser(): @@ -119,9 +84,9 @@ sp.add_argument( "--pyoxidizer-target", choices={"i686-pc-windows-msvc", "x86_64-pc-windows-msvc"}, + required=True, help="Build with PyOxidizer targeting this host triple", ) - sp.add_argument("--python", help="path to python.exe to use") sp.add_argument("--iscc", help="path to iscc.exe to use") sp.add_argument( "--version", @@ -137,9 +102,9 @@ sp.add_argument( "--pyoxidizer-target", choices={"i686-pc-windows-msvc", "x86_64-pc-windows-msvc"}, + required=True, help="Build with PyOxidizer targeting this host triple", ) - sp.add_argument("--python", help="Path to Python executable to use") sp.add_argument( "--sign-sn", help="Subject name (or fragment thereof) of certificate " @@ -155,12 +120,6 @@ ) sp.add_argument("--version", help="Version string to use") sp.add_argument( - "--extra-packages-script", - help=( - "Script to execute to include extra packages in " "py2exe binary." - ), - ) - sp.add_argument( "--extra-wxs", help="CSV of path_to_wxs_file=working_dir_for_wxs_file" ) sp.add_argument(
--- a/contrib/packaging/hgpackaging/downloads.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/hgpackaging/downloads.py Tue Apr 05 11:09:03 2022 +0200 @@ -25,48 +25,6 @@ 'size': 715086, 'sha256': '411f94974492fd2ecf52590cb05b1023530aec67e64154a88b1e4ebcd9c28588', }, - 'py2exe': { - 'url': 'https://versaweb.dl.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.zip', - 'size': 149687, - 'sha256': '6bd383312e7d33eef2e43a5f236f9445e4f3e0f6b16333c6f183ed445c44ddbd', - 'version': '0.6.9', - }, - # The VC9 CRT merge modules aren't readily available on most systems because - # they are only installed as part of a full Visual Studio 2008 install. - # While we could potentially extract them from a Visual Studio 2008 - # installer, it is easier to just fetch them from a known URL. - 'vc9-crt-x86-msm': { - 'url': 'https://github.com/indygreg/vc90-merge-modules/raw/9232f8f0b2135df619bf7946eaa176b4ac35ccff/Microsoft_VC90_CRT_x86.msm', - 'size': 615424, - 'sha256': '837e887ef31b332feb58156f429389de345cb94504228bb9a523c25a9dd3d75e', - }, - 'vc9-crt-x86-msm-policy': { - 'url': 'https://github.com/indygreg/vc90-merge-modules/raw/9232f8f0b2135df619bf7946eaa176b4ac35ccff/policy_9_0_Microsoft_VC90_CRT_x86.msm', - 'size': 71168, - 'sha256': '3fbcf92e3801a0757f36c5e8d304e134a68d5cafd197a6df7734ae3e8825c940', - }, - 'vc9-crt-x64-msm': { - 'url': 'https://github.com/indygreg/vc90-merge-modules/raw/9232f8f0b2135df619bf7946eaa176b4ac35ccff/Microsoft_VC90_CRT_x86_x64.msm', - 'size': 662528, - 'sha256': '50d9639b5ad4844a2285269c7551bf5157ec636e32396ddcc6f7ec5bce487a7c', - }, - 'vc9-crt-x64-msm-policy': { - 'url': 'https://github.com/indygreg/vc90-merge-modules/raw/9232f8f0b2135df619bf7946eaa176b4ac35ccff/policy_9_0_Microsoft_VC90_CRT_x86_x64.msm', - 'size': 71168, - 'sha256': '0550ea1929b21239134ad3a678c944ba0f05f11087117b6cf0833e7110686486', - }, - 'virtualenv': { - 'url': 'https://files.pythonhosted.org/packages/37/db/89d6b043b22052109da35416abc3c397655e4bd3cff031446ba02b9654fa/virtualenv-16.4.3.tar.gz', - 'size': 3713208, - 'sha256': '984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39', - 'version': '16.4.3', - }, - 'wix': { - 'url': 'https://github.com/wixtoolset/wix3/releases/download/wix3111rtm/wix311-binaries.zip', - 'size': 34358269, - 'sha256': '37f0a533b0978a454efb5dc3bd3598becf9660aaf4287e55bf68ca6b527d051d', - 'version': '3.11.1', - }, }
--- a/contrib/packaging/hgpackaging/inno.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/hgpackaging/inno.py Tue Apr 05 11:09:03 2022 +0200 @@ -14,29 +14,13 @@ import jinja2 -from .py2exe import ( - build_py2exe, - stage_install, -) from .pyoxidizer import create_pyoxidizer_install_layout from .util import ( - find_legacy_vc_runtime_files, normalize_windows_version, process_install_rules, read_version_py, ) -EXTRA_PACKAGES = { - 'dulwich', - 'keyring', - 'pygments', - 'win32ctypes', -} - -EXTRA_INCLUDES = { - '_curses', - '_curses_panel', -} EXTRA_INSTALL_RULES = [ ('contrib/win32/mercurial.ini', 'defaultrc/mercurial.rc'), @@ -47,80 +31,6 @@ } -def build_with_py2exe( - source_dir: pathlib.Path, - build_dir: pathlib.Path, - python_exe: pathlib.Path, - iscc_exe: pathlib.Path, - version=None, -): - """Build the Inno installer using py2exe. - - Build files will be placed in ``build_dir``. - - py2exe's setup.py doesn't use setuptools. It doesn't have modern logic - for finding the Python 2.7 toolchain. So, we require the environment - to already be configured with an active toolchain. - """ - if not iscc_exe.exists(): - raise Exception('%s does not exist' % iscc_exe) - - vc_x64 = r'\x64' in os.environ.get('LIB', '') - arch = 'x64' if vc_x64 else 'x86' - inno_build_dir = build_dir / ('inno-py2exe-%s' % arch) - staging_dir = inno_build_dir / 'stage' - - requirements_txt = ( - source_dir / 'contrib' / 'packaging' / 'requirements-windows-py2.txt' - ) - - inno_build_dir.mkdir(parents=True, exist_ok=True) - - build_py2exe( - source_dir, - build_dir, - python_exe, - 'inno', - requirements_txt, - extra_packages=EXTRA_PACKAGES, - extra_includes=EXTRA_INCLUDES, - ) - - # Purge the staging directory for every build so packaging is - # pristine. - if staging_dir.exists(): - print('purging %s' % staging_dir) - shutil.rmtree(staging_dir) - - # Now assemble all the packaged files into the staging directory. - stage_install(source_dir, staging_dir) - - # We also install some extra files. - process_install_rules(EXTRA_INSTALL_RULES, source_dir, staging_dir) - - # hg.exe depends on VC9 runtime DLLs. Copy those into place. - for f in find_legacy_vc_runtime_files(vc_x64): - if f.name.endswith('.manifest'): - basename = 'Microsoft.VC90.CRT.manifest' - else: - basename = f.name - - dest_path = staging_dir / basename - - print('copying %s to %s' % (f, dest_path)) - shutil.copyfile(f, dest_path) - - build_installer( - source_dir, - inno_build_dir, - staging_dir, - iscc_exe, - version, - arch="x64" if vc_x64 else None, - suffix="-python2", - ) - - def build_with_pyoxidizer( source_dir: pathlib.Path, build_dir: pathlib.Path,
--- a/contrib/packaging/hgpackaging/py2exe.py Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,248 +0,0 @@ -# py2exe.py - Functionality for performing py2exe builds. -# -# Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com> -# -# This software may be used and distributed according to the terms of the -# GNU General Public License version 2 or any later version. - -# no-check-code because Python 3 native. - -import os -import pathlib -import subprocess - -from .downloads import download_entry -from .util import ( - extract_tar_to_directory, - extract_zip_to_directory, - process_install_rules, - python_exe_info, -) - - -STAGING_RULES = [ - ('contrib/bash_completion', 'contrib/'), - ('contrib/hgk', 'contrib/hgk.tcl'), - ('contrib/hgweb.fcgi', 'contrib/'), - ('contrib/hgweb.wsgi', 'contrib/'), - ('contrib/logo-droplets.svg', 'contrib/'), - ('contrib/mercurial.el', 'contrib/'), - ('contrib/mq.el', 'contrib/'), - ('contrib/tcsh_completion', 'contrib/'), - ('contrib/tcsh_completion_build.sh', 'contrib/'), - ('contrib/vim/*', 'contrib/vim/'), - ('contrib/win32/postinstall.txt', 'ReleaseNotes.txt'), - ('contrib/win32/ReadMe.html', 'ReadMe.html'), - ('contrib/xml.rnc', 'contrib/'), - ('contrib/zsh_completion', 'contrib/'), - ('dist/hg.exe', './'), - ('dist/lib/*.dll', 'lib/'), - ('dist/lib/*.pyd', 'lib/'), - ('dist/lib/library.zip', 'lib/'), - ('dist/Microsoft.VC*.CRT.manifest', './'), - ('dist/msvc*.dll', './'), - ('dist/python*.dll', './'), - ('doc/*.html', 'doc/'), - ('doc/style.css', 'doc/'), - ('mercurial/helptext/**/*.txt', 'helptext/'), - ('mercurial/defaultrc/*.rc', 'defaultrc/'), - ('mercurial/locale/**/*', 'locale/'), - ('mercurial/templates/**/*', 'templates/'), - ('COPYING', 'Copying.txt'), -] - -# List of paths to exclude from the staging area. -STAGING_EXCLUDES = [ - 'doc/hg-ssh.8.html', -] - - -def build_py2exe( - source_dir: pathlib.Path, - build_dir: pathlib.Path, - python_exe: pathlib.Path, - build_name: str, - venv_requirements_txt: pathlib.Path, - extra_packages=None, - extra_excludes=None, - extra_dll_excludes=None, - extra_packages_script=None, - extra_includes=None, -): - """Build Mercurial with py2exe. - - Build files will be placed in ``build_dir``. - - py2exe's setup.py doesn't use setuptools. It doesn't have modern logic - for finding the Python 2.7 toolchain. So, we require the environment - to already be configured with an active toolchain. - """ - if 'VCINSTALLDIR' not in os.environ: - raise Exception( - 'not running from a Visual C++ build environment; ' - 'execute the "Visual C++ <version> Command Prompt" ' - 'application shortcut or a vcsvarsall.bat file' - ) - - # Identity x86/x64 and validate the environment matches the Python - # architecture. - vc_x64 = r'\x64' in os.environ['LIB'] - - py_info = python_exe_info(python_exe) - - if vc_x64: - if py_info['arch'] != '64bit': - raise Exception( - 'architecture mismatch: Visual C++ environment ' - 'is configured for 64-bit but Python is 32-bit' - ) - else: - if py_info['arch'] != '32bit': - raise Exception( - 'architecture mismatch: Visual C++ environment ' - 'is configured for 32-bit but Python is 64-bit' - ) - - if py_info['py3']: - raise Exception('Only Python 2 is currently supported') - - build_dir.mkdir(exist_ok=True) - - gettext_pkg, gettext_entry = download_entry('gettext', build_dir) - gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0] - virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir) - py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir) - - venv_path = build_dir / ( - 'venv-%s-%s' % (build_name, 'x64' if vc_x64 else 'x86') - ) - - gettext_root = build_dir / ('gettext-win-%s' % gettext_entry['version']) - - if not gettext_root.exists(): - extract_zip_to_directory(gettext_pkg, gettext_root) - extract_zip_to_directory(gettext_dep_pkg, gettext_root) - - # This assumes Python 2. We don't need virtualenv on Python 3. - virtualenv_src_path = build_dir / ( - 'virtualenv-%s' % virtualenv_entry['version'] - ) - virtualenv_py = virtualenv_src_path / 'virtualenv.py' - - if not virtualenv_src_path.exists(): - extract_tar_to_directory(virtualenv_pkg, build_dir) - - py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version']) - - if not py2exe_source_path.exists(): - extract_zip_to_directory(py2exe_pkg, build_dir) - - if not venv_path.exists(): - print('creating virtualenv with dependencies') - subprocess.run( - [str(python_exe), str(virtualenv_py), str(venv_path)], check=True - ) - - venv_python = venv_path / 'Scripts' / 'python.exe' - venv_pip = venv_path / 'Scripts' / 'pip.exe' - - subprocess.run( - [str(venv_pip), 'install', '-r', str(venv_requirements_txt)], check=True - ) - - # Force distutils to use VC++ settings from environment, which was - # validated above. - env = dict(os.environ) - env['DISTUTILS_USE_SDK'] = '1' - env['MSSdk'] = '1' - - if extra_packages_script: - more_packages = set( - subprocess.check_output(extra_packages_script, cwd=build_dir) - .split(b'\0')[-1] - .strip() - .decode('utf-8') - .splitlines() - ) - if more_packages: - if not extra_packages: - extra_packages = more_packages - else: - extra_packages |= more_packages - - if extra_packages: - env['HG_PY2EXE_EXTRA_PACKAGES'] = ' '.join(sorted(extra_packages)) - hgext3rd_extras = sorted( - e for e in extra_packages if e.startswith('hgext3rd.') - ) - if hgext3rd_extras: - env['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'] = ' '.join(hgext3rd_extras) - if extra_includes: - env['HG_PY2EXE_EXTRA_INCLUDES'] = ' '.join(sorted(extra_includes)) - if extra_excludes: - env['HG_PY2EXE_EXTRA_EXCLUDES'] = ' '.join(sorted(extra_excludes)) - if extra_dll_excludes: - env['HG_PY2EXE_EXTRA_DLL_EXCLUDES'] = ' '.join( - sorted(extra_dll_excludes) - ) - - py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe' - if not py2exe_py_path.exists(): - print('building py2exe') - subprocess.run( - [str(venv_python), 'setup.py', 'install'], - cwd=py2exe_source_path, - env=env, - check=True, - ) - - # Register location of msgfmt and other binaries. - env['PATH'] = '%s%s%s' % ( - env['PATH'], - os.pathsep, - str(gettext_root / 'bin'), - ) - - print('building Mercurial') - subprocess.run( - [str(venv_python), 'setup.py', 'py2exe', 'build_doc', '--html'], - cwd=str(source_dir), - env=env, - check=True, - ) - - -def stage_install( - source_dir: pathlib.Path, staging_dir: pathlib.Path, lower_case=False -): - """Copy all files to be installed to a directory. - - This allows packaging to simply walk a directory tree to find source - files. - """ - if lower_case: - rules = [] - for source, dest in STAGING_RULES: - # Only lower directory names. - if '/' in dest: - parent, leaf = dest.rsplit('/', 1) - dest = '%s/%s' % (parent.lower(), leaf) - rules.append((source, dest)) - else: - rules = STAGING_RULES - - process_install_rules(rules, source_dir, staging_dir) - - # Write out a default editor.rc file to configure notepad as the - # default editor. - with (staging_dir / 'defaultrc' / 'editor.rc').open( - 'w', encoding='utf-8' - ) as fh: - fh.write('[ui]\neditor = notepad\n') - - # Purge any files we don't want to be there. - for f in STAGING_EXCLUDES: - p = staging_dir / f - if p.exists(): - print('removing %s' % p) - p.unlink()
--- a/contrib/packaging/hgpackaging/pyoxidizer.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/hgpackaging/pyoxidizer.py Tue Apr 05 11:09:03 2022 +0200 @@ -23,7 +23,6 @@ STAGING_RULES_WINDOWS = [ - ('contrib/bash_completion', 'contrib/'), ('contrib/hgk', 'contrib/hgk.tcl'), ('contrib/hgweb.fcgi', 'contrib/'), ('contrib/hgweb.wsgi', 'contrib/'), @@ -36,7 +35,6 @@ ('contrib/win32/postinstall.txt', 'ReleaseNotes.txt'), ('contrib/win32/ReadMe.html', 'ReadMe.html'), ('contrib/xml.rnc', 'contrib/'), - ('contrib/zsh_completion', 'contrib/'), ('doc/*.html', 'doc/'), ('doc/style.css', 'doc/'), ('COPYING', 'Copying.txt'),
--- a/contrib/packaging/hgpackaging/util.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/hgpackaging/util.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,23 +7,15 @@ # no-check-code because Python 3 native. -import distutils.version -import getpass import glob import os import pathlib import re import shutil import subprocess -import tarfile import zipfile -def extract_tar_to_directory(source: pathlib.Path, dest: pathlib.Path): - with tarfile.open(source, 'r') as tf: - tf.extractall(dest) - - def extract_zip_to_directory(source: pathlib.Path, dest: pathlib.Path): with zipfile.ZipFile(source, 'r') as zf: zf.extractall(dest) @@ -81,59 +73,6 @@ raise Exception("could not find vcruntime140.dll") -def find_legacy_vc_runtime_files(x64=False): - """Finds Visual C++ Runtime DLLs to include in distribution.""" - winsxs = pathlib.Path(os.environ['SYSTEMROOT']) / 'WinSxS' - - prefix = 'amd64' if x64 else 'x86' - - candidates = sorted( - p - for p in os.listdir(winsxs) - if p.lower().startswith('%s_microsoft.vc90.crt_' % prefix) - ) - - for p in candidates: - print('found candidate VC runtime: %s' % p) - - # Take the newest version. - version = candidates[-1] - - d = winsxs / version - - return [ - d / 'msvcm90.dll', - d / 'msvcp90.dll', - d / 'msvcr90.dll', - winsxs / 'Manifests' / ('%s.manifest' % version), - ] - - -def windows_10_sdk_info(): - """Resolves information about the Windows 10 SDK.""" - - base = pathlib.Path(os.environ['ProgramFiles(x86)']) / 'Windows Kits' / '10' - - if not base.is_dir(): - raise Exception('unable to find Windows 10 SDK at %s' % base) - - # Find the latest version. - bin_base = base / 'bin' - - versions = [v for v in os.listdir(bin_base) if v.startswith('10.')] - version = sorted(versions, reverse=True)[0] - - bin_version = bin_base / version - - return { - 'root': base, - 'version': version, - 'bin_root': bin_version, - 'bin_x86': bin_version / 'x86', - 'bin_x64': bin_version / 'x64', - } - - def normalize_windows_version(version): """Normalize Mercurial version string so WiX/Inno accepts it. @@ -194,93 +133,6 @@ return '.'.join('%d' % x for x in versions[0:4]) -def find_signtool(): - """Find signtool.exe from the Windows SDK.""" - sdk = windows_10_sdk_info() - - for key in ('bin_x64', 'bin_x86'): - p = sdk[key] / 'signtool.exe' - - if p.exists(): - return p - - raise Exception('could not find signtool.exe in Windows 10 SDK') - - -def sign_with_signtool( - file_path, - description, - subject_name=None, - cert_path=None, - cert_password=None, - timestamp_url=None, -): - """Digitally sign a file with signtool.exe. - - ``file_path`` is file to sign. - ``description`` is text that goes in the signature. - - The signing certificate can be specified by ``cert_path`` or - ``subject_name``. These correspond to the ``/f`` and ``/n`` arguments - to signtool.exe, respectively. - - The certificate password can be specified via ``cert_password``. If - not provided, you will be prompted for the password. - - ``timestamp_url`` is the URL of a RFC 3161 timestamp server (``/tr`` - argument to signtool.exe). - """ - if cert_path and subject_name: - raise ValueError('cannot specify both cert_path and subject_name') - - while cert_path and not cert_password: - cert_password = getpass.getpass('password for %s: ' % cert_path) - - args = [ - str(find_signtool()), - 'sign', - '/v', - '/fd', - 'sha256', - '/d', - description, - ] - - if cert_path: - args.extend(['/f', str(cert_path), '/p', cert_password]) - elif subject_name: - args.extend(['/n', subject_name]) - - if timestamp_url: - args.extend(['/tr', timestamp_url, '/td', 'sha256']) - - args.append(str(file_path)) - - print('signing %s' % file_path) - subprocess.run(args, check=True) - - -PRINT_PYTHON_INFO = ''' -import platform; print("%s:%s" % (platform.architecture()[0], platform.python_version())) -'''.strip() - - -def python_exe_info(python_exe: pathlib.Path): - """Obtain information about a Python executable.""" - - res = subprocess.check_output([str(python_exe), '-c', PRINT_PYTHON_INFO]) - - arch, version = res.decode('utf-8').split(':') - - version = distutils.version.LooseVersion(version) - - return { - 'arch': arch, - 'version': version, - 'py3': version >= distutils.version.LooseVersion('3'), - } - - def process_install_rules( rules: list, source_dir: pathlib.Path, dest_dir: pathlib.Path ):
--- a/contrib/packaging/hgpackaging/wix.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/hgpackaging/wix.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,376 +7,16 @@ # no-check-code because Python 3 native. -import collections import json import os import pathlib -import re import shutil -import subprocess import typing -import uuid -import xml.dom.minidom -from .downloads import download_entry -from .py2exe import ( - build_py2exe, - stage_install, -) from .pyoxidizer import ( build_docs_html, - create_pyoxidizer_install_layout, run_pyoxidizer, ) -from .util import ( - extract_zip_to_directory, - normalize_windows_version, - process_install_rules, - sign_with_signtool, -) - - -EXTRA_PACKAGES = { - 'dulwich', - 'distutils', - 'keyring', - 'pygments', - 'win32ctypes', -} - -EXTRA_INCLUDES = { - '_curses', - '_curses_panel', -} - -EXTRA_INSTALL_RULES = [ - ('contrib/packaging/wix/COPYING.rtf', 'COPYING.rtf'), - ('contrib/win32/mercurial.ini', 'defaultrc/mercurial.rc'), -] - -STAGING_REMOVE_FILES = [ - # We use the RTF variant. - 'copying.txt', -] - -SHORTCUTS = { - # hg.1.html' - 'hg.file.5d3e441c_28d9_5542_afd0_cdd4234f12d5': { - 'Name': 'Mercurial Command Reference', - }, - # hgignore.5.html - 'hg.file.5757d8e0_f207_5e10_a2ec_3ba0a062f431': { - 'Name': 'Mercurial Ignore Files', - }, - # hgrc.5.html - 'hg.file.92e605fd_1d1a_5dc6_9fc0_5d2998eb8f5e': { - 'Name': 'Mercurial Configuration Files', - }, -} - - -def find_version(source_dir: pathlib.Path): - version_py = source_dir / 'mercurial' / '__version__.py' - - with version_py.open('r', encoding='utf-8') as fh: - source = fh.read().strip() - - m = re.search('version = b"(.*)"', source) - return m.group(1) - - -def ensure_vc90_merge_modules(build_dir): - x86 = ( - download_entry( - 'vc9-crt-x86-msm', - build_dir, - local_name='microsoft.vcxx.crt.x86_msm.msm', - )[0], - download_entry( - 'vc9-crt-x86-msm-policy', - build_dir, - local_name='policy.x.xx.microsoft.vcxx.crt.x86_msm.msm', - )[0], - ) - - x64 = ( - download_entry( - 'vc9-crt-x64-msm', - build_dir, - local_name='microsoft.vcxx.crt.x64_msm.msm', - )[0], - download_entry( - 'vc9-crt-x64-msm-policy', - build_dir, - local_name='policy.x.xx.microsoft.vcxx.crt.x64_msm.msm', - )[0], - ) - return { - 'x86': x86, - 'x64': x64, - } - - -def run_candle(wix, cwd, wxs, source_dir, defines=None): - args = [ - str(wix / 'candle.exe'), - '-nologo', - str(wxs), - '-dSourceDir=%s' % source_dir, - ] - - if defines: - args.extend('-d%s=%s' % define for define in sorted(defines.items())) - - subprocess.run(args, cwd=str(cwd), check=True) - - -def make_files_xml(staging_dir: pathlib.Path, is_x64) -> str: - """Create XML string listing every file to be installed.""" - - # We derive GUIDs from a deterministic file path identifier. - # We shoehorn the name into something that looks like a URL because - # the UUID namespaces are supposed to work that way (even though - # the input data probably is never validated). - - doc = xml.dom.minidom.parseString( - '<?xml version="1.0" encoding="utf-8"?>' - '<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">' - '</Wix>' - ) - - # Assemble the install layout by directory. This makes it easier to - # emit XML, since each directory has separate entities. - manifest = collections.defaultdict(dict) - - for root, dirs, files in os.walk(staging_dir): - dirs.sort() - - root = pathlib.Path(root) - rel_dir = root.relative_to(staging_dir) - - for i in range(len(rel_dir.parts)): - parent = '/'.join(rel_dir.parts[0 : i + 1]) - manifest.setdefault(parent, {}) - - for f in sorted(files): - full = root / f - manifest[str(rel_dir).replace('\\', '/')][full.name] = full - - component_groups = collections.defaultdict(list) - - # Now emit a <Fragment> for each directory. - # Each directory is composed of a <DirectoryRef> pointing to its parent - # and defines child <Directory>'s and a <Component> with all the files. - for dir_name, entries in sorted(manifest.items()): - # The directory id is derived from the path. But the root directory - # is special. - if dir_name == '.': - parent_directory_id = 'INSTALLDIR' - else: - parent_directory_id = 'hg.dir.%s' % dir_name.replace( - '/', '.' - ).replace('-', '_') - - fragment = doc.createElement('Fragment') - directory_ref = doc.createElement('DirectoryRef') - directory_ref.setAttribute('Id', parent_directory_id) - - # Add <Directory> entries for immediate children directories. - for possible_child in sorted(manifest.keys()): - if ( - dir_name == '.' - and '/' not in possible_child - and possible_child != '.' - ): - child_directory_id = ('hg.dir.%s' % possible_child).replace( - '-', '_' - ) - name = possible_child - else: - if not possible_child.startswith('%s/' % dir_name): - continue - name = possible_child[len(dir_name) + 1 :] - if '/' in name: - continue - - child_directory_id = 'hg.dir.%s' % possible_child.replace( - '/', '.' - ).replace('-', '_') - - directory = doc.createElement('Directory') - directory.setAttribute('Id', child_directory_id) - directory.setAttribute('Name', name) - directory_ref.appendChild(directory) - - # Add <Component>s for files in this directory. - for rel, source_path in sorted(entries.items()): - if dir_name == '.': - full_rel = rel - else: - full_rel = '%s/%s' % (dir_name, rel) - - component_unique_id = ( - 'https://www.mercurial-scm.org/wix-installer/0/component/%s' - % full_rel - ) - component_guid = uuid.uuid5(uuid.NAMESPACE_URL, component_unique_id) - component_id = 'hg.component.%s' % str(component_guid).replace( - '-', '_' - ) - - component = doc.createElement('Component') - - component.setAttribute('Id', component_id) - component.setAttribute('Guid', str(component_guid).upper()) - component.setAttribute('Win64', 'yes' if is_x64 else 'no') - - # Assign this component to a top-level group. - if dir_name == '.': - component_groups['ROOT'].append(component_id) - elif '/' in dir_name: - component_groups[dir_name[0 : dir_name.index('/')]].append( - component_id - ) - else: - component_groups[dir_name].append(component_id) - - unique_id = ( - 'https://www.mercurial-scm.org/wix-installer/0/%s' % full_rel - ) - file_guid = uuid.uuid5(uuid.NAMESPACE_URL, unique_id) - - # IDs have length limits. So use GUID to derive them. - file_guid_normalized = str(file_guid).replace('-', '_') - file_id = 'hg.file.%s' % file_guid_normalized - - file_element = doc.createElement('File') - file_element.setAttribute('Id', file_id) - file_element.setAttribute('Source', str(source_path)) - file_element.setAttribute('KeyPath', 'yes') - file_element.setAttribute('ReadOnly', 'yes') - - component.appendChild(file_element) - directory_ref.appendChild(component) - - fragment.appendChild(directory_ref) - doc.documentElement.appendChild(fragment) - - for group, component_ids in sorted(component_groups.items()): - fragment = doc.createElement('Fragment') - component_group = doc.createElement('ComponentGroup') - component_group.setAttribute('Id', 'hg.group.%s' % group) - - for component_id in component_ids: - component_ref = doc.createElement('ComponentRef') - component_ref.setAttribute('Id', component_id) - component_group.appendChild(component_ref) - - fragment.appendChild(component_group) - doc.documentElement.appendChild(fragment) - - # Add <Shortcut> to files that have it defined. - for file_id, metadata in sorted(SHORTCUTS.items()): - els = doc.getElementsByTagName('File') - els = [el for el in els if el.getAttribute('Id') == file_id] - - if not els: - raise Exception('could not find File[Id=%s]' % file_id) - - for el in els: - shortcut = doc.createElement('Shortcut') - shortcut.setAttribute('Id', 'hg.shortcut.%s' % file_id) - shortcut.setAttribute('Directory', 'ProgramMenuDir') - shortcut.setAttribute('Icon', 'hgIcon.ico') - shortcut.setAttribute('IconIndex', '0') - shortcut.setAttribute('Advertise', 'yes') - for k, v in sorted(metadata.items()): - shortcut.setAttribute(k, v) - - el.appendChild(shortcut) - - return doc.toprettyxml() - - -def build_installer_py2exe( - source_dir: pathlib.Path, - python_exe: pathlib.Path, - msi_name='mercurial', - version=None, - extra_packages_script=None, - extra_wxs: typing.Optional[typing.Dict[str, str]] = None, - extra_features: typing.Optional[typing.List[str]] = None, - signing_info: typing.Optional[typing.Dict[str, str]] = None, -): - """Build a WiX MSI installer using py2exe. - - ``source_dir`` is the path to the Mercurial source tree to use. - ``arch`` is the target architecture. either ``x86`` or ``x64``. - ``python_exe`` is the path to the Python executable to use/bundle. - ``version`` is the Mercurial version string. If not defined, - ``mercurial/__version__.py`` will be consulted. - ``extra_packages_script`` is a command to be run to inject extra packages - into the py2exe binary. It should stage packages into the virtualenv and - print a null byte followed by a newline-separated list of packages that - should be included in the exe. - ``extra_wxs`` is a dict of {wxs_name: working_dir_for_wxs_build}. - ``extra_features`` is a list of additional named Features to include in - the build. These must match Feature names in one of the wxs scripts. - """ - arch = 'x64' if r'\x64' in os.environ.get('LIB', '') else 'x86' - - hg_build_dir = source_dir / 'build' - - requirements_txt = ( - source_dir / 'contrib' / 'packaging' / 'requirements-windows-py2.txt' - ) - - build_py2exe( - source_dir, - hg_build_dir, - python_exe, - 'wix', - requirements_txt, - extra_packages=EXTRA_PACKAGES, - extra_packages_script=extra_packages_script, - extra_includes=EXTRA_INCLUDES, - ) - - build_dir = hg_build_dir / ('wix-%s' % arch) - staging_dir = build_dir / 'stage' - - build_dir.mkdir(exist_ok=True) - - # Purge the staging directory for every build so packaging is pristine. - if staging_dir.exists(): - print('purging %s' % staging_dir) - shutil.rmtree(staging_dir) - - stage_install(source_dir, staging_dir, lower_case=True) - - # We also install some extra files. - process_install_rules(EXTRA_INSTALL_RULES, source_dir, staging_dir) - - # And remove some files we don't want. - for f in STAGING_REMOVE_FILES: - p = staging_dir / f - if p.exists(): - print('removing %s' % p) - p.unlink() - - return run_wix_packaging( - source_dir, - build_dir, - staging_dir, - arch, - version=version, - python2=True, - msi_name=msi_name, - suffix="-python2", - extra_wxs=extra_wxs, - extra_features=extra_features, - signing_info=signing_info, - ) def build_installer_pyoxidizer( @@ -454,133 +94,3 @@ return { "msi_path": dist_path, } - - -def run_wix_packaging( - source_dir: pathlib.Path, - build_dir: pathlib.Path, - staging_dir: pathlib.Path, - arch: str, - version: str, - python2: bool, - msi_name: typing.Optional[str] = "mercurial", - suffix: str = "", - extra_wxs: typing.Optional[typing.Dict[str, str]] = None, - extra_features: typing.Optional[typing.List[str]] = None, - signing_info: typing.Optional[typing.Dict[str, str]] = None, -): - """Invokes WiX to package up a built Mercurial. - - ``signing_info`` is a dict defining properties to facilitate signing the - installer. Recognized keys include ``name``, ``subject_name``, - ``cert_path``, ``cert_password``, and ``timestamp_url``. If populated, - we will sign both the hg.exe and the .msi using the signing credentials - specified. - """ - - orig_version = version or find_version(source_dir) - version = normalize_windows_version(orig_version) - print('using version string: %s' % version) - if version != orig_version: - print('(normalized from: %s)' % orig_version) - - if signing_info: - sign_with_signtool( - staging_dir / "hg.exe", - "%s %s" % (signing_info["name"], version), - subject_name=signing_info["subject_name"], - cert_path=signing_info["cert_path"], - cert_password=signing_info["cert_password"], - timestamp_url=signing_info["timestamp_url"], - ) - - wix_dir = source_dir / 'contrib' / 'packaging' / 'wix' - - wix_pkg, wix_entry = download_entry('wix', build_dir) - wix_path = build_dir / ('wix-%s' % wix_entry['version']) - - if not wix_path.exists(): - extract_zip_to_directory(wix_pkg, wix_path) - - if python2: - ensure_vc90_merge_modules(build_dir) - - source_build_rel = pathlib.Path(os.path.relpath(source_dir, build_dir)) - - defines = {'Platform': arch} - - # Derive a .wxs file with the staged files. - manifest_wxs = build_dir / 'stage.wxs' - with manifest_wxs.open('w', encoding='utf-8') as fh: - fh.write(make_files_xml(staging_dir, is_x64=arch == 'x64')) - - run_candle(wix_path, build_dir, manifest_wxs, staging_dir, defines=defines) - - for source, rel_path in sorted((extra_wxs or {}).items()): - run_candle(wix_path, build_dir, source, rel_path, defines=defines) - - source = wix_dir / 'mercurial.wxs' - defines['Version'] = version - defines['Comments'] = 'Installs Mercurial version %s' % version - - if python2: - defines["PythonVersion"] = "2" - defines['VCRedistSrcDir'] = str(build_dir) - else: - defines["PythonVersion"] = "3" - - if (staging_dir / "lib").exists(): - defines["MercurialHasLib"] = "1" - - if extra_features: - assert all(';' not in f for f in extra_features) - defines['MercurialExtraFeatures'] = ';'.join(extra_features) - - run_candle(wix_path, build_dir, source, source_build_rel, defines=defines) - - msi_path = ( - source_dir - / 'dist' - / ('%s-%s-%s%s.msi' % (msi_name, orig_version, arch, suffix)) - ) - - args = [ - str(wix_path / 'light.exe'), - '-nologo', - '-ext', - 'WixUIExtension', - '-sw1076', - '-spdb', - '-o', - str(msi_path), - ] - - for source, rel_path in sorted((extra_wxs or {}).items()): - assert source.endswith('.wxs') - source = os.path.basename(source) - args.append(str(build_dir / ('%s.wixobj' % source[:-4]))) - - args.extend( - [ - str(build_dir / 'stage.wixobj'), - str(build_dir / 'mercurial.wixobj'), - ] - ) - - subprocess.run(args, cwd=str(source_dir), check=True) - - print('%s created' % msi_path) - - if signing_info: - sign_with_signtool( - msi_path, - "%s %s" % (signing_info["name"], version), - subject_name=signing_info["subject_name"], - cert_path=signing_info["cert_path"], - cert_password=signing_info["cert_password"], - timestamp_url=signing_info["timestamp_url"], - ) - - return { - 'msi_path': msi_path, - }
--- a/contrib/packaging/mercurial.spec Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/mercurial.spec Tue Apr 05 11:09:03 2022 +0200 @@ -126,14 +126,6 @@ install -m 755 contrib/hgk $RPM_BUILD_ROOT%{_bindir}/ install -m 755 contrib/hg-ssh $RPM_BUILD_ROOT%{_bindir}/ -bash_completion_dir=$RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d -mkdir -p $bash_completion_dir -install -m 644 contrib/bash_completion $bash_completion_dir/mercurial.sh - -zsh_completion_dir=$RPM_BUILD_ROOT%{_datadir}/zsh/site-functions -mkdir -p $zsh_completion_dir -install -m 644 contrib/zsh_completion $zsh_completion_dir/_mercurial - mkdir -p $RPM_BUILD_ROOT%{emacs_lispdir} install -m 644 contrib/mercurial.el $RPM_BUILD_ROOT%{emacs_lispdir}/ install -m 644 contrib/mq.el $RPM_BUILD_ROOT%{emacs_lispdir}/ @@ -148,9 +140,12 @@ %doc CONTRIBUTORS COPYING doc/README doc/hg*.txt doc/hg*.html *.cgi contrib/*.fcgi contrib/*.wsgi %doc %attr(644,root,root) %{_mandir}/man?/hg* %doc %attr(644,root,root) contrib/*.svg +%dir %{_datadir}/bash-completion/ +%dir %{_datadir}/bash-completion/completions +%{_datadir}/bash-completion/completions/hg %dir %{_datadir}/zsh/ %dir %{_datadir}/zsh/site-functions/ -%{_datadir}/zsh/site-functions/_mercurial +%{_datadir}/zsh/site-functions/_hg %dir %{_datadir}/emacs/site-lisp/ %{_datadir}/emacs/site-lisp/mercurial.el %{_datadir}/emacs/site-lisp/mq.el @@ -158,8 +153,6 @@ %{_bindir}/chg %{_bindir}/hgk %{_bindir}/hg-ssh -%dir %{_sysconfdir}/bash_completion.d/ -%config(noreplace) %{_sysconfdir}/bash_completion.d/mercurial.sh %dir %{_sysconfdir}/mercurial %dir %{_sysconfdir}/mercurial/hgrc.d %if "%{?withpython}"
--- a/contrib/packaging/requirements-windows-py2.txt Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile --generate-hashes --output-file=contrib/packaging/requirements-windows-py2.txt contrib/packaging/requirements-windows.txt.in -# -certifi==2021.5.30 \ - --hash=sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee \ - --hash=sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8 \ - # via dulwich -configparser==4.0.2 \ - --hash=sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c \ - --hash=sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df \ - # via entrypoints -docutils==0.16 \ - --hash=sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af \ - --hash=sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc \ - # via -r contrib/packaging/requirements-windows.txt.in -dulwich==0.19.16 ; python_version <= "2.7" \ - --hash=sha256:10699277c6268d0c16febe141a5b1c1a6e9744f3144c2d2de1706f4b1adafe63 \ - --hash=sha256:267160904e9a1cb6c248c5efc53597a35d038ecc6f60bdc4546b3053bed11982 \ - --hash=sha256:4e3aba5e4844e7c700721c1fc696987ea820ee3528a03604dc4e74eff4196826 \ - --hash=sha256:60bb2c2c92f5025c1b53a556304008f0f624c98ae36f22d870e056b2d4236c11 \ - --hash=sha256:dddae02d372fc3b5cfb0046d0f62246ef281fa0c088df7601ab5916607add94b \ - --hash=sha256:f00d132082b8fcc2eb0d722abc773d4aeb5558c1475d7edd1f0f571146c29db9 \ - --hash=sha256:f74561c448bfb6f04c07de731c1181ae4280017f759b0bb04fa5770aa84ca850 \ - # via -r contrib/packaging/requirements-windows.txt.in -entrypoints==0.3 \ - --hash=sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 \ - --hash=sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451 \ - # via keyring -keyring==18.0.1 \ - --hash=sha256:67d6cc0132bd77922725fae9f18366bb314fd8f95ff4d323a4df41890a96a838 \ - --hash=sha256:7b29ebfcf8678c4da531b2478a912eea01e80007e5ddca9ee0c7038cb3489ec6 \ - # via -r contrib/packaging/requirements-windows.txt.in -pygments==2.5.2 \ - --hash=sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b \ - --hash=sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe \ - # via -r contrib/packaging/requirements-windows.txt.in -pywin32-ctypes==0.2.0 \ - --hash=sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942 \ - --hash=sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98 \ - # via -r contrib/packaging/requirements-windows.txt.in, keyring -urllib3==1.25.11 \ - --hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \ - --hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e \ - # via dulwich -windows-curses==2.1.0 \ - --hash=sha256:261fde5680d1ce4ce116908996b9a3cfb0ffb03ea68d42240f62b56a9fa6af2c \ - --hash=sha256:66034dc9a705d87308cc9ea90836f4ee60008a1d5e2c1d34ace627f60268158b \ - --hash=sha256:669caad3ae16faf2d201d7ab3b8af418a2fd074d8a39d60ca26f3acb34b6afe5 \ - --hash=sha256:73bd3eebccfda55330783f165151de115bfa238d1332f0b2e224b550d6187840 \ - --hash=sha256:89a6d973f88cfe49b41ea80164dcbec209d296e0cec34a02002578b0bf464a64 \ - --hash=sha256:8ba7c000d7ffa5452bbd0966b96e69261e4f117ebe510aeb8771a9650197b7f0 \ - --hash=sha256:97084c6b37b1534f6a28a514d521dfae402f77dcbad42b14ee32e8d5bdc13648 \ - --hash=sha256:9e474a181f96d60429a4766145628264e60b72e7715876f9135aeb2e842f9433 \ - --hash=sha256:cfe64c30807c146ef8d094412f90f2a2c81ad6aefff3ebfe8e37aabe2f801303 \ - --hash=sha256:ff8c67f74b88944d99fa9d22971c05c335bc74f149120f0a69340c2c3a595497 \ - # via -r contrib/packaging/requirements-windows.txt.in
--- a/contrib/packaging/requirements-windows.txt.in Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/packaging/requirements-windows.txt.in Tue Apr 05 11:09:03 2022 +0200 @@ -1,13 +1,11 @@ docutils -# Pinned to an old version because 0.20 drops Python 3 compatibility. -dulwich < 0.20 ; python_version <= '2.7' -dulwich ; python_version >= '3' +dulwich # Needed by the release note tooling fuzzywuzzy keyring -pygit2 ; python_version >= '3' +pygit2 pygments # Needed by the phabricator tests
--- a/contrib/perf-utils/perf-revlog-write-plot.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/perf-utils/perf-revlog-write-plot.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,7 +9,6 @@ # various plot related to write performance in a revlog # # usage: perf-revlog-write-plot.py details.json -from __future__ import absolute_import, print_function import json import re
--- a/contrib/perf-utils/search-discovery-case Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/perf-utils/search-discovery-case Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This use a subsetmaker extension (next to this script) to generate a steam of # random discovery instance. When interesting case are discovered, information # about them are print on the stdout. -from __future__ import print_function import json import os
--- a/contrib/perf.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/perf.py Tue Apr 05 11:09:03 2022 +0200 @@ -54,7 +54,6 @@ # - make perf command for recent feature work correctly with early # Mercurial -from __future__ import absolute_import import contextlib import functools import gc @@ -370,7 +369,7 @@ return len -class noop(object): +class noop: """dummy context manager""" def __enter__(self): @@ -414,7 +413,7 @@ # available since 2.2 (or ae5f92e154d3) from mercurial import node - class defaultformatter(object): + class defaultformatter: """Minimized composition of baseformatter and plainformatter""" def __init__(self, ui, topic, opts): @@ -653,7 +652,7 @@ origvalue = getattr(obj, _sysstr(name)) - class attrutil(object): + class attrutil: def set(self, newvalue): setattr(obj, _sysstr(name), newvalue) @@ -2943,7 +2942,7 @@ fm.end() -class _faketr(object): +class _faketr: def add(s, x, y, z=None): return None
--- a/contrib/phab-clean.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/phab-clean.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # A small script to automatically reject idle Diffs # # you need to set the PHABBOT_USER and PHABBOT_TOKEN environment variable for authentication -from __future__ import absolute_import, print_function import datetime import os
--- a/contrib/python-hook-examples.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/python-hook-examples.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ ''' Examples of useful python hooks for Mercurial. ''' -from __future__ import absolute_import from mercurial import ( patch, util,
--- a/contrib/python-zstandard/make_cffi.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/python-zstandard/make_cffi.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # This software may be modified and distributed under the terms # of the BSD license. See the LICENSE file for details. -from __future__ import absolute_import import cffi import distutils.ccompiler
--- a/contrib/python-zstandard/setup.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/python-zstandard/setup.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be modified and distributed under the terms # of the BSD license. See the LICENSE file for details. -from __future__ import print_function from distutils.version import LooseVersion import os
--- a/contrib/python-zstandard/tests/test_module_attributes.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/python-zstandard/tests/test_module_attributes.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import unittest import zstandard as zstd
--- a/contrib/python-zstandard/zstandard/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/python-zstandard/zstandard/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ """Python interface to the Zstandard (zstd) compression library.""" -from __future__ import absolute_import, unicode_literals # This module serves 2 roles: #
--- a/contrib/python-zstandard/zstandard/cffi.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/python-zstandard/zstandard/cffi.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ """Python interface to the Zstandard (zstd) compression library.""" -from __future__ import absolute_import, unicode_literals # This should match what the C extension exports. __all__ = [
--- a/contrib/python3-ratchet.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/python3-ratchet.py Tue Apr 05 11:09:03 2022 +0200 @@ -15,8 +15,6 @@ $ python3 ../contrib/python3-ratchet.py \ > --working-tests=../contrib/python3-whitelist """ -from __future__ import print_function -from __future__ import absolute_import import argparse import json
--- a/contrib/revsetbenchmarks.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/revsetbenchmarks.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # # call with --help for details -from __future__ import absolute_import, print_function import math import optparse # cannot use argparse, python 2.7 only import os
--- a/contrib/showstack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/showstack.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ r"""dump stack trace when receiving SIGQUIT (Ctrl-\) or SIGINFO (Ctrl-T on BSDs) """ -from __future__ import absolute_import, print_function import signal import sys import traceback
--- a/contrib/simplemerge Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/simplemerge Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from __future__ import absolute_import import getopt import sys
--- a/contrib/synthrepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/synthrepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -36,7 +36,6 @@ - Symlinks and binary files are ignored ''' -from __future__ import absolute_import import bisect import collections import itertools @@ -213,7 +212,7 @@ for filename, mar, lineadd, lineremove, isbin in parsegitdiff(diff): if isbin: continue - added = sum(pycompat.itervalues(lineadd), 0) + added = sum(lineadd.values(), 0) if mar == 'm': if added and lineremove: lineschanged[
--- a/contrib/testparseutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/testparseutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import abc import re @@ -80,7 +79,7 @@ #################### -class embeddedmatcher(object): # pytype: disable=ignored-metaclass +class embeddedmatcher: # pytype: disable=ignored-metaclass """Base class to detect embedded code fragments in *.t test script""" __metaclass__ = abc.ABCMeta @@ -157,7 +156,7 @@ :ends: line number (1-origin), at which embedded code ends (exclusive) :code: extracted embedded code, which is single-stringified - >>> class ambigmatcher(object): + >>> class ambigmatcher: ... # mock matcher class to examine implementation of ... # "ambiguous matching" corner case ... def __init__(self, desc, matchfunc):
--- a/contrib/undumprevlog Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/undumprevlog Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # $ hg init # $ undumprevlog < repo.dump -from __future__ import absolute_import, print_function import sys from mercurial.node import bin
--- a/contrib/win32/hgwebdir_wsgi.py Tue Apr 05 10:55:28 2022 +0200 +++ b/contrib/win32/hgwebdir_wsgi.py Tue Apr 05 11:09:03 2022 +0200 @@ -78,7 +78,6 @@ # - Restart the web server and see if things are running. # -from __future__ import absolute_import # Configuration file location hgweb_config = r'c:\your\directory\wsgi.config'
--- a/doc/check-seclevel.py Tue Apr 05 10:55:28 2022 +0200 +++ b/doc/check-seclevel.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # # checkseclevel - checking section title levels in each online help document -from __future__ import absolute_import import optparse import os
--- a/doc/docchecker Tue Apr 05 10:55:28 2022 +0200 +++ b/doc/docchecker Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import os import re
--- a/doc/gendoc.py Tue Apr 05 10:55:28 2022 +0200 +++ b/doc/gendoc.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ where DOC is the name of a document """ -from __future__ import absolute_import import os import sys
--- a/doc/hgmanpage.py Tue Apr 05 10:55:28 2022 +0200 +++ b/doc/hgmanpage.py Tue Apr 05 11:09:03 2022 +0200 @@ -41,7 +41,6 @@ by the command whatis or apropos. """ -from __future__ import absolute_import __docformat__ = 'reStructuredText' @@ -113,7 +112,7 @@ self.output = visitor.astext() -class Table(object): +class Table: def __init__(self): self._rows = [] self._options = ['center'] @@ -313,7 +312,7 @@ pass def list_start(self, node): - class enum_char(object): + class enum_char: enum_style = { 'bullet': '\\(bu', 'emdash': '\\(em',
--- a/doc/runrst Tue Apr 05 10:55:28 2022 +0200 +++ b/doc/runrst Tue Apr 05 11:09:03 2022 +0200 @@ -12,7 +12,6 @@ where WRITER is the name of a Docutils writer such as 'html' or 'manpage' """ -from __future__ import absolute_import import sys
--- a/hg Tue Apr 05 10:55:28 2022 +0200 +++ b/hg Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import sys @@ -44,10 +43,9 @@ with tracing.log('hg script'): # enable importing on demand to reduce startup time try: - if sys.version_info[0] < 3 or sys.version_info >= (3, 6): - import hgdemandimport + import hgdemandimport - hgdemandimport.enable() + hgdemandimport.enable() except ImportError: sys.stderr.write( "abort: couldn't find mercurial libraries in [%s]\n"
--- a/hgdemandimport/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgdemandimport/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,15 +11,11 @@ # demand loading is per-package. Keeping demandimport in the mercurial package # would disable demand loading for any modules in mercurial. -from __future__ import absolute_import import os import sys -if sys.version_info[0] >= 3: - from . import demandimportpy3 as demandimport -else: - from . import demandimportpy2 as demandimport +from . import demandimportpy3 as demandimport # Full module names which can't be lazy imported. # Extensions can add to this set.
--- a/hgdemandimport/demandimportpy2.py Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,326 +0,0 @@ -# demandimport.py - global demand-loading of modules for Mercurial -# -# Copyright 2006, 2007 Olivia Mackall <olivia@selenic.com> -# -# This software may be used and distributed according to the terms of the -# GNU General Public License version 2 or any later version. - -''' -demandimport - automatic demandloading of modules - -To enable this module, do: - - import demandimport; demandimport.enable() - -Imports of the following forms will be demand-loaded: - - import a, b.c - import a.b as c - from a import b,c # a will be loaded immediately - -These imports will not be delayed: - - from a import * - b = __import__(a) -''' - -from __future__ import absolute_import - -import __builtin__ as builtins -import contextlib -import sys - -from . import tracing - -contextmanager = contextlib.contextmanager - -_origimport = __import__ - -nothing = object() - - -def _hgextimport(importfunc, name, globals, *args, **kwargs): - try: - return importfunc(name, globals, *args, **kwargs) - except ImportError: - if not globals: - raise - # extensions are loaded with "hgext_" prefix - hgextname = 'hgext_%s' % name - nameroot = hgextname.split('.', 1)[0] - contextroot = globals.get('__name__', '').split('.', 1)[0] - if nameroot != contextroot: - raise - # retry to import with "hgext_" prefix - return importfunc(hgextname, globals, *args, **kwargs) - - -class _demandmod(object): - """module demand-loader and proxy - - Specify 1 as 'level' argument at construction, to import module - relatively. - """ - - def __init__(self, name, globals, locals, level): - if '.' in name: - head, rest = name.split('.', 1) - after = [rest] - else: - head = name - after = [] - object.__setattr__( - self, "_data", (head, globals, locals, after, level, set()) - ) - object.__setattr__(self, "_module", None) - - def _extend(self, name): - """add to the list of submodules to load""" - self._data[3].append(name) - - def _addref(self, name): - """Record that the named module ``name`` imports this module. - - References to this proxy class having the name of this module will be - replaced at module load time. We assume the symbol inside the importing - module is identical to the "head" name of this module. We don't - actually know if "as X" syntax is being used to change the symbol name - because this information isn't exposed to __import__. - """ - self._data[5].add(name) - - def _load(self): - if not self._module: - with tracing.log('demandimport %s', self._data[0]): - head, globals, locals, after, level, modrefs = self._data - mod = _hgextimport( - _origimport, head, globals, locals, None, level - ) - if mod is self: - # In this case, _hgextimport() above should imply - # _demandimport(). Otherwise, _hgextimport() never - # returns _demandmod. This isn't intentional behavior, - # in fact. (see also issue5304 for detail) - # - # If self._module is already bound at this point, self - # should be already _load()-ed while _hgextimport(). - # Otherwise, there is no way to import actual module - # as expected, because (re-)invoking _hgextimport() - # should cause same result. - # This is reason why _load() returns without any more - # setup but assumes self to be already bound. - mod = self._module - assert mod and mod is not self, "%s, %s" % (self, mod) - return - - # load submodules - def subload(mod, p): - h, t = p, None - if '.' in p: - h, t = p.split('.', 1) - if getattr(mod, h, nothing) is nothing: - setattr( - mod, - h, - _demandmod(p, mod.__dict__, mod.__dict__, level=1), - ) - elif t: - subload(getattr(mod, h), t) - - for x in after: - subload(mod, x) - - # Replace references to this proxy instance with the - # actual module. - if locals: - if locals.get(head) is self: - locals[head] = mod - elif locals.get(head + 'mod') is self: - locals[head + 'mod'] = mod - - for modname in modrefs: - modref = sys.modules.get(modname, None) - if modref and getattr(modref, head, None) is self: - setattr(modref, head, mod) - - object.__setattr__(self, "_module", mod) - - def __repr__(self): - if self._module: - return "<proxied module '%s'>" % self._data[0] - return "<unloaded module '%s'>" % self._data[0] - - def __call__(self, *args, **kwargs): - raise TypeError("%s object is not callable" % repr(self)) - - def __getattr__(self, attr): - self._load() - return getattr(self._module, attr) - - def __setattr__(self, attr, val): - self._load() - setattr(self._module, attr, val) - - @property - def __dict__(self): - self._load() - return self._module.__dict__ - - @property - def __doc__(self): - self._load() - return self._module.__doc__ - - -_pypy = '__pypy__' in sys.builtin_module_names - - -def _demandimport(name, globals=None, locals=None, fromlist=None, level=-1): - if locals is None or name in ignores or fromlist == ('*',): - # these cases we can't really delay - return _hgextimport(_origimport, name, globals, locals, fromlist, level) - elif not fromlist: - # import a [as b] - if '.' in name: # a.b - base, rest = name.split('.', 1) - # email.__init__ loading email.mime - if globals and globals.get('__name__', None) == base: - return _origimport(name, globals, locals, fromlist, level) - # if a is already demand-loaded, add b to its submodule list - if base in locals: - if isinstance(locals[base], _demandmod): - locals[base]._extend(rest) - return locals[base] - return _demandmod(name, globals, locals, level) - else: - # There is a fromlist. - # from a import b,c,d - # from . import b,c,d - # from .a import b,c,d - - # level == -1: relative and absolute attempted (Python 2 only). - # level >= 0: absolute only (Python 2 w/ absolute_import and Python 3). - # The modern Mercurial convention is to use absolute_import everywhere, - # so modern Mercurial code will have level >= 0. - - # The name of the module the import statement is located in. - globalname = globals.get('__name__') - - def processfromitem(mod, attr): - """Process an imported symbol in the import statement. - - If the symbol doesn't exist in the parent module, and if the - parent module is a package, it must be a module. We set missing - modules up as _demandmod instances. - """ - symbol = getattr(mod, attr, nothing) - nonpkg = getattr(mod, '__path__', nothing) is nothing - if symbol is nothing: - if nonpkg: - # do not try relative import, which would raise ValueError, - # and leave unknown attribute as the default __import__() - # would do. the missing attribute will be detected later - # while processing the import statement. - return - mn = '%s.%s' % (mod.__name__, attr) - if mn in ignores: - importfunc = _origimport - else: - importfunc = _demandmod - symbol = importfunc(attr, mod.__dict__, locals, level=1) - setattr(mod, attr, symbol) - - # Record the importing module references this symbol so we can - # replace the symbol with the actual module instance at load - # time. - if globalname and isinstance(symbol, _demandmod): - symbol._addref(globalname) - - def chainmodules(rootmod, modname): - # recurse down the module chain, and return the leaf module - mod = rootmod - for comp in modname.split('.')[1:]: - obj = getattr(mod, comp, nothing) - if obj is nothing: - obj = _demandmod(comp, mod.__dict__, mod.__dict__, level=1) - setattr(mod, comp, obj) - elif mod.__name__ + '.' + comp in sys.modules: - # prefer loaded module over attribute (issue5617) - obj = sys.modules[mod.__name__ + '.' + comp] - mod = obj - return mod - - if level >= 0: - if name: - # "from a import b" or "from .a import b" style - rootmod = _hgextimport( - _origimport, name, globals, locals, level=level - ) - mod = chainmodules(rootmod, name) - elif _pypy: - # PyPy's __import__ throws an exception if invoked - # with an empty name and no fromlist. Recreate the - # desired behaviour by hand. - mn = globalname - mod = sys.modules[mn] - if getattr(mod, '__path__', nothing) is nothing: - mn = mn.rsplit('.', 1)[0] - mod = sys.modules[mn] - if level > 1: - mn = mn.rsplit('.', level - 1)[0] - mod = sys.modules[mn] - else: - mod = _hgextimport( - _origimport, name, globals, locals, level=level - ) - - for x in fromlist: - processfromitem(mod, x) - - return mod - - # But, we still need to support lazy loading of standard library and 3rd - # party modules. So handle level == -1. - mod = _hgextimport(_origimport, name, globals, locals) - mod = chainmodules(mod, name) - - for x in fromlist: - processfromitem(mod, x) - - return mod - - -ignores = set() - - -def init(ignoreset): - global ignores - ignores = ignoreset - - -def isenabled(): - return builtins.__import__ == _demandimport - - -def enable(): - """enable global demand-loading of modules""" - builtins.__import__ = _demandimport - - -def disable(): - """disable global demand-loading of modules""" - builtins.__import__ = _origimport - - -@contextmanager -def deactivated(): - """context manager for disabling demandimport in 'with' blocks""" - demandenabled = isenabled() - if demandenabled: - disable() - - try: - yield - finally: - if demandenabled: - enable()
--- a/hgdemandimport/demandimportpy3.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgdemandimport/demandimportpy3.py Tue Apr 05 11:09:03 2022 +0200 @@ -24,7 +24,6 @@ """ # This line is unnecessary, but it satisfies test-check-py3-compat.t. -from __future__ import absolute_import import contextlib import importlib.util @@ -34,12 +33,6 @@ _deactivated = False -# Python 3.5's LazyLoader doesn't work for some reason. -# https://bugs.python.org/issue26186 is a known issue with extension -# importing. But it appears to not have a meaningful effect with -# Mercurial. -_supported = sys.version_info[0:2] >= (3, 6) - class _lazyloaderex(importlib.util.LazyLoader): """This is a LazyLoader except it also follows the _deactivated global and @@ -55,7 +48,7 @@ super().exec_module(module) -class LazyFinder(object): +class LazyFinder: """A wrapper around a ``MetaPathFinder`` that makes loaders lazy. ``sys.meta_path`` finders have their ``find_spec()`` called to locate a @@ -145,9 +138,6 @@ def enable(): - if not _supported: - return - new_finders = [] for finder in sys.meta_path: new_finders.append(
--- a/hgdemandimport/tracing.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgdemandimport/tracing.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import os
--- a/hgext/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import pkgutil __path__ = pkgutil.extend_path(__path__, __name__)
--- a/hgext/absorb.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/absorb.py Tue Apr 05 11:09:03 2022 +0200 @@ -31,7 +31,6 @@ # * Converge getdraftstack() with other code in core # * move many attributes on fixupstate to be private -from __future__ import absolute_import import collections @@ -84,7 +83,7 @@ defaultdict = collections.defaultdict -class nullui(object): +class nullui: """blank ui object doing nothing""" debugflag = False @@ -98,7 +97,7 @@ return nullfunc -class emptyfilecontext(object): +class emptyfilecontext: """minimal filecontext representing an empty file""" def __init__(self, repo): @@ -278,7 +277,7 @@ ) -class filefixupstate(object): +class filefixupstate: """state needed to apply fixups to a single file internally, it keeps file contents of several revisions and a linelog. @@ -656,7 +655,7 @@ ) -class fixupstate(object): +class fixupstate: """state needed to run absorb internally, it keeps paths and filefixupstates. @@ -734,7 +733,7 @@ def apply(self): """apply fixups to individual filefixupstates""" - for path, state in pycompat.iteritems(self.fixupmap): + for path, state in self.fixupmap.items(): if self.ui.debugflag: self.ui.write(_(b'applying fixups to %s\n') % path) state.apply() @@ -742,10 +741,7 @@ @property def chunkstats(self): """-> {path: chunkstats}. collect chunkstats from filefixupstates""" - return { - path: state.chunkstats - for path, state in pycompat.iteritems(self.fixupmap) - } + return {path: state.chunkstats for path, state in self.fixupmap.items()} def commit(self): """commit changes. update self.finalnode, self.replacemap""" @@ -763,7 +759,7 @@ chunkstats = self.chunkstats if ui.verbose: # chunkstats for each file - for path, stat in pycompat.iteritems(chunkstats): + for path, stat in chunkstats.items(): if stat[0]: ui.write( _(b'%s: %d of %d chunk(s) applied\n') @@ -846,7 +842,7 @@ repo = self.repo needupdate = [ (name, self.replacemap[hsh]) - for name, hsh in pycompat.iteritems(repo._bookmarks) + for name, hsh in repo._bookmarks.items() if hsh in self.replacemap ] changes = [] @@ -909,7 +905,7 @@ # ctx changes more files (not a subset of memworkingcopy) if not set(ctx.files()).issubset(set(memworkingcopy)): return False - for path, content in pycompat.iteritems(memworkingcopy): + for path, content in memworkingcopy.items(): if path not in pctx or path not in ctx: return False fctx = ctx[path] @@ -952,7 +948,7 @@ def _cleanupoldcommits(self): replacements = { k: ([v] if v is not None else []) - for k, v in pycompat.iteritems(self.replacemap) + for k, v in self.replacemap.items() } if replacements: scmutil.cleanupnodes( @@ -1002,7 +998,7 @@ if not path or not info: continue patchmap[path].append(info) - for path, patches in pycompat.iteritems(patchmap): + for path, patches in patchmap.items(): if path not in ctx or not patches: continue patches.sort(reverse=True)
--- a/hgext/acl.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/acl.py Tue Apr 05 11:09:03 2022 +0200 @@ -213,7 +213,6 @@ ''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/amend.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/amend.py Tue Apr 05 11:09:03 2022 +0200 @@ -10,7 +10,6 @@ ``commit --amend`` but does not prompt an editor. """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/automv.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/automv.py Tue Apr 05 11:09:03 2022 +0200 @@ -24,7 +24,6 @@ # # See http://markmail.org/thread/5pxnljesvufvom57 for context. -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/beautifygraph.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/beautifygraph.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ A terminal with UTF-8 support and monospace narrow text are required. ''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/blackbox.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/blackbox.py Tue Apr 05 11:09:03 2022 +0200 @@ -42,7 +42,6 @@ """ -from __future__ import absolute_import import re @@ -106,7 +105,7 @@ _lastlogger = loggingutil.proxylogger() -class blackboxlogger(object): +class blackboxlogger: def __init__(self, ui, repo): self._repo = repo self._trackedevents = set(ui.configlist(b'blackbox', b'track'))
--- a/hgext/bookflow.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/bookflow.py Tue Apr 05 11:09:03 2022 +0200 @@ -13,7 +13,6 @@ :hg up|co NAME: switch to bookmark :hg push -B .: push active bookmark """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/bugzilla.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/bugzilla.py Tue Apr 05 11:09:03 2022 +0200 @@ -291,7 +291,6 @@ Changeset commit comment. Bug 1234. ''' -from __future__ import absolute_import import json import re @@ -435,7 +434,7 @@ ) -class bzaccess(object): +class bzaccess: '''Base class for access to Bugzilla.''' def __init__(self, ui): @@ -691,7 +690,7 @@ # Bugzilla via XMLRPC interface. -class cookietransportrequest(object): +class cookietransportrequest: """A Transport request method that retains cookies over its lifetime. The regular xmlrpclib transports ignore cookies. Which causes @@ -1096,7 +1095,7 @@ pass -class bugzilla(object): +class bugzilla: # supported versions of bugzilla. different versions have # different schemas. _versions = {
--- a/hgext/censor.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/censor.py Tue Apr 05 11:09:03 2022 +0200 @@ -28,7 +28,6 @@ ignore censored data and merely report that it was encountered. """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial.node import short
--- a/hgext/children.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/children.py Tue Apr 05 11:09:03 2022 +0200 @@ -14,7 +14,6 @@ "children(REV)"` instead. ''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/churn.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/churn.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ '''command to display statistics about repository history''' -from __future__ import absolute_import, division import datetime import os
--- a/hgext/clonebundles.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/clonebundles.py Tue Apr 05 11:09:03 2022 +0200 @@ -202,7 +202,6 @@ Mercurial server when the bundle hosting service fails. """ -from __future__ import absolute_import from mercurial import ( bundlecaches,
--- a/hgext/closehead.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/closehead.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ '''close arbitrary heads without checking them out first''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/commitextras.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/commitextras.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ '''adds a new flag extras to commit (ADVANCED)''' -from __future__ import absolute_import import re
--- a/hgext/convert/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ '''import revisions from foreign VCS repositories into Mercurial''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import registrar
--- a/hgext/convert/bzr.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/bzr.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # This module is for handling Breezy imports or `brz`, but it's also compatible # with Bazaar or `bzr`, that was formerly known as Bazaar-NG; # it cannot access `bar` repositories, but they were never used very much. -from __future__ import absolute_import import os @@ -16,7 +15,6 @@ from mercurial import ( demandimport, error, - pycompat, util, ) from . import common @@ -210,7 +208,7 @@ if not branch.supports_tags(): return {} tagdict = branch.tags.get_tag_dict() - for name, rev in pycompat.iteritems(tagdict): + for name, rev in tagdict.items(): bytetags[self.recode(name)] = rev return bytetags
--- a/hgext/convert/common.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/common.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,12 +4,12 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import base64 import datetime import errno import os +import pickle import re import shlex import subprocess @@ -25,7 +25,6 @@ ) from mercurial.utils import procutil -pickle = util.pickle propertycache = util.propertycache @@ -35,7 +34,7 @@ return d.encode('latin1') -class _shlexpy3proxy(object): +class _shlexpy3proxy: def __init__(self, l): self._l = l @@ -128,7 +127,7 @@ SKIPREV = b'SKIP' -class commit(object): +class commit: def __init__( self, author, @@ -158,7 +157,7 @@ self.ctx = ctx # for hg to hg conversions -class converter_source(object): +class converter_source: """Conversion source interface""" def __init__(self, ui, repotype, path=None, revs=None): @@ -247,7 +246,7 @@ if not encoding: encoding = self.encoding or b'utf-8' - if isinstance(s, pycompat.unicode): + if isinstance(s, str): return s.encode("utf-8") try: return s.decode(pycompat.sysstr(encoding)).encode("utf-8") @@ -308,7 +307,7 @@ return True -class converter_sink(object): +class converter_sink: """Conversion sink (target) interface""" def __init__(self, ui, repotype, path): @@ -404,7 +403,7 @@ raise NotImplementedError -class commandline(object): +class commandline: def __init__(self, ui, command): self.ui = ui self.command = command @@ -418,7 +417,7 @@ def _cmdline(self, cmd, *args, **kwargs): kwargs = pycompat.byteskwargs(kwargs) cmdline = [self.command, cmd] + list(args) - for k, v in pycompat.iteritems(kwargs): + for k, v in kwargs.items(): if len(k) == 1: cmdline.append(b'-' + k) else: @@ -553,7 +552,7 @@ if err.errno != errno.ENOENT: raise return - for i, line in enumerate(util.iterfile(fp)): + for i, line in enumerate(fp): line = line.splitlines()[0].rstrip() if not line: # Ignore blank lines
--- a/hgext/convert/convcmd.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/convcmd.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import os @@ -87,7 +86,7 @@ def recode(s): - if isinstance(s, pycompat.unicode): + if isinstance(s, str): return s.encode(pycompat.sysstr(orig_encoding), 'replace') else: return s.decode('utf-8').encode( @@ -177,7 +176,7 @@ raise error.Abort(_(b'%s: unknown repository type') % path) -class progresssource(object): +class progresssource: def __init__(self, ui, source, filecount): self.ui = ui self.source = source @@ -199,7 +198,7 @@ self.progress.complete() -class converter(object): +class converter: def __init__(self, ui, source, dest, revmapfile, opts): self.source = source @@ -243,7 +242,7 @@ m = {} try: fp = open(path, b'rb') - for i, line in enumerate(util.iterfile(fp)): + for i, line in enumerate(fp): line = line.splitlines()[0].rstrip() if not line: # Ignore blank lines @@ -585,9 +584,7 @@ # write another hash correspondence to override the # previous one so we don't end up with extra tag heads tagsparents = [ - e - for e in pycompat.iteritems(self.map) - if e[1] == tagsparent + e for e in self.map.items() if e[1] == tagsparent ] if tagsparents: self.map[tagsparents[0][0]] = nrev
--- a/hgext/convert/cvs.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/cvs.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -19,7 +18,6 @@ from mercurial import ( encoding, error, - pycompat, util, ) from mercurial.utils import ( @@ -317,7 +315,7 @@ if full: raise error.Abort(_(b"convert from cvs does not support --full")) self._parse() - return sorted(pycompat.iteritems(self.files[rev])), {}, set() + return sorted(self.files[rev].items()), {}, set() def getcommit(self, rev): self._parse()
--- a/hgext/convert/cvsps.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/cvsps.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,10 +4,10 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import functools import os +import pickle import re from mercurial.i18n import _ @@ -25,10 +25,8 @@ stringutil, ) -pickle = util.pickle - -class logentry(object): +class logentry: """Class logentry has the following attributes: .author - author name as CVS knows it .branch - name of branch this revision is on @@ -468,7 +466,7 @@ # find the branches starting from this revision branchpoints = set() - for branch, revision in pycompat.iteritems(branchmap): + for branch, revision in branchmap.items(): revparts = tuple([int(i) for i in revision.split(b'.')]) if len(revparts) < 2: # bad tags continue @@ -579,7 +577,7 @@ return log -class changeset(object): +class changeset: """Class changeset has the following attributes: .id - integer identifying this changeset (list index) .author - author name as CVS knows it
--- a/hgext/convert/darcs.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/darcs.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -114,7 +113,7 @@ shutil.rmtree(self.tmppath, ignore_errors=True) def recode(self, s, encoding=None): - if isinstance(s, pycompat.unicode): + if isinstance(s, str): # XMLParser returns unicode objects for anything it can't # encode into ASCII. We convert them back to str to get # recode's normal conversion behavior.
--- a/hgext/convert/filemap.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/filemap.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import posixpath @@ -42,7 +41,7 @@ return posixpath.normpath(path) -class filemapper(object): +class filemapper: """Map and filter filenames when importing. A name can be mapped to itself, a new name, or None (omit from new repository).""" @@ -126,7 +125,7 @@ repo belong to the source repo and what parts don't.""" if self.targetprefixes is None: self.targetprefixes = set() - for before, after in pycompat.iteritems(self.rename): + for before, after in self.rename.items(): self.targetprefixes.add(after) # If "." is a target, then all target files are considered from the
--- a/hgext/convert/git.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/git.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os @@ -20,7 +19,7 @@ from . import common -class submodule(object): +class submodule: def __init__(self, path, node, url): self.path = path self.node = node
--- a/hgext/convert/gnuarch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/gnuarch.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import shutil @@ -28,7 +27,7 @@ class gnuarch_source(common.converter_source, common.commandline): - class gnuarch_rev(object): + class gnuarch_rev: def __init__(self, rev): self.rev = rev self.summary = b''
--- a/hgext/convert/hg.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/hg.py Tue Apr 05 11:09:03 2022 +0200 @@ -16,7 +16,6 @@ # identifier to be stored in the converted revision. This will cause # the converted revision to have a different identity than the # source. -from __future__ import absolute_import import os import re @@ -40,7 +39,6 @@ merge as mergemod, mergestate, phases, - pycompat, util, ) from mercurial.utils import dateutil @@ -139,7 +137,7 @@ if missings: self.after() - for pbranch, heads in sorted(pycompat.iteritems(missings)): + for pbranch, heads in sorted(missings.items()): pbranchpath = os.path.join(self.path, pbranch) prepo = hg.peer(self.ui, {}, pbranchpath) self.ui.note( @@ -424,7 +422,7 @@ tagparent = tagparent or self.repo.nullid oldlines = set() - for branch, heads in pycompat.iteritems(self.repo.branchmap()): + for branch, heads in self.repo.branchmap().items(): for h in heads: if b'.hgtags' in self.repo[h]: oldlines.update( @@ -596,7 +594,7 @@ maappend = ma.append rappend = r.append d = ctx1.manifest().diff(ctx2.manifest()) - for f, ((node1, flag1), (node2, flag2)) in pycompat.iteritems(d): + for f, ((node1, flag1), (node2, flag2)) in d.items(): if node2 is None: rappend(f) else: @@ -622,7 +620,7 @@ cleanp2 = set() if len(parents) == 2: d = parents[1].manifest().diff(ctx.manifest(), clean=True) - for f, value in pycompat.iteritems(d): + for f, value in d.items(): if value is None: cleanp2.add(f) changes = [(f, rev) for f in files if f not in self.ignored]
--- a/hgext/convert/monotone.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/monotone.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import re @@ -103,7 +102,7 @@ # Prepare the command in automate stdio format kwargs = pycompat.byteskwargs(kwargs) command = [] - for k, v in pycompat.iteritems(kwargs): + for k, v in kwargs.items(): command.append(b"%d:%s" % (len(k), k)) if v: command.append(b"%d:%s" % (len(v), v)) @@ -151,7 +150,7 @@ raise error.Abort(_(b'bad mtn packet - no end of packet size')) lengthstr += read try: - length = pycompat.long(lengthstr[:-1]) + length = int(lengthstr[:-1]) except TypeError: raise error.Abort( _(b'bad mtn packet - bad packet size %s') % lengthstr
--- a/hgext/convert/p4.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/p4.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import marshal import re
--- a/hgext/convert/subversion.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/subversion.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,11 +1,11 @@ # Subversion 1.4/1.5 Python API backend # # Copyright(C) 2007 Daniel Holth et al -from __future__ import absolute_import import codecs import locale import os +import pickle import re import xml.dom.minidom @@ -26,7 +26,6 @@ from . import common -pickle = util.pickle stringio = util.stringio propertycache = util.propertycache urlerr = util.urlerr @@ -181,7 +180,7 @@ return optrev -class changedpath(object): +class changedpath: def __init__(self, p): self.copyfrom_path = p.copyfrom_path self.copyfrom_rev = p.copyfrom_rev @@ -203,7 +202,7 @@ def receiver(orig_paths, revnum, author, date, message, pool): paths = {} if orig_paths is not None: - for k, v in pycompat.iteritems(orig_paths): + for k, v in orig_paths.items(): paths[k] = changedpath(v) pickle.dump((paths, revnum, author, date, message), fp, protocol) @@ -249,7 +248,7 @@ get_log_child(ui.fout, *args) -class logstream(object): +class logstream: """Interruptible revision log iterator.""" def __init__(self, stdout): @@ -298,7 +297,7 @@ def receiver(orig_paths, revnum, author, date, message, pool): paths = {} if orig_paths is not None: - for k, v in pycompat.iteritems(orig_paths): + for k, v in orig_paths.items(): paths[k] = changedpath(v) self.append((paths, revnum, author, date, message)) @@ -730,7 +729,7 @@ ) files = [ n - for n, e in pycompat.iteritems(entries) + for n, e in entries.items() if e.kind == svn.core.svn_node_file ] self.removed = set() @@ -820,7 +819,7 @@ origpaths = [] copies = [ (e.copyfrom_path, e.copyfrom_rev, p) - for p, e in pycompat.iteritems(origpaths) + for p, e in origpaths.items() if e.copyfrom_path ] # Apply moves/copies from more specific to general @@ -851,7 +850,7 @@ # be represented in mercurial. addeds = { p: e.copyfrom_path - for p, e in pycompat.iteritems(origpaths) + for p, e in origpaths.items() if e.action == b'A' and e.copyfrom_path } badroots = set() @@ -1140,7 +1139,7 @@ parents = [] # check whether this revision is the start of a branch or part # of a branch renaming - orig_paths = sorted(pycompat.iteritems(orig_paths)) + orig_paths = sorted(orig_paths.items()) root_paths = [ (p, e) for p, e in orig_paths if self.module.startswith(p) ] @@ -1302,7 +1301,7 @@ path += b'/' return ( (path + p) - for p, e in pycompat.iteritems(entries) + for p, e in entries.items() if e.kind == svn.core.svn_node_file )
--- a/hgext/convert/transport.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/convert/transport.py Tue Apr 05 11:09:03 2022 +0200 @@ -16,7 +16,6 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. -from __future__ import absolute_import import svn.client import svn.core @@ -71,7 +70,7 @@ pass -class SvnRaTransport(object): +class SvnRaTransport: """ Open an ra connection to a Subversion repository. """ @@ -108,7 +107,7 @@ self.ra = ra svn.ra.reparent(self.ra, self.svn_url.encode('utf8')) - class Reporter(object): + class Reporter: def __init__(self, reporter_data): self._reporter, self._baton = reporter_data
--- a/hgext/eol.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/eol.py Tue Apr 05 11:09:03 2022 +0200 @@ -91,7 +91,6 @@ used. """ -from __future__ import absolute_import import os import re @@ -186,7 +185,7 @@ } -class eolfile(object): +class eolfile: def __init__(self, ui, root, data): self._decode = { b'LF': b'to-lf', @@ -379,7 +378,7 @@ if not repo.local(): return - for name, fn in pycompat.iteritems(filters): + for name, fn in filters.items(): repo.adddatafilter(name, fn) ui.setconfig(b'patch', b'eol', b'auto', b'eol')
--- a/hgext/extdiff.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/extdiff.py Tue Apr 05 11:09:03 2022 +0200 @@ -81,7 +81,6 @@ pretty fast (at least faster than having to compare the entire tree). ''' -from __future__ import absolute_import import os import re @@ -696,7 +695,7 @@ return dodiff(ui, repo, cmdline, pats, opts) -class savedcmd(object): +class savedcmd: """use external program to diff repository (or selected files) Show differences between revisions for the specified files, using
--- a/hgext/factotum.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/factotum.py Tue Apr 05 11:09:03 2022 +0200 @@ -45,7 +45,6 @@ ''' -from __future__ import absolute_import import os from mercurial.i18n import _
--- a/hgext/fastannotate/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -101,7 +101,6 @@ # # * format changes to the revmap file (maybe use length-encoding # instead of null-terminated file paths at least?) -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/fastannotate/commands.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/commands.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os
--- a/hgext/fastannotate/context.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/context.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import contextlib @@ -160,7 +159,7 @@ _defaultdiffopthash = hashdiffopts(mdiff.defaultopts) -class annotateopts(object): +class annotateopts: """like mercurial.mdiff.diffopts, but is for annotate followrename: follow renames, like "hg annotate -f" @@ -175,7 +174,7 @@ def __init__(self, **opts): opts = pycompat.byteskwargs(opts) - for k, v in pycompat.iteritems(self.defaults): + for k, v in self.defaults.items(): setattr(self, k, opts.get(k, v)) @util.propertycache @@ -197,7 +196,7 @@ defaultopts = annotateopts() -class _annotatecontext(object): +class _annotatecontext: """do not use this class directly as it does not use lock to protect writes. use "with annotatecontext(...)" instead. """ @@ -584,7 +583,7 @@ # find an unresolved line and its linelog rev to annotate hsh = None try: - for (rev, _linenum), idxs in pycompat.iteritems(key2idxs): + for (rev, _linenum), idxs in key2idxs.items(): if revmap.rev2flag(rev) & revmapmod.sidebranchflag: continue hsh = annotateresult[idxs[0]][0] @@ -595,7 +594,7 @@ # the remaining key2idxs are not in main branch, resolving them # using the hard way... revlines = {} - for (rev, linenum), idxs in pycompat.iteritems(key2idxs): + for (rev, linenum), idxs in key2idxs.items(): if rev not in revlines: hsh = annotateresult[idxs[0]][0] if self.ui.debugflag: @@ -784,7 +783,7 @@ pass -class pathhelper(object): +class pathhelper: """helper for getting paths for lockfile, linelog and revmap""" def __init__(self, repo, path, opts=defaultopts):
--- a/hgext/fastannotate/error.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/error.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import class CorruptedFileError(Exception):
--- a/hgext/fastannotate/formatter.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/formatter.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.node import ( hex, @@ -20,7 +19,7 @@ # imitating mercurial.commands.annotate, not using the vanilla formatter since # the data structures are a bit different, and we have some fast paths. -class defaultformatter(object): +class defaultformatter: """the default formatter that does leftpad and support some common flags""" def __init__(self, ui, repo, opts):
--- a/hgext/fastannotate/protocol.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/protocol.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import os @@ -15,7 +14,6 @@ error, extensions, hg, - pycompat, util, wireprotov1peer, wireprotov1server, @@ -190,7 +188,7 @@ for result in results: r = result.result() # TODO: pconvert these paths on the server? - r = {util.pconvert(p): v for p, v in pycompat.iteritems(r)} + r = {util.pconvert(p): v for p, v in r.items()} for path in sorted(r): # ignore malicious paths if not path.startswith(b'fastannotate/') or b'/../' in (
--- a/hgext/fastannotate/revmap.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/revmap.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import bisect import io @@ -49,7 +48,7 @@ _hshlen = 20 -class revmap(object): +class revmap: """trivial hg bin hash - linelog rev bidirectional map also stores a flag (uint8) for each revision, and track renames.
--- a/hgext/fastannotate/support.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastannotate/support.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.pycompat import getattr from mercurial import ( @@ -23,7 +22,7 @@ ) -class _lazyfctx(object): +class _lazyfctx: """delegates to fctx but do not construct fctx when unnecessary""" def __init__(self, repo, node, path):
--- a/hgext/fastexport.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fastexport.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # The format specification for fast-import streams can be found at # https://git-scm.com/docs/git-fast-import#_input_format -from __future__ import absolute_import import re from mercurial.i18n import _
--- a/hgext/fetch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fetch.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ '''pull, update and merge in one command (DEPRECATED)''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial.node import short
--- a/hgext/fix.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fix.py Tue Apr 05 11:09:03 2022 +0200 @@ -122,7 +122,6 @@ file content back to stdout as documented above. """ -from __future__ import absolute_import import collections import itertools @@ -378,9 +377,7 @@ Useful as a hook point for extending "hg fix" with output summarizing the effects of the command, though we choose not to output anything here. """ - replacements = { - prec: [succ] for prec, succ in pycompat.iteritems(replacements) - } + replacements = {prec: [succ] for prec, succ in replacements.items()} scmutil.cleanupnodes(repo, replacements, b'fix', fixphase=True) @@ -693,7 +690,7 @@ """ metadata = {} newdata = fixctx[path].data() - for fixername, fixer in pycompat.iteritems(fixers): + for fixername, fixer in fixers.items(): if fixer.affects(opts, fixctx, path): ranges = lineranges( opts, path, basepaths, basectxs, fixctx, newdata @@ -771,7 +768,7 @@ Directly updates the dirstate for the affected files. """ - for path, data in pycompat.iteritems(filedata): + for path, data in filedata.items(): fctx = ctx[path] fctx.write(data, fctx.flags()) @@ -906,7 +903,7 @@ return names -class Fixer(object): +class Fixer: """Wraps the raw config values for a fixer with methods""" def __init__(
--- a/hgext/fsmonitor/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -107,7 +107,6 @@ # The issues related to nested repos and subrepos are probably not fundamental # ones. Patches to fix them are welcome. -from __future__ import absolute_import import codecs import os @@ -502,15 +501,11 @@ visit.update(f for f in copymap if f not in results and matchfn(f)) else: if matchalways: - visit.update( - f for f, st in pycompat.iteritems(dmap) if f not in results - ) + visit.update(f for f, st in dmap.items() if f not in results) visit.update(f for f in copymap if f not in results) else: visit.update( - f - for f, st in pycompat.iteritems(dmap) - if f not in results and matchfn(f) + f for f, st in dmap.items() if f not in results and matchfn(f) ) visit.update(f for f in copymap if f not in results and matchfn(f)) @@ -686,7 +681,7 @@ ) -class poststatus(object): +class poststatus: def __init__(self, startclock): self._startclock = pycompat.sysbytes(startclock) @@ -761,7 +756,7 @@ pass -class state_update(object): +class state_update: """This context manager is responsible for dispatching the state-enter and state-leave signals to the watchman service. The enter and leave methods can be invoked manually (for scenarios where context manager
--- a/hgext/fsmonitor/pywatchman/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/pywatchman/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # no unicode literals -from __future__ import absolute_import, division, print_function import inspect import math @@ -302,7 +301,7 @@ ) -class Transport(object): +class Transport: """communication transport to the watchman server""" buf = None @@ -347,7 +346,7 @@ self.buf.append(b) -class Codec(object): +class Codec: """communication encoding for the watchman server""" transport = None @@ -860,7 +859,7 @@ self.transport.write(cmd + b"\n") -class client(object): +class client: """Handles the communication with the watchman service""" sockpath = None
--- a/hgext/fsmonitor/pywatchman/capabilities.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/pywatchman/capabilities.py Tue Apr 05 11:09:03 2022 +0200 @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # no unicode literals -from __future__ import absolute_import, division, print_function def parse_version(vstr):
--- a/hgext/fsmonitor/pywatchman/compat.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/pywatchman/compat.py Tue Apr 05 11:09:03 2022 +0200 @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # no unicode literals -from __future__ import absolute_import, division, print_function import sys
--- a/hgext/fsmonitor/pywatchman/encoding.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/pywatchman/encoding.py Tue Apr 05 11:09:03 2022 +0200 @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # no unicode literals -from __future__ import absolute_import, division, print_function import sys
--- a/hgext/fsmonitor/pywatchman/load.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/pywatchman/load.py Tue Apr 05 11:09:03 2022 +0200 @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # no unicode literals -from __future__ import absolute_import, division, print_function import ctypes
--- a/hgext/fsmonitor/pywatchman/pybser.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/pywatchman/pybser.py Tue Apr 05 11:09:03 2022 +0200 @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # no unicode literals -from __future__ import absolute_import, division, print_function import binascii import collections @@ -94,7 +93,7 @@ return ret -class _bser_buffer(object): +class _bser_buffer: def __init__(self, version): self.bser_version = version self.buf = ctypes.create_string_buffer(8192) @@ -325,7 +324,7 @@ # This is a quack-alike with the bserObjectType in bser.c # It provides by getattr accessors and getitem for both index # and name. -class _BunserDict(object): +class _BunserDict: __slots__ = ("_keys", "_values") def __init__(self, keys, values): @@ -351,7 +350,7 @@ return len(self._keys) -class Bunser(object): +class Bunser: def __init__(self, mutable=True, value_encoding=None, value_errors=None): self.mutable = mutable self.value_encoding = value_encoding
--- a/hgext/fsmonitor/state.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/state.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -23,7 +22,7 @@ _versionformat = b">I" -class state(object): +class state: def __init__(self, repo): self._vfs = repo.vfs self._ui = repo.ui
--- a/hgext/fsmonitor/watchmanclient.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/fsmonitor/watchmanclient.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import getpass @@ -44,7 +43,7 @@ super(WatchmanNoRoot, self).__init__(msg) -class client(object): +class client: def __init__(self, ui, root, timeout=1.0): err = None if not self._user:
--- a/hgext/git/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/git/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ firstborn a la Rumpelstiltskin, etc. """ -from __future__ import absolute_import import os @@ -48,7 +47,7 @@ # TODO: extract an interface for this in core -class gitstore(object): # store.basicstore): +class gitstore: # store.basicstore): def __init__(self, path, vfstype): self.vfs = vfstype(path) self.opener = self.vfs @@ -130,7 +129,7 @@ return orig(requirements, storebasepath, vfstype) -class gitfilestorage(object): +class gitfilestorage: def file(self, path): if path[0:1] == b'/': path = path[1:] @@ -162,7 +161,7 @@ _BMS_PREFIX = 'refs/heads/' -class gitbmstore(object): +class gitbmstore: def __init__(self, gitrepo): self.gitrepo = gitrepo self._aclean = True
--- a/hgext/git/dirstate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/git/dirstate.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import contextlib import errno import os @@ -68,7 +66,7 @@ @interfaceutil.implementer(intdirstate.idirstate) -class gitdirstate(object): +class gitdirstate: def __init__(self, ui, root, gitrepo): self._ui = ui self._root = os.path.dirname(root)
--- a/hgext/git/gitlog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/git/gitlog.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from mercurial.i18n import _ from mercurial.node import ( @@ -31,7 +29,7 @@ pygit2 = gitutil.get_pygit2() -class baselog(object): # revlog.revlog): +class baselog: # revlog.revlog): """Common implementations between changelog and manifestlog.""" def __init__(self, gr, db): @@ -71,7 +69,7 @@ return t is not None -class baselogindex(object): +class baselogindex: def __init__(self, log): self._log = log
--- a/hgext/git/gitutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/git/gitutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ """utilities to assist in working with pygit2""" -from __future__ import absolute_import from mercurial.node import bin, hex, sha1nodeconstants
--- a/hgext/git/index.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/git/index.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import collections import os import sqlite3
--- a/hgext/git/manifest.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/git/manifest.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from mercurial import ( match as matchmod, pathutil, @@ -17,7 +15,7 @@ @interfaceutil.implementer(repository.imanifestdict) -class gittreemanifest(object): +class gittreemanifest: """Expose git trees (and optionally a builder's overlay) as a manifestdict. Very similar to mercurial.manifest.treemanifest. @@ -260,7 +258,7 @@ @interfaceutil.implementer(repository.imanifestrevisionstored) -class gittreemanifestctx(object): +class gittreemanifestctx: def __init__(self, repo, gittree): self._repo = repo self._tree = gittree @@ -281,7 +279,7 @@ @interfaceutil.implementer(repository.imanifestrevisionwritable) -class memgittreemanifestctx(object): +class memgittreemanifestctx: def __init__(self, repo, tree): self._repo = repo self._tree = tree
--- a/hgext/githelp.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/githelp.py Tue Apr 05 11:09:03 2022 +0200 @@ -15,7 +15,6 @@ produced. """ -from __future__ import absolute_import import getopt import re @@ -116,14 +115,14 @@ opts = dict( [ (k, convert(v)) if isinstance(v, bytes) else (k, v) - for k, v in pycompat.iteritems(opts) + for k, v in opts.items() ] ) return args, opts -class Command(object): +class Command: def __init__(self, name): self.name = name self.args = [] @@ -132,7 +131,7 @@ def __bytes__(self): cmd = b"hg " + self.name if self.opts: - for k, values in sorted(pycompat.iteritems(self.opts)): + for k, values in sorted(self.opts.items()): for v in values: if v: if isinstance(v, int): @@ -164,7 +163,7 @@ return AndCommand(self, other) -class AndCommand(object): +class AndCommand: def __init__(self, left, right): self.left = left self.right = right
--- a/hgext/gpg.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/gpg.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ '''commands to sign and verify changesets''' -from __future__ import absolute_import import binascii import os @@ -65,7 +64,7 @@ help.CATEGORY_NAMES[_HELP_CATEGORY] = b'Signing changes (GPG)' -class gpg(object): +class gpg: def __init__(self, path, key=None): self.path = path self.key = (key and b" --local-user \"%s\"" % key) or b""
--- a/hgext/graphlog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/graphlog.py Tue Apr 05 11:09:03 2022 +0200 @@ -15,7 +15,6 @@ revision graph is also shown. ''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/hgk.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/hgk.py Tue Apr 05 11:09:03 2022 +0200 @@ -34,7 +34,6 @@ vdiff on hovered and selected revisions. ''' -from __future__ import absolute_import import os @@ -377,9 +376,7 @@ """start interactive history viewer""" opts = pycompat.byteskwargs(opts) os.chdir(repo.root) - optstr = b' '.join( - [b'--%s %s' % (k, v) for k, v in pycompat.iteritems(opts) if v] - ) + optstr = b' '.join([b'--%s %s' % (k, v) for k, v in opts.items() if v]) if repo.filtername is None: optstr += b'--hidden'
--- a/hgext/highlight/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/highlight/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -26,7 +26,6 @@ match (even matches with a low confidence score) will be used. """ -from __future__ import absolute_import from . import highlight from mercurial.hgweb import (
--- a/hgext/highlight/highlight.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/highlight/highlight.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # The original module was split in an interface and an implementation # file to defer pygments loading and speedup extension setup. -from __future__ import absolute_import from mercurial import demandimport
--- a/hgext/histedit.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/histedit.py Tue Apr 05 11:09:03 2022 +0200 @@ -190,7 +190,6 @@ """ -from __future__ import absolute_import # chistedit dependencies that are not available everywhere try: @@ -202,6 +201,7 @@ import functools import os +import pickle import struct from mercurial.i18n import _ @@ -245,7 +245,6 @@ urlutil, ) -pickle = util.pickle cmdtable = {} command = registrar.command(cmdtable) @@ -352,7 +351,7 @@ return b''.join([b'# %s\n' % l if l else b'#\n' for l in lines]) -class histeditstate(object): +class histeditstate: def __init__(self, repo): self.repo = repo self.actions = None @@ -491,7 +490,7 @@ return self.repo.vfs.exists(b'histedit-state') -class histeditaction(object): +class histeditaction: def __init__(self, state, node): self.state = state self.repo = state.repo @@ -1143,7 +1142,7 @@ return struct.unpack(b'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, b' ')) -class histeditrule(object): +class histeditrule: def __init__(self, ui, ctx, pos, action=b'pick'): self.ui = ui self.ctx = ctx @@ -1243,7 +1242,7 @@ return line[: n - 2] + b' >' -class _chistedit_state(object): +class _chistedit_state: def __init__( self, repo, @@ -2102,7 +2101,7 @@ mapping, tmpnodes, created, ntm = processreplacement(state) if mapping: - for prec, succs in pycompat.iteritems(mapping): + for prec, succs in mapping.items(): if not succs: ui.debug(b'histedit: %s is dropped\n' % short(prec)) else: @@ -2140,7 +2139,7 @@ nodechanges = fd( { hf(oldn): fl([hf(n) for n in newn], name=b'node') - for oldn, newn in pycompat.iteritems(mapping) + for oldn, newn in mapping.items() }, key=b"oldnode", value=b"newnodes", @@ -2388,7 +2387,7 @@ tsum = summary[len(fword) + 1 :].lstrip() # safe but slow: reverse iterate over the actions so we # don't clash on two commits having the same summary - for na, l in reversed(list(pycompat.iteritems(newact))): + for na, l in reversed(list(newact.items())): actx = repo[na.node] asum = _getsummary(actx) if asum == tsum: @@ -2401,7 +2400,7 @@ # copy over and flatten the new list actions = [] - for na, l in pycompat.iteritems(newact): + for na, l in newact.items(): actions.append(na) actions += l
--- a/hgext/hooklib/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/hooklib/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -13,7 +13,6 @@ extension as option. The functionality itself is planned to be supported long-term. """ -from __future__ import absolute_import from . import ( changeset_obsoleted, changeset_published,
--- a/hgext/hooklib/changeset_obsoleted.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/hooklib/changeset_obsoleted.py Tue Apr 05 11:09:03 2022 +0200 @@ -17,7 +17,6 @@ python:hgext.hooklib.changeset_obsoleted.hook """ -from __future__ import absolute_import import email.errors as emailerrors import email.utils as emailutils
--- a/hgext/hooklib/changeset_published.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/hooklib/changeset_published.py Tue Apr 05 11:09:03 2022 +0200 @@ -17,7 +17,6 @@ python:hgext.hooklib.changeset_published.hook """ -from __future__ import absolute_import import email.errors as emailerrors import email.utils as emailutils
--- a/hgext/hooklib/enforce_draft_commits.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/hooklib/enforce_draft_commits.py Tue Apr 05 11:09:03 2022 +0200 @@ -14,7 +14,6 @@ python:hgext.hooklib.enforce_draft_commits.hook """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/hooklib/reject_merge_commits.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/hooklib/reject_merge_commits.py Tue Apr 05 11:09:03 2022 +0200 @@ -14,7 +14,6 @@ python:hgext.hooklib.reject_merge_commits.hook """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/hooklib/reject_new_heads.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/hooklib/reject_new_heads.py Tue Apr 05 11:09:03 2022 +0200 @@ -14,7 +14,6 @@ python:hgext.hooklib.reject_new_heads.hook """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/infinitepush/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/infinitepush/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -87,7 +87,6 @@ bookmarks = True """ -from __future__ import absolute_import import collections import contextlib @@ -287,7 +286,7 @@ return remotebookmark -class bundlestore(object): +class bundlestore: def __init__(self, repo): self._repo = repo storetype = self._repo.ui.config(b'infinitepush', b'storetype') @@ -406,7 +405,7 @@ def wireprotolistkeyspatterns(repo, proto, namespace, patterns): patterns = wireprototypes.decodelist(patterns) - d = pycompat.iteritems(repo.listkeys(encoding.tolocal(namespace), patterns)) + d = repo.listkeys(encoding.tolocal(namespace), patterns).items() return pushkey.encodekeys(d) @@ -420,7 +419,7 @@ if pattern.endswith(b'*'): pattern = b're:^' + pattern[:-1] + b'.*' kind, pat, matcher = stringutil.stringmatcher(pattern) - for bookmark, node in pycompat.iteritems(bookmarks): + for bookmark, node in bookmarks.items(): if matcher(bookmark): results[bookmark] = node return results @@ -543,7 +542,7 @@ if part.type == b'changegroup': haschangegroup = True newpart = bundle2.bundlepart(part.type, data=part.read()) - for key, value in pycompat.iteritems(part.params): + for key, value in part.params.items(): newpart.addparam(key, value) parts.append(newpart) @@ -795,7 +794,7 @@ # saveremotenames expects 20 byte binary nodes for branches branches[rname].append(bin(hexnode)) - for bookmark, hexnode in pycompat.iteritems(newbookmarks): + for bookmark, hexnode in newbookmarks.items(): bookmarks[bookmark] = hexnode remotenamesext.saveremotenames(repo, remotepath, branches, bookmarks) @@ -805,7 +804,7 @@ return with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr: changes = [] - for scratchbook, node in pycompat.iteritems(bookmarks): + for scratchbook, node in bookmarks.items(): changectx = repo[node] changes.append((scratchbook, changectx.node())) repo._bookmarks.applychanges(repo, tr, changes) @@ -1046,7 +1045,7 @@ bundle2._processpart(op, part) else: bundlepart = bundle2.bundlepart(part.type, data=part.read()) - for key, value in pycompat.iteritems(part.params): + for key, value in part.params.items(): bundlepart.addparam(key, value) # Certain parts require a response @@ -1138,7 +1137,7 @@ # differs from previous behavior, we need to put it behind a # config flag for incremental rollout. bundlepart = bundle2.bundlepart(part.type, data=part.read()) - for key, value in pycompat.iteritems(part.params): + for key, value in part.params.items(): bundlepart.addparam(key, value) # Certain parts require a response @@ -1324,9 +1323,7 @@ b'new': newnode, b'old': oldnode, } - op.reply.newpart( - b'pushkey', mandatoryparams=pycompat.iteritems(params) - ) + op.reply.newpart(b'pushkey', mandatoryparams=params.items()) def bundle2pushkey(orig, op, part):
--- a/hgext/infinitepush/bundleparts.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/infinitepush/bundleparts.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.i18n import _ from mercurial.node import hex @@ -13,7 +12,6 @@ changegroup, error, extensions, - pycompat, revsetlang, util, ) @@ -68,7 +66,7 @@ parts.append( bundle2.bundlepart( scratchbranchparttype.upper(), - advisoryparams=pycompat.iteritems(params), + advisoryparams=params.items(), data=cg, ) ) @@ -103,7 +101,7 @@ return -class copiedpart(object): +class copiedpart: """a copy of unbundlepart content that can be consumed later""" def __init__(self, part):
--- a/hgext/infinitepush/common.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/infinitepush/common.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os
--- a/hgext/infinitepush/fileindexapi.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/infinitepush/fileindexapi.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ indexpath = PATH """ -from __future__ import absolute_import import os
--- a/hgext/infinitepush/indexapi.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/infinitepush/indexapi.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,10 +5,8 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import - -class indexapi(object): +class indexapi: """Class that manages access to infinitepush index. This class is a context manager and all write operations (like
--- a/hgext/infinitepush/sqlindexapi.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/infinitepush/sqlindexapi.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import logging import os @@ -14,8 +13,6 @@ import warnings import mysql.connector -from mercurial import pycompat - from . import indexapi @@ -180,7 +177,7 @@ self.sqlconnect() args = [] values = [] - for bookmark, node in pycompat.iteritems(bookmarks): + for bookmark, node in bookmarks.items(): args.append(b'(%s, %s, %s)') values.extend((bookmark, node, self.reponame)) args = b','.join(args)
--- a/hgext/infinitepush/store.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/infinitepush/store.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # based on bundleheads extension by Gregory Szorc <gps@mozilla.com> -from __future__ import absolute_import import abc import os @@ -26,7 +25,7 @@ pass -class abstractbundlestore(object): # pytype: disable=ignored-metaclass +class abstractbundlestore: # pytype: disable=ignored-metaclass """Defines the interface for bundle stores. A bundle store is an entity that stores raw bundle data. It is a simple @@ -57,7 +56,7 @@ """ -class filebundlestore(object): +class filebundlestore: """bundle store in filesystem meant for storing bundles somewhere on disk and on network filesystems
--- a/hgext/journal.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/journal.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ """ -from __future__ import absolute_import import collections import errno @@ -129,7 +128,7 @@ repo = store._repo if util.safehasattr(repo, 'journal'): oldmarks = bookmarks.bmstore(repo) - for mark, value in pycompat.iteritems(store): + for mark, value in store.items(): oldvalue = oldmarks.get(mark, repo.nullid) if value != oldvalue: repo.journal.record(bookmarktype, mark, oldvalue, value) @@ -167,7 +166,7 @@ pass while iterable_map: - value, key, it = order(pycompat.itervalues(iterable_map)) + value, key, it = order(iterable_map.values()) yield value try: iterable_map[key][0] = next(it) @@ -283,7 +282,7 @@ __str__ = encoding.strmethod(__bytes__) -class journalstorage(object): +class journalstorage: """Storage for journal entries Entries are divided over two files; one with entries that pertain to the
--- a/hgext/keyword.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/keyword.py Tue Apr 05 11:09:03 2022 +0200 @@ -83,8 +83,6 @@ ''' -from __future__ import absolute_import - import os import re import weakref @@ -237,7 +235,7 @@ return modified, added -class kwtemplater(object): +class kwtemplater: """ Sets up keyword templates, corresponding keyword regex, and provides keyword substitution functions. @@ -515,7 +513,7 @@ kwmaps = _defaultkwmaps(ui) if uikwmaps: ui.status(_(b'\tdisabling current template maps\n')) - for k, v in pycompat.iteritems(kwmaps): + for k, v in kwmaps.items(): ui.setconfig(b'keywordmaps', k, v, b'keyword') else: ui.status(_(b'\n\tconfiguration using current keyword template maps\n')) @@ -529,7 +527,7 @@ ui.writenoi18n(b'[extensions]\nkeyword =\n') demoitems(b'keyword', ui.configitems(b'keyword')) demoitems(b'keywordset', ui.configitems(b'keywordset')) - demoitems(b'keywordmaps', pycompat.iteritems(kwmaps)) + demoitems(b'keywordmaps', kwmaps.items()) keywords = b'$' + b'$\n$'.join(sorted(kwmaps.keys())) + b'$\n' repo.wvfs.write(fn, keywords) repo[None].add([fn])
--- a/hgext/largefiles/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -104,7 +104,6 @@ explicitly do so with the --large flag passed to the :hg:`add` command. ''' -from __future__ import absolute_import from mercurial import ( cmdutil,
--- a/hgext/largefiles/basestore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/basestore.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. '''base class for store implementations and store-related utility code''' -from __future__ import absolute_import from mercurial.i18n import _ @@ -42,7 +41,7 @@ return b"%s: %s" % (urlutil.hidepassword(self.url), self.detail) -class basestore(object): +class basestore: def __init__(self, ui, repo, url): self.ui = ui self.repo = repo
--- a/hgext/largefiles/lfcommands.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/lfcommands.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. '''High-level command function for lfconvert, plus the cmdtable.''' -from __future__ import absolute_import import errno import os
--- a/hgext/largefiles/lfutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/lfutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. '''largefiles utility code: must not import other modules in this package.''' -from __future__ import absolute_import import contextlib import copy @@ -757,7 +756,7 @@ return match -class automatedcommithook(object): +class automatedcommithook: """Stateful hook to update standins at the 1st commit of resuming For efficiency, updating standins in the working directory should
--- a/hgext/largefiles/localstore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/localstore.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. '''store class for local filesystem''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial.pycompat import open
--- a/hgext/largefiles/overrides.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/overrides.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. '''Overridden Mercurial commands and functions for the largefiles extension''' -from __future__ import absolute_import import copy import os @@ -493,7 +492,7 @@ large = opts.pop('large', False) if large: - class fakerepo(object): + class fakerepo: dirstate = lfutil.openlfdirstate(ui, repo) orig(ui, fakerepo, *pats, **opts) @@ -714,7 +713,7 @@ copies = orig(ctx1, ctx2, match=match) updated = {} - for k, v in pycompat.iteritems(copies): + for k, v in copies.items(): updated[lfutil.splitstandin(k) or k] = lfutil.splitstandin(v) or v return updated
--- a/hgext/largefiles/proto.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/proto.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os
--- a/hgext/largefiles/remotestore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/remotestore.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,13 +5,11 @@ # GNU General Public License version 2 or any later version. '''remote largefile store; the base class for wirestore''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import ( error, - pycompat, util, ) @@ -53,9 +51,8 @@ def exists(self, hashes): return { h: s == 0 - for (h, s) in pycompat.iteritems( - self._stat(hashes) - ) # dict-from-generator + for (h, s) in self._stat(hashes).items() + # dict-from-generator } def sendfile(self, filename, hash):
--- a/hgext/largefiles/reposetup.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/reposetup.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. '''setup for largefiles repositories: reposetup''' -from __future__ import absolute_import import copy
--- a/hgext/largefiles/storefactory.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/storefactory.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re
--- a/hgext/largefiles/wirestore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/largefiles/wirestore.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # GNU General Public License version 2 or any later version. '''largefile store working over Mercurial's wire protocol''' -from __future__ import absolute_import from . import ( lfutil,
--- a/hgext/lfs/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/lfs/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -120,7 +120,6 @@ usercache = /path/to/global/cache """ -from __future__ import absolute_import import sys @@ -400,7 +399,7 @@ def pointer(v): # In the file spec, version is first and the other keys are sorted. sortkeyfunc = lambda x: (x[0] != b'version', x) - items = sorted(pycompat.iteritems(pointers[v]), key=sortkeyfunc) + items = sorted(pointers[v].items(), key=sortkeyfunc) return util.sortdict(items) makemap = lambda v: {
--- a/hgext/lfs/blobstore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/lfs/blobstore.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import errno @@ -109,7 +108,7 @@ return None # progress is handled by the worker client -class local(object): +class local: """Local blobstore for large file contents. This blobstore is used both as a cache and as a staging area for large blobs @@ -274,7 +273,7 @@ except (AttributeError, IndexError): # it might be anything, for example a string reason = inst.reason - if isinstance(reason, pycompat.unicode): + if isinstance(reason, str): # SSLError of Python 2.7.9 contains a unicode reason = encoding.unitolocal(reason) return reason @@ -307,7 +306,7 @@ return None -class _gitlfsremote(object): +class _gitlfsremote: def __init__(self, repo, url): ui = repo.ui self.ui = ui @@ -407,7 +406,7 @@ ) def encodestr(x): - if isinstance(x, pycompat.unicode): + if isinstance(x, str): return x.encode('utf-8') return x @@ -643,7 +642,7 @@ getattr(h, "close_all", lambda: None)() -class _dummyremote(object): +class _dummyremote: """Dummy store storing blobs to temp directory.""" def __init__(self, repo, url): @@ -662,7 +661,7 @@ tostore.download(p.oid(), fp, None) -class _nullremote(object): +class _nullremote: """Null store storing blobs to /dev/null.""" def __init__(self, repo, url): @@ -675,7 +674,7 @@ pass -class _promptremote(object): +class _promptremote: """Prompt user to set lfs.url when accessed.""" def __init__(self, repo, url):
--- a/hgext/lfs/pointer.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/lfs/pointer.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re @@ -41,7 +40,7 @@ def serialize(self): sortkeyfunc = lambda x: (x[0] != b'version', x) - items = sorted(pycompat.iteritems(self.validate()), key=sortkeyfunc) + items = sorted(self.validate().items(), key=sortkeyfunc) return b''.join(b'%s %s\n' % (k, v) for k, v in items) def oid(self): @@ -63,7 +62,7 @@ def validate(self): """raise InvalidPointer on error. return self if there is no error""" requiredcount = 0 - for k, v in pycompat.iteritems(self): + for k, v in self.items(): if k in self._requiredre: if not self._requiredre[k].match(v): raise InvalidPointer(
--- a/hgext/lfs/wireprotolfsserver.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/lfs/wireprotolfsserver.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import datetime import errno
--- a/hgext/lfs/wrapper.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/lfs/wrapper.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import hashlib @@ -25,7 +24,6 @@ exchange, exthelper, localrepo, - pycompat, revlog, scmutil, util, @@ -143,7 +141,7 @@ # translate hg filelog metadata to lfs metadata with "x-hg-" prefix if hgmeta is not None: - for k, v in pycompat.iteritems(hgmeta): + for k, v in hgmeta.items(): metadata[b'x-hg-%s' % k] = v rawtext = metadata.serialize()
--- a/hgext/logtoprocess.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/logtoprocess.py Tue Apr 05 11:09:03 2022 +0200 @@ -32,7 +32,6 @@ """ -from __future__ import absolute_import import os @@ -45,7 +44,7 @@ testedwith = b'ships-with-hg-core' -class processlogger(object): +class processlogger: """Map log events to external commands Arguments are passed on as environment variables.
--- a/hgext/mq.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/mq.py Tue Apr 05 11:09:03 2022 +0200 @@ -62,7 +62,6 @@ in the strip extension. ''' -from __future__ import absolute_import, print_function import errno import os @@ -151,7 +150,7 @@ except KeyError: # note: load is lazy so we could avoid the try-except, # but I (marmoute) prefer this explicit code. - class dummyui(object): + class dummyui: def debug(self, msg): pass @@ -184,7 +183,7 @@ normname = util.normpath -class statusentry(object): +class statusentry: def __init__(self, node, name): self.node, self.name = node, name @@ -294,7 +293,7 @@ return lines -class patchheader(object): +class patchheader: def __init__(self, pf, plainmode=False): def eatdiff(lines): while lines: @@ -496,7 +495,7 @@ pass -class queue(object): +class queue: def __init__(self, ui, baseui, path, patchdir=None): self.basepath = path try: @@ -2025,7 +2024,7 @@ # we can't copy a file created by the patch itself if dst in copies: del copies[dst] - for src, dsts in pycompat.iteritems(copies): + for src, dsts in copies.items(): for dst in dsts: repo.dirstate.copy(src, dst) else: @@ -4288,7 +4287,7 @@ entry[1].extend(mqopt) def dotable(cmdtable): - for cmd, entry in pycompat.iteritems(cmdtable): + for cmd, entry in cmdtable.items(): cmd = cmdutil.parsealiases(cmd)[0] func = entry[0] if func.norepo:
--- a/hgext/narrow/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/narrow/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # GNU General Public License version 2 or any later version. '''create clones which fetch history data for subset of files (EXPERIMENTAL)''' -from __future__ import absolute_import from mercurial import ( localrepo,
--- a/hgext/narrow/narrowbundle2.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/narrow/narrowbundle2.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import struct
--- a/hgext/narrow/narrowcommands.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/narrow/narrowcommands.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import itertools import os
--- a/hgext/narrow/narrowdirstate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/narrow/narrowdirstate.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import error
--- a/hgext/narrow/narrowrepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/narrow/narrowrepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial import wireprototypes
--- a/hgext/narrow/narrowtemplates.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/narrow/narrowtemplates.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial import ( registrar,
--- a/hgext/narrow/narrowwirepeer.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/narrow/narrowwirepeer.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial import ( bundle2,
--- a/hgext/notify.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/notify.py Tue Apr 05 11:09:03 2022 +0200 @@ -154,7 +154,6 @@ references. See also ``notify.strip``. ''' -from __future__ import absolute_import import email.errors as emailerrors import email.utils as emailutils @@ -315,7 +314,7 @@ } -class notifier(object): +class notifier: '''email notification class.''' def __init__(self, ui, repo, hooktype):
--- a/hgext/pager.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/pager.py Tue Apr 05 11:09:03 2022 +0200 @@ -21,7 +21,6 @@ [pager] attend-cat = false ''' -from __future__ import absolute_import from mercurial import ( cmdutil,
--- a/hgext/patchbomb.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/patchbomb.py Tue Apr 05 11:09:03 2022 +0200 @@ -71,7 +71,6 @@ You can set patchbomb to always ask for confirmation by setting ``patchbomb.confirm`` to true. ''' -from __future__ import absolute_import import email.encoders as emailencoders import email.mime.base as emimebase
--- a/hgext/phabricator.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/phabricator.py Tue Apr 05 11:09:03 2022 +0200 @@ -57,11 +57,11 @@ example.phabtoken = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx """ -from __future__ import absolute_import import base64 import contextlib import hashlib +import io import itertools import json import mimetypes @@ -219,9 +219,7 @@ rawparams = encoding.unifromlocal(wdirvfs.read(b".arcconfig")) # json.loads only returns unicode strings arcconfig = pycompat.rapply( - lambda x: encoding.unitolocal(x) - if isinstance(x, pycompat.unicode) - else x, + lambda x: encoding.unitolocal(x) if isinstance(x, str) else x, pycompat.json_loads(rawparams), ) @@ -447,9 +445,7 @@ time.sleep(retry_interval) ui.debug(b'Conduit Response: %s\n' % body) parsed = pycompat.rapply( - lambda x: encoding.unitolocal(x) - if isinstance(x, pycompat.unicode) - else x, + lambda x: encoding.unitolocal(x) if isinstance(x, str) else x, # json.loads only accepts bytes from py3.6+ pycompat.json_loads(encoding.unifromlocal(body)), ) @@ -473,9 +469,7 @@ rawparams = encoding.unifromlocal(ui.fin.read()) # json.loads only returns unicode strings params = pycompat.rapply( - lambda x: encoding.unitolocal(x) - if isinstance(x, pycompat.unicode) - else x, + lambda x: encoding.unitolocal(x) if isinstance(x, str) else x, pycompat.json_loads(rawparams), ) # json.dumps only accepts unicode strings @@ -674,7 +668,7 @@ return output.getvalue() -class DiffChangeType(object): +class DiffChangeType: ADD = 1 CHANGE = 2 DELETE = 3 @@ -685,7 +679,7 @@ MULTICOPY = 8 -class DiffFileType(object): +class DiffFileType: TEXT = 1 IMAGE = 2 BINARY = 3 @@ -706,7 +700,7 @@ @attr.s -class phabchange(object): +class phabchange: """Represents a Differential change, owns Differential hunks and owned by a Differential diff. Each one represents one file in a diff. """ @@ -747,7 +741,7 @@ @attr.s -class phabdiff(object): +class phabdiff: """Represents a Differential diff, owns Differential changes. Corresponds to a commit. """ @@ -2200,7 +2194,7 @@ for drev, contents in patches: ui.status(_(b'applying patch from D%s\n') % drev) - with patch.extract(ui, pycompat.bytesio(contents)) as patchdata: + with patch.extract(ui, io.BytesIO(contents)) as patchdata: msg, node, rej = cmdutil.tryimportone( ui, repo, @@ -2279,7 +2273,7 @@ drevmap = getdrevmap(repo, logcmdutil.revrange(repo, [revs])) specs = [] unknown = [] - for r, d in pycompat.iteritems(drevmap): + for r, d in drevmap.items(): if d is None: unknown.append(repo[r]) else: @@ -2364,7 +2358,7 @@ revs = repo.revs('sort(_underway(), topo)') drevmap = getdrevmap(repo, revs) unknownrevs, drevids, revsbydrevid = [], set(), {} - for rev, drevid in pycompat.iteritems(drevmap): + for rev, drevid in drevmap.items(): if drevid is not None: drevids.add(drevid) revsbydrevid.setdefault(drevid, set()).add(rev)
--- a/hgext/rebase.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/rebase.py Tue Apr 05 11:09:03 2022 +0200 @@ -14,7 +14,6 @@ https://mercurial-scm.org/wiki/RebaseExtension ''' -from __future__ import absolute_import import errno import os @@ -160,7 +159,7 @@ ) -class rebaseruntime(object): +class rebaseruntime: """This class is a container for rebase runtime state""" def __init__(self, repo, ui, inmemory=False, dryrun=False, opts=None): @@ -244,7 +243,7 @@ f.write(b'%d\n' % int(self.keepbranchesf)) f.write(b'%s\n' % (self.activebookmark or b'')) destmap = self.destmap - for d, v in pycompat.iteritems(self.state): + for d, v in self.state.items(): oldrev = repo[d].hex() if v >= 0: newrev = repo[v].hex() @@ -506,7 +505,7 @@ # commits. self.storestatus(tr) - cands = [k for k, v in pycompat.iteritems(self.state) if v == revtodo] + cands = [k for k, v in self.state.items() if v == revtodo] p = repo.ui.makeprogress( _(b"rebasing"), unit=_(b'changesets'), total=len(cands) ) @@ -1337,7 +1336,7 @@ # emulate the old behavior, showing "nothing to rebase" (a better # behavior may be abort with "cannot find branching point" error) bpbase.clear() - for bp, bs in pycompat.iteritems(bpbase): # calculate roots + for bp, bs in bpbase.items(): # calculate roots roots += list(repo.revs(b'children(%d) & ancestors(%ld)', bp, bs)) rebaseset = repo.revs(b'%ld::', roots) @@ -2104,7 +2103,7 @@ fl = fm.formatlist fd = fm.formatdict changes = {} - for oldns, newn in pycompat.iteritems(replacements): + for oldns, newn in replacements.items(): for oldn in oldns: changes[hf(oldn)] = fl([hf(n) for n in newn], name=b'node') nodechanges = fd(changes, key=b"oldnode", value=b"newnodes") @@ -2258,7 +2257,7 @@ msg = _(b'rebase: (use "hg rebase --abort" to clear broken state)\n') ui.write(msg) return - numrebased = len([i for i in pycompat.itervalues(state) if i >= 0]) + numrebased = len([i for i in state.values() if i >= 0]) # i18n: column positioning for "hg summary" ui.write( _(b'rebase: %s, %s (rebase --continue)\n')
--- a/hgext/record.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/record.py Tue Apr 05 11:09:03 2022 +0200 @@ -10,7 +10,6 @@ The feature provided by this extension has been moved into core Mercurial as :hg:`commit --interactive`.''' -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/hgext/releasenotes.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/releasenotes.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ process simpler by automating it. """ -from __future__ import absolute_import import difflib import errno @@ -78,7 +77,7 @@ BULLET_SECTION = _(b'Other Changes') -class parsedreleasenotes(object): +class parsedreleasenotes: def __init__(self): self.sections = {} @@ -171,14 +170,14 @@ self.addnontitleditem(section, paragraphs) -class releasenotessections(object): +class releasenotessections: def __init__(self, ui, repo=None): if repo: sections = util.sortdict(DEFAULT_SECTIONS) custom_sections = getcustomadmonitions(repo) if custom_sections: sections.update(custom_sections) - self._sections = list(pycompat.iteritems(sections)) + self._sections = list(sections.items()) else: self._sections = list(DEFAULT_SECTIONS)
--- a/hgext/relink.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/relink.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # GNU General Public License version 2 or any later version. """recreates hardlinks between repository clones""" -from __future__ import absolute_import import os import stat
--- a/hgext/remotefilelog/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -124,7 +124,6 @@ corruption before returning metadata """ -from __future__ import absolute_import import os import time
--- a/hgext/remotefilelog/basepack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/basepack.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import collections import errno import mmap @@ -65,7 +63,7 @@ PACKOPENMODE = b'rb' -class _cachebackedpacks(object): +class _cachebackedpacks: def __init__(self, packs, cachesize): self._packs = set(packs) self._lrucache = util.lrucachedict(cachesize) @@ -111,7 +109,7 @@ self._lastpack = None -class basepackstore(object): +class basepackstore: # Default cache size limit for the pack files. DEFAULTCACHESIZE = 100 @@ -269,7 +267,7 @@ return newpacks -class versionmixin(object): +class versionmixin: # Mix-in for classes with multiple supported versions VERSION = None SUPPORTED_VERSIONS = [2] @@ -528,7 +526,7 @@ self.idxfp.write(struct.pack(b'!BB', self.VERSION, config)) -class indexparams(object): +class indexparams: __slots__ = ( 'fanoutprefix', 'fanoutstruct',
--- a/hgext/remotefilelog/basestore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/basestore.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import errno import os import shutil @@ -21,7 +19,7 @@ ) -class basestore(object): +class basestore: def __init__(self, repo, path, reponame, shared=False): """Creates a remotefilelog store object for the given repo name. @@ -148,7 +146,7 @@ filenamemap = self._resolvefilenames(existing.keys()) - for filename, sha in pycompat.iteritems(filenamemap): + for filename, sha in filenamemap.items(): yield (filename, existing[sha]) def _resolvefilenames(self, hashes): @@ -414,7 +412,7 @@ ) -class baseunionstore(object): +class baseunionstore: def __init__(self, *args, **kwargs): # If one of the functions that iterates all of the stores is about to # throw a KeyError, try this many times with a full refresh between
--- a/hgext/remotefilelog/connectionpool.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/connectionpool.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,11 +5,9 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial import ( hg, - pycompat, sshpeer, util, ) @@ -17,7 +15,7 @@ _sshv1peer = sshpeer.sshv1peer -class connectionpool(object): +class connectionpool: def __init__(self, repo): self._repo = repo self._pool = dict() @@ -61,13 +59,13 @@ return conn def close(self): - for pathpool in pycompat.itervalues(self._pool): + for pathpool in self._pool.values(): for conn in pathpool: conn.close() del pathpool[:] -class connection(object): +class connection: def __init__(self, pool, peer): self._pool = pool self.peer = peer
--- a/hgext/remotefilelog/constants.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/constants.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import struct from mercurial.i18n import _
--- a/hgext/remotefilelog/contentstore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/contentstore.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import threading from mercurial.node import ( @@ -19,7 +17,7 @@ ) -class ChainIndicies(object): +class ChainIndicies: """A static class for easy reference to the delta chain indicies.""" # The filename of this revision delta @@ -231,7 +229,7 @@ self._threaddata.metacache = (node, meta) -class remotecontentstore(object): +class remotecontentstore: def __init__(self, ui, fileservice, shared): self._fileservice = fileservice # type(shared) is usually remotefilelogcontentstore @@ -276,7 +274,7 @@ pass -class manifestrevlogstore(object): +class manifestrevlogstore: def __init__(self, repo): self._store = repo.store self._svfs = repo.svfs
--- a/hgext/remotefilelog/datapack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/datapack.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import struct import zlib @@ -455,7 +453,7 @@ def createindex(self, nodelocations, indexoffset): entries = sorted( - (n, db, o, s) for n, (db, o, s) in pycompat.iteritems(self.entries) + (n, db, o, s) for n, (db, o, s) in self.entries.items() ) rawindex = b''
--- a/hgext/remotefilelog/debugcommands.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/debugcommands.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import zlib @@ -82,7 +81,7 @@ os.remove(temppath) r = filelog.filelog(repo.svfs, b'temprevlog') - class faket(object): + class faket: def add(self, a, b, c): pass @@ -211,7 +210,7 @@ continue filepath = os.path.join(root, file) size, firstnode, mapping = parsefileblob(filepath, decompress) - for p1, p2, linknode, copyfrom in pycompat.itervalues(mapping): + for p1, p2, linknode, copyfrom in mapping.values(): if linknode == sha1nodeconstants.nullid: actualpath = os.path.relpath(root, path) key = fileserverclient.getcachekey(
--- a/hgext/remotefilelog/fileserverclient.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/fileserverclient.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import io import os @@ -140,7 +139,7 @@ peer.__class__ = remotefilepeer -class cacheconnection(object): +class cacheconnection: """The connection for communicating with the remote cache. Performs gets and sets by communicating with an external process that has the cache-specific implementation. @@ -303,7 +302,7 @@ pipeo.flush() -class fileserverclient(object): +class fileserverclient: """A client for requesting files from the remote file server.""" def __init__(self, repo): @@ -518,7 +517,7 @@ # returns cache misses. This enables tests to run easily # and may eventually allow us to be a drop in replacement # for the largefiles extension. - class simplecache(object): + class simplecache: def __init__(self): self.missingids = [] self.connected = True
--- a/hgext/remotefilelog/historypack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/historypack.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import struct from mercurial.node import ( @@ -521,7 +519,7 @@ files = ( (hashutil.sha1(filename).digest(), filename, offset, size) - for filename, (offset, size) in pycompat.iteritems(self.files) + for filename, (offset, size) in self.files.items() ) files = sorted(files) @@ -557,7 +555,7 @@ ) nodeindexoffset += constants.FILENAMESIZE + len(filename) - for node, location in sorted(pycompat.iteritems(nodelocations)): + for node, location in sorted(nodelocations.items()): nodeindexentries.append( struct.pack(nodeindexformat, node, location) )
--- a/hgext/remotefilelog/metadatastore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/metadatastore.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from mercurial.node import ( hex, sha1nodeconstants, @@ -143,7 +141,7 @@ ) -class remotemetadatastore(object): +class remotemetadatastore: def __init__(self, ui, fileservice, shared): self._fileservice = fileservice self._shared = shared
--- a/hgext/remotefilelog/remotefilectx.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/remotefilectx.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import time
--- a/hgext/remotefilelog/remotefilelog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/remotefilelog.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import os @@ -16,7 +15,6 @@ ancestor, error, mdiff, - pycompat, revlog, ) from mercurial.utils import storageutil @@ -29,7 +27,7 @@ ) -class remotefilelognodemap(object): +class remotefilelognodemap: def __init__(self, filename, store): self._filename = filename self._store = store @@ -44,7 +42,7 @@ return node -class remotefilelog(object): +class remotefilelog: _generaldelta = True _flagserrorclass = error.RevlogError @@ -424,7 +422,7 @@ return self.repo.nullid revmap, parentfunc = self._buildrevgraph(a, b) - nodemap = {v: k for (k, v) in pycompat.iteritems(revmap)} + nodemap = {v: k for (k, v) in revmap.items()} ancs = ancestor.ancestors(parentfunc, revmap[a], revmap[b]) if ancs: @@ -439,7 +437,7 @@ return self.repo.nullid revmap, parentfunc = self._buildrevgraph(a, b) - nodemap = {v: k for (k, v) in pycompat.iteritems(revmap)} + nodemap = {v: k for (k, v) in revmap.items()} ancs = ancestor.commonancestorsheads(parentfunc, revmap[a], revmap[b]) return map(nodemap.__getitem__, ancs) @@ -455,7 +453,7 @@ parentsmap = collections.defaultdict(list) allparents = set() for mapping in (amap, bmap): - for node, pdata in pycompat.iteritems(mapping): + for node, pdata in mapping.items(): parents = parentsmap[node] p1, p2, linknode, copyfrom = pdata # Don't follow renames (copyfrom).
--- a/hgext/remotefilelog/remotefilelogserver.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/remotefilelogserver.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -22,7 +21,6 @@ error, extensions, match, - pycompat, scmutil, store, streamclone, @@ -95,7 +93,7 @@ b'x_rfl_getfile', b'file node', permission=b'pull' )(getfile) - class streamstate(object): + class streamstate: match = None shallowremote = False noflatmf = False @@ -417,7 +415,7 @@ cachepath = repo.vfs.join(b"remotefilelogcache") for head in heads: mf = repo[head].manifest() - for filename, filenode in pycompat.iteritems(mf): + for filename, filenode in mf.items(): filecachepath = os.path.join(cachepath, filename, hex(filenode)) neededfiles.add(filecachepath)
--- a/hgext/remotefilelog/repack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/repack.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import os import time @@ -489,18 +487,18 @@ if type(m) is dict: # m is a result of diff of two manifests and is a dictionary that # maps filename to ((newnode, newflag), (oldnode, oldflag)) tuple - for filename, diff in pycompat.iteritems(m): + for filename, diff in m.items(): if diff[0][0] is not None: keepkeys.add(keyfn(filename, diff[0][0])) else: # m is a manifest object - for filename, filenode in pycompat.iteritems(m): + for filename, filenode in m.items(): keepkeys.add(keyfn(filename, filenode)) return keepkeys -class repacker(object): +class repacker: """Class for orchestrating the repack of data and history information into a new format. """ @@ -596,7 +594,7 @@ maxchainlen = ui.configint(b'packs', b'maxchainlen', 1000) byfile = {} - for entry in pycompat.itervalues(ledger.entries): + for entry in ledger.entries.values(): if entry.datasource: byfile.setdefault(entry.filename, {})[entry.node] = entry @@ -604,7 +602,7 @@ repackprogress = ui.makeprogress( _(b"repacking data"), unit=self.unit, total=len(byfile) ) - for filename, entries in sorted(pycompat.iteritems(byfile)): + for filename, entries in sorted(byfile.items()): repackprogress.update(count) ancestors = {} @@ -751,14 +749,14 @@ ui = self.repo.ui byfile = {} - for entry in pycompat.itervalues(ledger.entries): + for entry in ledger.entries.values(): if entry.historysource: byfile.setdefault(entry.filename, {})[entry.node] = entry progress = ui.makeprogress( _(b"repacking history"), unit=self.unit, total=len(byfile) ) - for filename, entries in sorted(pycompat.iteritems(byfile)): + for filename, entries in sorted(byfile.items()): ancestors = {} nodes = list(node for node in entries) @@ -821,7 +819,7 @@ return sortednodes -class repackledger(object): +class repackledger: """Storage for all the bookkeeping that happens during a repack. It contains the list of revisions being repacked, what happened to each revision, and which source store contained which revision originally (for later cleanup). @@ -869,7 +867,7 @@ self.created.add(value) -class repackentry(object): +class repackentry: """Simple class representing a single revision entry in the repackledger.""" __slots__ = (
--- a/hgext/remotefilelog/shallowbundle.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/shallowbundle.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.i18n import _ from mercurial.node import bin, hex
--- a/hgext/remotefilelog/shallowrepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/shallowrepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os @@ -15,7 +14,6 @@ error, localrepo, match, - pycompat, scmutil, sparse, util, @@ -269,7 +267,7 @@ mfrevlog = mfl.getstorage(b'') if base is not None: mfdict = mfl[repo[base].manifestnode()].read() - skip = set(pycompat.iteritems(mfdict)) + skip = set(mfdict.items()) else: skip = set() @@ -299,7 +297,7 @@ else: mfdict = mfl[mfnode].read() - diff = pycompat.iteritems(mfdict) + diff = mfdict.items() if pats: diff = (pf for pf in diff if m(pf[0])) if sparsematch:
--- a/hgext/remotefilelog/shallowstore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/shallowstore.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import def wrapstore(store):
--- a/hgext/remotefilelog/shallowutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/shallowutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import errno @@ -103,7 +102,7 @@ """ result = collections.defaultdict(lambda: 0) for dict in dicts: - for k, v in pycompat.iteritems(dict): + for k, v in dict.items(): result[k] += v return result @@ -111,7 +110,7 @@ def prefixkeys(dict, prefix): """Returns ``dict`` with ``prefix`` prepended to all its keys.""" result = {} - for k, v in pycompat.iteritems(dict): + for k, v in dict.items(): result[prefix + k] = v return result @@ -160,7 +159,7 @@ length limit is exceeded """ metabuf = b'' - for k, v in sorted(pycompat.iteritems((metadict or {}))): + for k, v in sorted((metadict or {}).items()): if len(k) != 1: raise error.ProgrammingError(b'packmeta: illegal key: %s' % k) if len(v) > 0xFFFE: @@ -176,8 +175,8 @@ _metaitemtypes = { - constants.METAKEYFLAG: (int, pycompat.long), - constants.METAKEYSIZE: (int, pycompat.long), + constants.METAKEYFLAG: (int, int), + constants.METAKEYSIZE: (int, int), } @@ -188,7 +187,7 @@ and METAKEYFLAG will be dropped if its value is 0. """ newmeta = {} - for k, v in pycompat.iteritems(metadict or {}): + for k, v in (metadict or {}).items(): expectedtype = _metaitemtypes.get(k, (bytes,)) if not isinstance(v, expectedtype): raise error.ProgrammingError(b'packmeta: wrong type of key %s' % k) @@ -209,7 +208,7 @@ integers. """ metadict = _parsepackmeta(metabuf) - for k, v in pycompat.iteritems(metadict): + for k, v in metadict.items(): if k in _metaitemtypes and int in _metaitemtypes[k]: metadict[k] = bin2int(v) return metadict
--- a/hgext/remotefilelog/shallowverifier.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotefilelog/shallowverifier.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import verify
--- a/hgext/remotenames.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/remotenames.py Tue Apr 05 11:09:03 2022 +0200 @@ -24,7 +24,6 @@ namespace (default: 'default') """ -from __future__ import absolute_import from mercurial.i18n import _ @@ -171,13 +170,13 @@ if not self.loaded: self._load() - for k, vtup in pycompat.iteritems(self.potentialentries): + for k, vtup in self.potentialentries.items(): yield (k, [bin(vtup[0])]) items = iteritems -class remotenames(object): +class remotenames: """ This class encapsulates all the remotenames state. It also contains methods to access that state in convenient ways. Remotenames are lazy @@ -208,7 +207,7 @@ if not self._nodetobmarks: bmarktonodes = self.bmarktonodes() self._nodetobmarks = {} - for name, node in pycompat.iteritems(bmarktonodes): + for name, node in bmarktonodes.items(): self._nodetobmarks.setdefault(node[0], []).append(name) return self._nodetobmarks @@ -219,7 +218,7 @@ if not self._nodetobranch: branchtonodes = self.branchtonodes() self._nodetobranch = {} - for name, nodes in pycompat.iteritems(branchtonodes): + for name, nodes in branchtonodes.items(): for node in nodes: self._nodetobranch.setdefault(node, []).append(name) return self._nodetobranch @@ -229,7 +228,7 @@ marktonodes = self.bmarktonodes() self._hoisttonodes = {} hoist += b'/' - for name, node in pycompat.iteritems(marktonodes): + for name, node in marktonodes.items(): if name.startswith(hoist): name = name[len(hoist) :] self._hoisttonodes[name] = node @@ -240,7 +239,7 @@ marktonodes = self.bmarktonodes() self._nodetohoists = {} hoist += b'/' - for name, node in pycompat.iteritems(marktonodes): + for name, node in marktonodes.items(): if name.startswith(hoist): name = name[len(hoist) :] self._nodetohoists.setdefault(node[0], []).append(name)
--- a/hgext/schemes.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/schemes.py Tue Apr 05 11:09:03 2022 +0200 @@ -39,7 +39,6 @@ You can override a predefined scheme by defining a new scheme with the same name. """ -from __future__ import absolute_import import os import re @@ -68,7 +67,7 @@ _partre = re.compile(br'{(\d+)\}') -class ShortRepository(object): +class ShortRepository: def __init__(self, url, scheme, templater): self.scheme = scheme self.templater = templater
--- a/hgext/share.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/share.py Tue Apr 05 11:09:03 2022 +0200 @@ -65,7 +65,6 @@ and there are no untracked files, delete that share and create a new share. ''' -from __future__ import absolute_import import errno from mercurial.i18n import _
--- a/hgext/show.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/show.py Tue Apr 05 11:09:03 2022 +0200 @@ -25,7 +25,6 @@ performed. """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial.node import nullrev
--- a/hgext/sparse.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/sparse.py Tue Apr 05 11:09:03 2022 +0200 @@ -71,7 +71,6 @@ tools/tests/** """ -from __future__ import absolute_import from mercurial.i18n import _ from mercurial.pycompat import setattr
--- a/hgext/split.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/split.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. """command to split a changeset into smaller ones (EXPERIMENTAL)""" -from __future__ import absolute_import from mercurial.i18n import _
--- a/hgext/sqlitestore.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/sqlitestore.py Tue Apr 05 11:09:03 2022 +0200 @@ -43,7 +43,6 @@ # --extra-config-opt extensions.sqlitestore= \ # --extra-config-opt storage.new-repo-backend=sqlite -from __future__ import absolute_import import sqlite3 import struct @@ -265,7 +264,7 @@ @attr.s -class revisionentry(object): +class revisionentry: rid = attr.ib() rev = attr.ib() node = attr.ib() @@ -279,7 +278,7 @@ @interfaceutil.implementer(repository.irevisiondelta) @attr.s(slots=True) -class sqliterevisiondelta(object): +class sqliterevisiondelta: node = attr.ib() p1node = attr.ib() p2node = attr.ib() @@ -295,14 +294,14 @@ @interfaceutil.implementer(repository.iverifyproblem) @attr.s(frozen=True) -class sqliteproblem(object): +class sqliteproblem: warning = attr.ib(default=None) error = attr.ib(default=None) node = attr.ib(default=None) @interfaceutil.implementer(repository.ifilestorage) -class sqlitefilestore(object): +class sqlitefilestore: """Implements storage for an individual tracked path.""" def __init__(self, db, path, compression): @@ -1250,7 +1249,7 @@ @interfaceutil.implementer(repository.ilocalrepositoryfilestorage) -class sqlitefilestorage(object): +class sqlitefilestorage: """Repository file storage backed by SQLite.""" def file(self, path):
--- a/hgext/strip.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/strip.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ This extension allows you to strip changesets and all their descendants from the repository. See the command help for details. """ -from __future__ import absolute_import from mercurial import commands
--- a/hgext/transplant.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/transplant.py Tue Apr 05 11:09:03 2022 +0200 @@ -13,7 +13,6 @@ Transplanted patches are recorded in .hg/transplant/transplants, as a map from a changeset hash to its hash in the source repository. ''' -from __future__ import absolute_import import os @@ -76,13 +75,13 @@ ) -class transplantentry(object): +class transplantentry: def __init__(self, lnode, rnode): self.lnode = lnode self.rnode = rnode -class transplants(object): +class transplants: def __init__(self, path=None, transplantfile=None, opener=None): self.path = path self.transplantfile = transplantfile @@ -107,7 +106,7 @@ if not os.path.isdir(self.path): os.mkdir(self.path) fp = self.opener(self.transplantfile, b'w') - for list in pycompat.itervalues(self.transplants): + for list in self.transplants.values(): for t in list: l, r = map(hex, (t.lnode, t.rnode)) fp.write(l + b':' + r + b'\n') @@ -129,7 +128,7 @@ self.dirty = True -class transplanter(object): +class transplanter: def __init__(self, ui, repo, opts): self.ui = ui self.repo = repo
--- a/hgext/uncommit.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/uncommit.py Tue Apr 05 11:09:03 2022 +0200 @@ -17,7 +17,6 @@ added and removed in the working directory. """ -from __future__ import absolute_import from mercurial.i18n import _ @@ -81,9 +80,7 @@ files = initialfiles - exclude # Filter copies copied = copiesmod.pathcopies(base, ctx) - copied = { - dst: src for dst, src in pycompat.iteritems(copied) if dst in files - } + copied = {dst: src for dst, src in copied.items() if dst in files} def filectxfn(repo, memctx, path, contentctx=ctx, redirect=()): if path not in contentctx:
--- a/hgext/win32mbcs.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/win32mbcs.py Tue Apr 05 11:09:03 2022 +0200 @@ -44,7 +44,6 @@ It is useful for the users who want to commit with UTF-8 log message. ''' -from __future__ import absolute_import import os import sys @@ -95,7 +94,7 @@ def encode(arg): - if isinstance(arg, pycompat.unicode): + if isinstance(arg, str): return arg.encode(_encoding) elif isinstance(arg, tuple): return tuple(map(encode, arg)) @@ -136,7 +135,7 @@ def wrapper(func, args, kwds): - return basewrapper(func, pycompat.unicode, encode, decode, args, kwds) + return basewrapper(func, str, encode, decode, args, kwds) def reversewrapper(func, args, kwds):
--- a/hgext/win32text.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/win32text.py Tue Apr 05 11:09:03 2022 +0200 @@ -41,7 +41,6 @@ # or pretxnchangegroup.cr = python:hgext.win32text.forbidcr ''' -from __future__ import absolute_import import re from mercurial.i18n import _ @@ -213,7 +212,7 @@ def reposetup(ui, repo): if not repo.local(): return - for name, fn in pycompat.iteritems(_filters): + for name, fn in _filters.items(): repo.adddatafilter(name, fn)
--- a/hgext/zeroconf/Zeroconf.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/zeroconf/Zeroconf.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - """ Multicast DNS Service Discovery for Python, v0.12 Copyright (C) 2003, Paul Scott-Murphy @@ -233,7 +231,7 @@ # implementation classes -class DNSEntry(object): +class DNSEntry: """A DNS entry""" def __init__(self, name, type, clazz): @@ -508,7 +506,7 @@ return self.toString(b"%s:%s" % (self.server, self.port)) -class DNSIncoming(object): +class DNSIncoming: """Object representation of an incoming DNS packet""" def __init__(self, data): @@ -704,7 +702,7 @@ return result -class DNSOutgoing(object): +class DNSOutgoing: """Object representation of an outgoing packet""" def __init__(self, flags, multicast=1): @@ -866,7 +864,7 @@ return b''.join(self.data) -class DNSCache(object): +class DNSCache: """A cache of DNS entries""" def __init__(self): @@ -984,7 +982,7 @@ self.condition.release() -class Listener(object): +class Listener: """A Listener is used by this module to listen on the multicast group to which DNS messages are sent, allowing the implementation to cache information as it arrives. @@ -1129,7 +1127,7 @@ event(self.zeroconf) -class ServiceInfo(object): +class ServiceInfo: """Service information""" def __init__( @@ -1388,7 +1386,7 @@ return result -class Zeroconf(object): +class Zeroconf: """Implementation of Zeroconf Multicast DNS Service Discovery Supports registration, unregistration, queries and browsing.
--- a/hgext/zeroconf/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext/zeroconf/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -22,7 +22,6 @@ $ hg paths zc-test = http://example.com:8000/test ''' -from __future__ import absolute_import import os import socket @@ -159,7 +158,7 @@ # listen -class listener(object): +class listener: def __init__(self): self.found = {}
--- a/hgext3rd/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/hgext3rd/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ # name space package to host third party extensions -from __future__ import absolute_import import pkgutil __path__ = pkgutil.extend_path(__path__, __name__)
--- a/i18n/check-translation.py Tue Apr 05 10:55:28 2022 +0200 +++ b/i18n/check-translation.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ #!/usr/bin/env python3 # # check-translation.py - check Mercurial specific translation problems -from __future__ import absolute_import import re
--- a/i18n/hggettext Tue Apr 05 10:55:28 2022 +0200 +++ b/i18n/hggettext Tue Apr 05 11:09:03 2022 +0200 @@ -20,7 +20,6 @@ join the message cataloges to get the final catalog. """ -from __future__ import absolute_import, print_function import inspect import os
--- a/i18n/polib.py Tue Apr 05 10:55:28 2022 +0200 +++ b/i18n/polib.py Tue Apr 05 11:09:03 2022 +0200 @@ -13,7 +13,6 @@ :func:`~polib.mofile` convenience functions. """ -from __future__ import absolute_import __author__ = 'David Jean Louis <izimobil@gmail.com>' __version__ = '1.0.7' @@ -43,7 +42,7 @@ except ImportError: # replacement of io.open() for python < 2.6 # we use codecs instead - class io(object): + class io: @staticmethod def open(fpath, mode='r', encoding=None): return codecs.open(fpath, mode, encoding) @@ -817,7 +816,7 @@ # class _BaseEntry {{{ -class _BaseEntry(object): +class _BaseEntry: """ Base class for :class:`~polib.POEntry` and :class:`~polib.MOEntry` classes. This class should **not** be instanciated directly. @@ -1228,7 +1227,7 @@ # class _POFileParser {{{ -class _POFileParser(object): +class _POFileParser: """ A finite state machine to parse efficiently and correctly po file format. @@ -1707,7 +1706,7 @@ # class _MOFileParser {{{ -class _MOFileParser(object): +class _MOFileParser: """ A class to parse binary mo files. """
--- a/i18n/posplit Tue Apr 05 10:55:28 2022 +0200 +++ b/i18n/posplit Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # license: MIT/X11/Expat # -from __future__ import absolute_import, print_function import polib import re
--- a/mercurial/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import # Allow 'from mercurial import demandimport' to keep working. import hgdemandimport
--- a/mercurial/ancestor.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/ancestor.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import heapq @@ -147,7 +146,7 @@ return deepest(gca) -class incrementalmissingancestors(object): +class incrementalmissingancestors: """persistent state used to calculate missing ancestors incrementally Although similar in spirit to lazyancestors below, this is a separate class @@ -317,7 +316,7 @@ see(p2) -class lazyancestors(object): +class lazyancestors: def __init__(self, pfunc, revs, stoprev=0, inclusive=False): """Create a new object generating ancestors for the given revs. Does not generate revs lower than stoprev.
--- a/mercurial/archival.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/archival.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import gzip import os @@ -76,7 +75,7 @@ def guesskind(dest): - for kind, extensions in pycompat.iteritems(exts): + for kind, extensions in exts.items(): if any(dest.endswith(ext) for ext in extensions): return kind return None @@ -133,43 +132,10 @@ return out.getvalue() -class tarit(object): +class tarit: """write archive to tar file or stream. can write uncompressed, or compress with gzip or bzip2.""" - if pycompat.ispy3: - GzipFileWithTime = gzip.GzipFile # camelcase-required - else: - - class GzipFileWithTime(gzip.GzipFile): - def __init__(self, *args, **kw): - timestamp = None - if 'mtime' in kw: - timestamp = kw.pop('mtime') - if timestamp is None: - self.timestamp = time.time() - else: - self.timestamp = timestamp - gzip.GzipFile.__init__(self, *args, **kw) - - def _write_gzip_header(self): - self.fileobj.write(b'\037\213') # magic header - self.fileobj.write(b'\010') # compression method - fname = self.name - if fname and fname.endswith(b'.gz'): - fname = fname[:-3] - flags = 0 - if fname: - flags = gzip.FNAME # pytype: disable=module-attr - self.fileobj.write(pycompat.bytechr(flags)) - gzip.write32u( # pytype: disable=module-attr - self.fileobj, int(self.timestamp) - ) - self.fileobj.write(b'\002') - self.fileobj.write(b'\377') - if fname: - self.fileobj.write(fname + b'\000') - def __init__(self, dest, mtime, kind=b''): self.mtime = mtime self.fileobj = None @@ -179,7 +145,7 @@ mode = mode[0:1] if not fileobj: fileobj = open(name, mode + b'b') - gzfileobj = self.GzipFileWithTime( + gzfileobj = gzip.GzipFile( name, pycompat.sysstr(mode + b'b'), zlib.Z_BEST_COMPRESSION, @@ -227,7 +193,7 @@ self.fileobj.close() -class zipit(object): +class zipit: """write archive to zip file or stream. can write uncompressed, or compressed with deflate.""" @@ -274,7 +240,7 @@ self.z.close() -class fileit(object): +class fileit: '''write archive as files in directory.''' def __init__(self, name, mtime): @@ -339,9 +305,6 @@ subrepos tells whether to include subrepos. """ - if kind == b'txz' and not pycompat.ispy3: - raise error.Abort(_(b'xz compression is only available in Python 3')) - if kind == b'files': if prefix: raise error.Abort(_(b'cannot give prefix when archiving to files'))
--- a/mercurial/bookmarks.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/bookmarks.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import struct @@ -59,7 +58,7 @@ return fp -class bmstore(object): +class bmstore: r"""Storage for bookmarks. This object should do all bookmark-related reads and writes, so @@ -138,7 +137,7 @@ return iter(self._refmap) def iteritems(self): - return pycompat.iteritems(self._refmap) + return self._refmap.items() def items(self): return self._refmap.items() @@ -251,7 +250,7 @@ self._aclean = True def _write(self, fp): - for name, node in sorted(pycompat.iteritems(self._refmap)): + for name, node in sorted(self._refmap.items()): fp.write(b"%s %s\n" % (hex(node), encoding.fromlocal(name))) self._clean = True self._repo.invalidatevolatilesets() @@ -419,7 +418,7 @@ ) name = repo._activebookmark.split(b'@', 1)[0] heads = [] - for mark, n in pycompat.iteritems(repo._bookmarks): + for mark, n in repo._bookmarks.items(): if mark.split(b'@', 1)[0] == name: heads.append(n) return heads @@ -477,7 +476,7 @@ marks = getattr(repo, '_bookmarks', {}) hasnode = repo.changelog.hasnode - for k, v in pycompat.iteritems(marks): + for k, v in marks.items(): # don't expose local divergent bookmarks if hasnode(v) and not isdivergent(k): yield k, v @@ -688,7 +687,7 @@ remotemarks""" changed = [] localmarks = repo._bookmarks - for (b, id) in pycompat.iteritems(remotemarks): + for (b, id) in remotemarks.items(): if id != localmarks.get(b, None) and id in repo: changed.append((b, id, ui.debug, _(b"updating bookmark %s\n") % b)) for b in localmarks: @@ -1075,7 +1074,7 @@ hexfn = fm.hexfunc if len(bmarks) == 0 and fm.isplain(): ui.status(_(b"no bookmarks set\n")) - for bmark, (n, prefix, label) in sorted(pycompat.iteritems(bmarks)): + for bmark, (n, prefix, label) in sorted(bmarks.items()): fm.startitem() fm.context(repo=repo) if not ui.quiet:
--- a/mercurial/branchmap.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/branchmap.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import struct @@ -63,7 +62,7 @@ unpack_from = struct.unpack_from -class BranchMapCache(object): +class BranchMapCache: """mapping of filtered views of repo with their branchcache""" def __init__(self): @@ -120,7 +119,7 @@ clbranchinfo = cl.branchinfo rbheads = [] closed = set() - for bheads in pycompat.itervalues(remotebranchmap): + for bheads in remotebranchmap.values(): rbheads += bheads for h in bheads: r = clrev(h) @@ -170,7 +169,7 @@ return b'branch cache' -class branchcache(object): +class branchcache: """A dict like object that hold branches heads cache. This cache is used to avoid costly computations to determine all the @@ -271,7 +270,7 @@ return key in self._entries def iteritems(self): - for k, v in pycompat.iteritems(self._entries): + for k, v in self._entries.items(): self._verifybranch(k) yield k, v @@ -401,13 +400,13 @@ return heads def iterbranches(self): - for bn, heads in pycompat.iteritems(self): + for bn, heads in self.items(): yield (bn, heads) + self._branchtip(heads) def iterheads(self): """returns all the heads""" self._verifyall() - return pycompat.itervalues(self._entries) + return self._entries.values() def copy(self): """return an deep copy of the branchcache object""" @@ -435,7 +434,7 @@ cachekey.append(hex(self.filteredhash)) f.write(b" ".join(cachekey) + b'\n') nodecount = 0 - for label, nodes in sorted(pycompat.iteritems(self._entries)): + for label, nodes in sorted(self._entries.items()): label = encoding.fromlocal(label) for node in nodes: nodecount += 1 @@ -491,7 +490,7 @@ # Faster than using ctx.obsolete() obsrevs = obsolete.getrevs(repo, b'obsolete') - for branch, newheadrevs in pycompat.iteritems(newbranches): + for branch, newheadrevs in newbranches.items(): # For every branch, compute the new branchheads. # A branchhead is a revision such that no descendant is on # the same branch. @@ -632,7 +631,7 @@ _rbccloseflag = 0x80000000 -class revbranchcache(object): +class revbranchcache: """Persistent cache, mapping from revision number to branch name and close. This is a low level cache, independent of filtering.
--- a/mercurial/bundle2.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/bundle2.py Tue Apr 05 11:09:03 2022 +0200 @@ -145,7 +145,6 @@ preserve. """ -from __future__ import absolute_import, division import collections import errno @@ -252,7 +251,7 @@ return _decorator -class unbundlerecords(object): +class unbundlerecords: """keep record of what happens during and unbundle New records are added using `records.add('cat', obj)`. Where 'cat' is a @@ -300,7 +299,7 @@ __bool__ = __nonzero__ -class bundleoperation(object): +class bundleoperation: """an object that represents a single bundling process Its purpose is to carry unbundle-related objects and states. @@ -380,7 +379,7 @@ return op -class partiterator(object): +class partiterator: def __init__(self, repo, op, unbundler): self.repo = repo self.op = op @@ -627,7 +626,7 @@ bundlepriority = [b'HG10GZ', b'HG10BZ', b'HG10UN'] -class bundle20(object): +class bundle20: """represent an outgoing bundle2 container Use the `addparam` method to add stream level parameter. and `newpart` to @@ -751,7 +750,7 @@ return salvaged -class unpackermixin(object): +class unpackermixin: """A mixin to extract bytes and struct data from a stream""" def __init__(self, fp): @@ -984,7 +983,7 @@ unbundler._compressed = True -class bundlepart(object): +class bundlepart: """A bundle2 part contains application level payload The part `type` is used to route the part to the application level @@ -1274,7 +1273,7 @@ ) -class interruptoperation(object): +class interruptoperation: """A limited operation to be use by part handler during interruption It only have access to an ui object. @@ -2240,7 +2239,7 @@ b'remote repository changed while pushing - please try again ' b'(%s is %s expected %s)' ) - for expectedphase, nodes in pycompat.iteritems(phasetonodes): + for expectedphase, nodes in phasetonodes.items(): for n in nodes: actualphase = phasecache.phase(unfi, cl.rev(n)) if actualphase != expectedphase:
--- a/mercurial/bundlecaches.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/bundlecaches.py Tue Apr 05 11:09:03 2022 +0200 @@ -21,7 +21,7 @@ @attr.s -class bundlespec(object): +class bundlespec: compression = attr.ib() wirecompression = attr.ib() version = attr.ib() @@ -343,7 +343,7 @@ return newentries -class clonebundleentry(object): +class clonebundleentry: """Represents an item in a clone bundles manifest. This rich class is needed to support sorting since sorted() in Python 3
--- a/mercurial/bundlerepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/bundlerepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ were part of the actual repository. """ -from __future__ import absolute_import import os import shutil @@ -271,7 +270,7 @@ return filespos -class bundlerepository(object): +class bundlerepository: """A repository instance that is a union of a local repo and a bundle. Instances represent a read-only repository composed of a local repository @@ -551,7 +550,7 @@ return repo -class bundletransactionmanager(object): +class bundletransactionmanager: def transaction(self): return None
--- a/mercurial/cacheutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cacheutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from . import repoview
--- a/mercurial/cext/base85.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/base85.c Tue Apr 05 11:09:03 2022 +0200 @@ -38,7 +38,7 @@ unsigned int acc, val, ch; int pad = 0; - if (!PyArg_ParseTuple(args, PY23("s#|i", "y#|i"), &text, &len, &pad)) { + if (!PyArg_ParseTuple(args, "y#|i", &text, &len, &pad)) { return NULL; } @@ -90,7 +90,7 @@ int c; unsigned int acc; - if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &len)) { + if (!PyArg_ParseTuple(args, "y#", &text, &len)) { return NULL; } @@ -177,7 +177,6 @@ static const int version = 1; -#ifdef IS_PY3K static struct PyModuleDef base85_module = { PyModuleDef_HEAD_INIT, "base85", base85_doc, -1, methods, }; @@ -191,13 +190,3 @@ PyModule_AddIntConstant(m, "version", version); return m; } -#else -PyMODINIT_FUNC initbase85(void) -{ - PyObject *m; - m = Py_InitModule3("base85", methods, base85_doc); - - b85prep(); - PyModule_AddIntConstant(m, "version", version); -} -#endif
--- a/mercurial/cext/bdiff.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/bdiff.c Tue Apr 05 11:09:03 2022 +0200 @@ -76,8 +76,7 @@ l.next = NULL; - if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, - &bb)) { + if (!PyArg_ParseTuple(args, "y*y*:bdiff", &ba, &bb)) { return NULL; } @@ -233,7 +232,7 @@ Py_ssize_t nelts = 0, size, i, start = 0; PyObject *result = NULL; - if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &size)) { + if (!PyArg_ParseTuple(args, "y#", &text, &size)) { goto abort; } if (!size) { @@ -299,8 +298,7 @@ NULL, /* priv */ }; - if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr, - &lb)) { + if (!PyArg_ParseTuple(args, "y#y#", &a.ptr, &la, &b.ptr, &lb)) { return NULL; } @@ -337,7 +335,6 @@ static const int version = 3; -#ifdef IS_PY3K static struct PyModuleDef bdiff_module = { PyModuleDef_HEAD_INIT, "bdiff", mdiff_doc, -1, methods, }; @@ -349,11 +346,3 @@ PyModule_AddIntConstant(m, "version", version); return m; } -#else -PyMODINIT_FUNC initbdiff(void) -{ - PyObject *m; - m = Py_InitModule3("bdiff", methods, mdiff_doc); - PyModule_AddIntConstant(m, "version", version); -} -#endif
--- a/mercurial/cext/charencode.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/charencode.c Tue Apr 05 11:09:03 2022 +0200 @@ -15,14 +15,6 @@ #include "compat.h" #include "util.h" -#ifdef IS_PY3K -/* The mapping of Python types is meant to be temporary to get Python - * 3 to compile. We should remove this once Python 3 support is fully - * supported and proper types are used in the extensions themselves. */ -#define PyInt_Type PyLong_Type -#define PyInt_AS_LONG PyLong_AS_LONG -#endif - /* clang-format off */ static const char lowertable[128] = { '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', @@ -133,8 +125,7 @@ { const char *buf; Py_ssize_t i, len; - if (!PyArg_ParseTuple(args, PY23("s#:isasciistr", "y#:isasciistr"), - &buf, &len)) { + if (!PyArg_ParseTuple(args, "y#:isasciistr", &buf, &len)) { return NULL; } i = 0; @@ -228,12 +219,12 @@ const char *table; if (!PyArg_ParseTuple(args, "O!O!O!:make_file_foldmap", &PyDict_Type, - &dmap, &PyInt_Type, &spec_obj, &PyFunction_Type, + &dmap, &PyLong_Type, &spec_obj, &PyFunction_Type, &normcase_fallback)) { goto quit; } - spec = (int)PyInt_AS_LONG(spec_obj); + spec = (int)PyLong_AS_LONG(spec_obj); switch (spec) { case NORMCASE_LOWER: table = lowertable;
--- a/mercurial/cext/dirs.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/dirs.c Tue Apr 05 11:09:03 2022 +0200 @@ -13,11 +13,7 @@ #include "util.h" -#ifdef IS_PY3K #define PYLONG_VALUE(o) ((PyLongObject *)o)->ob_digit[0] -#else -#define PYLONG_VALUE(o) PyInt_AS_LONG(o) -#endif /* * This is a multiset of directory names, built from the files that @@ -100,11 +96,7 @@ } /* Force Python to not reuse a small shared int. */ -#ifdef IS_PY3K val = PyLong_FromLong(0x1eadbeef); -#else - val = PyInt_FromLong(0x1eadbeef); -#endif if (val == NULL) goto bail;
--- a/mercurial/cext/manifest.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/manifest.c Tue Apr 05 11:09:03 2022 +0200 @@ -317,12 +317,7 @@ return ret; } -#ifdef IS_PY3K #define LAZYMANIFESTENTRIESITERATOR_TPFLAGS Py_TPFLAGS_DEFAULT -#else -#define LAZYMANIFESTENTRIESITERATOR_TPFLAGS Py_TPFLAGS_DEFAULT \ - | Py_TPFLAGS_HAVE_ITER -#endif static PyTypeObject lazymanifestEntriesIterator = { PyVarObject_HEAD_INIT(NULL, 0) /* header */ @@ -365,12 +360,7 @@ return PyBytes_FromStringAndSize(l->start, pl); } -#ifdef IS_PY3K #define LAZYMANIFESTKEYSITERATOR_TPFLAGS Py_TPFLAGS_DEFAULT -#else -#define LAZYMANIFESTKEYSITERATOR_TPFLAGS Py_TPFLAGS_DEFAULT \ - | Py_TPFLAGS_HAVE_ITER -#endif static PyTypeObject lazymanifestKeysIterator = { PyVarObject_HEAD_INIT(NULL, 0) /* header */ @@ -790,7 +780,7 @@ Py_INCREF(copy->pydata); for (i = 0; i < self->numlines; i++) { PyObject *arglist = NULL, *result = NULL; - arglist = Py_BuildValue(PY23("(s)", "(y)"), + arglist = Py_BuildValue("(y)", self->lines[i].start); if (!arglist) { goto bail; @@ -955,11 +945,7 @@ {NULL}, }; -#ifdef IS_PY3K #define LAZYMANIFEST_TPFLAGS Py_TPFLAGS_DEFAULT -#else -#define LAZYMANIFEST_TPFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_SEQUENCE_IN -#endif static PyTypeObject lazymanifestType = { PyVarObject_HEAD_INIT(NULL, 0) /* header */
--- a/mercurial/cext/mpatch.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/mpatch.c Tue Apr 05 11:09:03 2022 +0200 @@ -144,8 +144,7 @@ Py_ssize_t patchlen; char *bin; - if (!PyArg_ParseTuple(args, PY23("ls#", "ly#"), &orig, &bin, - &patchlen)) { + if (!PyArg_ParseTuple(args, "ly#", &orig, &bin, &patchlen)) { return NULL; } @@ -182,7 +181,6 @@ static const int version = 1; -#ifdef IS_PY3K static struct PyModuleDef mpatch_module = { PyModuleDef_HEAD_INIT, "mpatch", mpatch_doc, -1, methods, }; @@ -203,13 +201,3 @@ return m; } -#else -PyMODINIT_FUNC initmpatch(void) -{ - PyObject *m; - m = Py_InitModule3("mpatch", methods, mpatch_doc); - mpatch_Error = - PyErr_NewException("mercurial.cext.mpatch.mpatchError", NULL, NULL); - PyModule_AddIntConstant(m, "version", version); -} -#endif
--- a/mercurial/cext/osutil.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/osutil.c Tue Apr 05 11:09:03 2022 +0200 @@ -73,19 +73,11 @@ }; #endif -#ifdef IS_PY3K #define listdir_slot(name) \ static PyObject *listdir_stat_##name(PyObject *self, void *x) \ { \ return PyLong_FromLong(((struct listdir_stat *)self)->st.name); \ } -#else -#define listdir_slot(name) \ - static PyObject *listdir_stat_##name(PyObject *self, void *x) \ - { \ - return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \ - } -#endif listdir_slot(st_dev) listdir_slot(st_mode) @@ -206,7 +198,7 @@ ? _S_IFDIR : _S_IFREG; if (!wantstat) - return Py_BuildValue(PY23("si", "yi"), fd->cFileName, kind); + return Py_BuildValue("yi", fd->cFileName, kind); py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL); if (!py_st) @@ -224,7 +216,7 @@ if (kind == _S_IFREG) stp->st_size = ((__int64)fd->nFileSizeHigh << 32) + fd->nFileSizeLow; - return Py_BuildValue(PY23("siN", "yiN"), fd->cFileName, + return Py_BuildValue("yiN", fd->cFileName, kind, py_st); } @@ -412,10 +404,10 @@ PyObject *stat = makestat(&st); if (!stat) goto error; - elem = Py_BuildValue(PY23("siN", "yiN"), ent->d_name, + elem = Py_BuildValue("yiN", ent->d_name, kind, stat); } else - elem = Py_BuildValue(PY23("si", "yi"), ent->d_name, + elem = Py_BuildValue("yi", ent->d_name, kind); if (!elem) goto error; @@ -593,10 +585,10 @@ stat = makestat(&st); if (!stat) goto error; - elem = Py_BuildValue(PY23("siN", "yiN"), + elem = Py_BuildValue("yiN", filename, kind, stat); } else - elem = Py_BuildValue(PY23("si", "yi"), + elem = Py_BuildValue("yi", filename, kind); if (!elem) goto error; @@ -767,10 +759,6 @@ #if defined(HAVE_SETPROCTITLE) /* setproctitle is the first choice - available in FreeBSD */ #define SETPROCNAME_USE_SETPROCTITLE -#elif (defined(__linux__) || defined(__APPLE__)) && PY_MAJOR_VERSION == 2 -/* rewrite the argv buffer in place - works in Linux and OS X. Py_GetArgcArgv - * in Python 3 returns the copied wchar_t **argv, thus unsupported. */ -#define SETPROCNAME_USE_ARGVREWRITE #else #define SETPROCNAME_USE_NONE #endif @@ -780,49 +768,11 @@ static PyObject *setprocname(PyObject *self, PyObject *args) { const char *name = NULL; - if (!PyArg_ParseTuple(args, PY23("s", "y"), &name)) + if (!PyArg_ParseTuple(args, "y", &name)) return NULL; #if defined(SETPROCNAME_USE_SETPROCTITLE) setproctitle("%s", name); -#elif defined(SETPROCNAME_USE_ARGVREWRITE) - { - static char *argvstart = NULL; - static size_t argvsize = 0; - if (argvstart == NULL) { - int argc = 0, i; - char **argv = NULL; - char *argvend; - extern void Py_GetArgcArgv(int *argc, char ***argv); - Py_GetArgcArgv(&argc, &argv); - /* Py_GetArgcArgv may not do much if a custom python - * launcher is used that doesn't record the information - * it needs. Let's handle this gracefully instead of - * segfaulting. */ - if (argv != NULL) - argvend = argvstart = argv[0]; - else - argvend = argvstart = NULL; - - /* Check the memory we can use. Typically, argv[i] and - * argv[i + 1] are continuous. */ - for (i = 0; i < argc; ++i) { - size_t len; - if (argv[i] > argvend || argv[i] < argvstart) - break; /* not continuous */ - len = strlen(argv[i]); - argvend = argv[i] + len + 1 /* '\0' */; - } - if (argvend > argvstart) /* sanity check */ - argvsize = argvend - argvstart; - } - - if (argvstart && argvsize > 1) { - int n = snprintf(argvstart, argvsize, "%s", name); - if (n >= 0 && (size_t)n < argvsize) - memset(argvstart + n, 0, argvsize - n); - } - } #endif Py_RETURN_NONE; @@ -1135,14 +1085,14 @@ const char *path = NULL; struct statfs buf; int r; - if (!PyArg_ParseTuple(args, PY23("s", "y"), &path)) + if (!PyArg_ParseTuple(args, "y", &path)) return NULL; memset(&buf, 0, sizeof(buf)); r = statfs(path, &buf); if (r != 0) return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue(PY23("s", "y"), describefstype(&buf)); + return Py_BuildValue("y", describefstype(&buf)); } #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */ @@ -1153,14 +1103,14 @@ const char *path = NULL; struct statfs buf; int r; - if (!PyArg_ParseTuple(args, PY23("s", "y"), &path)) + if (!PyArg_ParseTuple(args, "y", &path)) return NULL; memset(&buf, 0, sizeof(buf)); r = statfs(path, &buf); if (r != 0) return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue(PY23("s", "y"), buf.f_mntonname); + return Py_BuildValue("y", buf.f_mntonname); } #endif /* defined(HAVE_BSD_STATFS) */ @@ -1195,8 +1145,7 @@ static char *kwlist[] = {"path", "stat", "skip", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, PY23("s#|OO:listdir", - "y#|OO:listdir"), + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y#|OO:listdir", kwlist, &path, &plen, &statobj, &skipobj)) return NULL; @@ -1227,12 +1176,8 @@ char fpmode[4]; int fppos = 0; int plus; -#ifndef IS_PY3K - FILE *fp; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwds, PY23("et|si:posixfile", - "et|yi:posixfile"), + if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|yi:posixfile", kwlist, Py_FileSystemDefaultEncoding, &name, &mode, &bufsize)) @@ -1302,26 +1247,9 @@ PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); goto bail; } -#ifndef IS_PY3K - fp = _fdopen(fd, fpmode); - if (fp == NULL) { - _close(fd); - PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); - goto bail; - } - - file_obj = PyFile_FromFile(fp, name, mode, fclose); - if (file_obj == NULL) { - fclose(fp); - goto bail; - } - - PyFile_SetBufSize(file_obj, bufsize); -#else file_obj = PyFile_FromFd(fd, name, mode, bufsize, NULL, NULL, NULL, 1); if (file_obj == NULL) goto bail; -#endif bail: PyMem_Free(name); return file_obj; @@ -1387,7 +1315,6 @@ static const int version = 4; -#ifdef IS_PY3K static struct PyModuleDef osutil_module = { PyModuleDef_HEAD_INIT, "osutil", @@ -1406,14 +1333,3 @@ PyModule_AddIntConstant(m, "version", version); return m; } -#else -PyMODINIT_FUNC initosutil(void) -{ - PyObject *m; - if (PyType_Ready(&listdir_stat_type) == -1) - return; - - m = Py_InitModule3("osutil", methods, osutil_doc); - PyModule_AddIntConstant(m, "version", version); -} -#endif
--- a/mercurial/cext/parsers.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/parsers.c Tue Apr 05 11:09:03 2022 +0200 @@ -17,22 +17,6 @@ #include "charencode.h" #include "util.h" -#ifdef IS_PY3K -/* The mapping of Python types is meant to be temporary to get Python - * 3 to compile. We should remove this once Python 3 support is fully - * supported and proper types are used in the extensions themselves. */ -#define PyInt_Check PyLong_Check -#define PyInt_FromLong PyLong_FromLong -#define PyInt_FromSsize_t PyLong_FromSsize_t -#define PyInt_AsLong PyLong_AsLong -#else -/* Windows on Python 2.7 doesn't define S_IFLNK. Python 3+ defines via - * pyport.h. */ -#ifndef S_IFLNK -#define S_IFLNK 0120000 -#endif -#endif - static const char *const versionerrortext = "Python minor version mismatch"; static const int dirstate_v1_from_p2 = -2; @@ -313,17 +297,17 @@ static PyObject *dirstate_item_v1_mode(dirstateItemObject *self) { - return PyInt_FromLong(dirstate_item_c_v1_mode(self)); + return PyLong_FromLong(dirstate_item_c_v1_mode(self)); }; static PyObject *dirstate_item_v1_size(dirstateItemObject *self) { - return PyInt_FromLong(dirstate_item_c_v1_size(self)); + return PyLong_FromLong(dirstate_item_c_v1_size(self)); }; static PyObject *dirstate_item_v1_mtime(dirstateItemObject *self) { - return PyInt_FromLong(dirstate_item_c_v1_mtime(self)); + return PyLong_FromLong(dirstate_item_c_v1_mtime(self)); }; static PyObject *dirstate_item_mtime_likely_equal_to(dirstateItemObject *self, @@ -571,17 +555,17 @@ static PyObject *dirstate_item_get_mode(dirstateItemObject *self) { - return PyInt_FromLong(dirstate_item_c_v1_mode(self)); + return PyLong_FromLong(dirstate_item_c_v1_mode(self)); }; static PyObject *dirstate_item_get_size(dirstateItemObject *self) { - return PyInt_FromLong(dirstate_item_c_v1_size(self)); + return PyLong_FromLong(dirstate_item_c_v1_size(self)); }; static PyObject *dirstate_item_get_mtime(dirstateItemObject *self) { - return PyInt_FromLong(dirstate_item_c_v1_mtime(self)); + return PyLong_FromLong(dirstate_item_c_v1_mtime(self)); }; static PyObject *dirstate_item_get_state(dirstateItemObject *self) @@ -831,9 +815,8 @@ Py_ssize_t len = 40; Py_ssize_t readlen; - if (!PyArg_ParseTuple( - args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"), - &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen)) { + if (!PyArg_ParseTuple(args, "O!O!y#:parse_dirstate", &PyDict_Type, + &dmap, &PyDict_Type, &cmap, &str, &readlen)) { goto quit; } @@ -846,8 +829,8 @@ goto quit; } - parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, (Py_ssize_t)20, - str + 20, (Py_ssize_t)20); + parents = Py_BuildValue("y#y#", str, (Py_ssize_t)20, str + 20, + (Py_ssize_t)20); if (!parents) { goto quit; } @@ -1176,8 +1159,7 @@ Py_ssize_t datalen, offset, stop; PyObject *markers = NULL; - if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen, - &offset, &stop)) { + if (!PyArg_ParseTuple(args, "y#nn", &data, &datalen, &offset, &stop)) { return NULL; } if (offset < 0) { @@ -1289,7 +1271,7 @@ if (!ver) { return -1; } - hexversion = PyInt_AsLong(ver); + hexversion = PyLong_AsLong(ver); Py_DECREF(ver); /* sys.hexversion is a 32-bit number by default, so the -1 case * should only occur in unusual circumstances (e.g. if sys.hexversion @@ -1309,7 +1291,6 @@ return 0; } -#ifdef IS_PY3K static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers", parsers_doc, -1, methods}; @@ -1323,15 +1304,3 @@ module_init(mod); return mod; } -#else -PyMODINIT_FUNC initparsers(void) -{ - PyObject *mod; - - if (check_python_version() == -1) { - return; - } - mod = Py_InitModule3("parsers", methods, parsers_doc); - module_init(mod); -} -#endif
--- a/mercurial/cext/pathencode.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/pathencode.c Tue Apr 05 11:09:03 2022 +0200 @@ -535,8 +535,7 @@ Py_ssize_t len, newlen; PyObject *ret; - if (!PyArg_ParseTuple(args, PY23("s#:lowerencode", "y#:lowerencode"), - &path, &len)) { + if (!PyArg_ParseTuple(args, "y#:lowerencode", &path, &len)) { return NULL; } @@ -711,7 +710,7 @@ } } - shaobj = PyObject_CallFunction(shafunc, PY23("s#", "y#"), str, len); + shaobj = PyObject_CallFunction(shafunc, "y#", str, len); if (shaobj == NULL) { return -1;
--- a/mercurial/cext/revlog.c Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/revlog.c Tue Apr 05 11:09:03 2022 +0200 @@ -23,16 +23,6 @@ #include "revlog.h" #include "util.h" -#ifdef IS_PY3K -/* The mapping of Python types is meant to be temporary to get Python - * 3 to compile. We should remove this once Python 3 support is fully - * supported and proper types are used in the extensions themselves. */ -#define PyInt_Check PyLong_Check -#define PyInt_FromLong PyLong_FromLong -#define PyInt_FromSsize_t PyLong_FromSsize_t -#define PyInt_AsLong PyLong_AsLong -#endif - typedef struct indexObjectStruct indexObject; typedef struct { @@ -43,6 +33,7 @@ int abi_version; Py_ssize_t (*index_length)(const indexObject *); const char *(*index_node)(indexObject *, Py_ssize_t); + int (*fast_rank)(indexObject *, Py_ssize_t); int (*index_parents)(PyObject *, int, int *); } Revlog_CAPI; @@ -119,11 +110,9 @@ static int index_find_node(indexObject *self, const char *node); #if LONG_MAX == 0x7fffffffL -static const char *const tuple_format = - PY23("Kiiiiiis#KiBBi", "Kiiiiiiy#KiBBi"); +static const char *const tuple_format = "Kiiiiiiy#KiBBi"; #else -static const char *const tuple_format = - PY23("kiiiiiis#kiBBi", "kiiiiiiy#kiBBi"); +static const char *const tuple_format = "kiiiiiiy#kiBBi"; #endif /* A RevlogNG v1 index entry is 64 bytes long. */ @@ -576,6 +565,33 @@ } /* + * Return the stored rank of a given revision if known, or rank_unknown + * otherwise. + * + * The rank of a revision is the size of the sub-graph it defines as a head. + * Equivalently, the rank of a revision `r` is the size of the set + * `ancestors(r)`, `r` included. + * + * This method returns the rank retrieved from the revlog in constant time. It + * makes no attempt at computing unknown values for versions of the revlog + * which do not persist the rank. + */ +static int index_fast_rank(indexObject *self, Py_ssize_t pos) +{ + Py_ssize_t length = index_length(self); + + if (self->format_version != format_cl2 || pos >= length) { + return rank_unknown; + } + + if (pos == nullrev) { + return 0; /* convention */ + } + + return getbe32(index_deref(self, pos) + entry_cl2_offset_rank); +} + +/* * Return the hash of the node corresponding to the given rev. The * rev is assumed to be existing. If not, an exception is set. */ @@ -730,9 +746,9 @@ char comp_mode; char *data; #if LONG_MAX == 0x7fffffffL - const char *const sidedata_format = PY23("nKiKB", "nKiKB"); + const char *const sidedata_format = "nKiKB"; #else - const char *const sidedata_format = PY23("nkikB", "nkikB"); + const char *const sidedata_format = "nkikB"; #endif if (self->entry_size == v1_entry_size || self->inlined) { @@ -802,7 +818,7 @@ #define istat(__n, __d) \ do { \ s = PyBytes_FromString(__d); \ - t = PyInt_FromSsize_t(self->__n); \ + t = PyLong_FromSsize_t(self->__n); \ if (!s || !t) \ goto bail; \ if (PyDict_SetItem(obj, s, t) == -1) \ @@ -953,7 +969,7 @@ l = PyList_GET_SIZE(roots); for (i = 0; i < l; i++) { - revnum = PyInt_AsLong(PyList_GET_ITEM(roots, i)); + revnum = PyLong_AsLong(PyList_GET_ITEM(roots, i)); if (revnum == -1 && PyErr_Occurred()) goto bail; /* If root is out of range, e.g. wdir(), it must be unreachable @@ -966,7 +982,7 @@ /* Populate tovisit with all the heads */ l = PyList_GET_SIZE(heads); for (i = 0; i < l; i++) { - revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i)); + revnum = PyLong_AsLong(PyList_GET_ITEM(heads, i)); if (revnum == -1 && PyErr_Occurred()) goto bail; if (revnum + 1 < 0 || revnum + 1 >= len + 1) { @@ -986,7 +1002,7 @@ revnum = tovisit[k++]; if (revstates[revnum + 1] & RS_ROOT) { revstates[revnum + 1] |= RS_REACHABLE; - val = PyInt_FromLong(revnum); + val = PyLong_FromLong(revnum); if (val == NULL) goto bail; r = PyList_Append(reachable, val); @@ -1031,7 +1047,7 @@ RS_REACHABLE) && !(revstates[i + 1] & RS_REACHABLE)) { revstates[i + 1] |= RS_REACHABLE; - val = PyInt_FromSsize_t(i); + val = PyLong_FromSsize_t(i); if (val == NULL) goto bail; r = PyList_Append(reachable, val); @@ -1116,7 +1132,7 @@ } for (i = 0; i < numphases; ++i) { - PyObject *pyphase = PyInt_FromLong(trackedphases[i]); + PyObject *pyphase = PyLong_FromLong(trackedphases[i]); PyObject *phaseroots = NULL; if (pyphase == NULL) goto release; @@ -1175,7 +1191,7 @@ "bad phase number in internal list"); goto release; } - pyrev = PyInt_FromLong(rev); + pyrev = PyLong_FromLong(rev); if (pyrev == NULL) goto release; if (PySet_Add(pyphase, pyrev) == -1) { @@ -1189,7 +1205,7 @@ if (phasesetsdict == NULL) goto release; for (i = 0; i < numphases; ++i) { - PyObject *pyphase = PyInt_FromLong(trackedphases[i]); + PyObject *pyphase = PyLong_FromLong(trackedphases[i]); if (pyphase == NULL) goto release; if (PyDict_SetItem(phasesetsdict, pyphase, phasesets[i]) == @@ -1247,7 +1263,7 @@ if (heads == NULL) goto bail; if (len == 0) { - PyObject *nullid = PyInt_FromLong(-1); + PyObject *nullid = PyLong_FromLong(-1); if (nullid == NULL || PyList_Append(heads, nullid) == -1) { Py_XDECREF(nullid); goto bail; @@ -1296,7 +1312,7 @@ if (nothead[i]) continue; - head = PyInt_FromSsize_t(i); + head = PyLong_FromSsize_t(i); if (head == NULL || PyList_Append(heads, head) == -1) { Py_XDECREF(head); goto bail; @@ -1442,7 +1458,7 @@ assert(PyErr_Occurred()); goto bail; } - key = PyInt_FromSsize_t(base); + key = PyLong_FromSsize_t(base); allvalues = PyDict_GetItem(cache, key); if (allvalues == NULL && PyErr_Occurred()) { goto bail; @@ -1459,7 +1475,7 @@ goto bail; } } - value = PyInt_FromSsize_t(rev); + value = PyLong_FromSsize_t(rev); if (PyList_Append(allvalues, value)) { goto bail; } @@ -1486,8 +1502,8 @@ return NULL; } - if (PyInt_Check(stoparg)) { - stoprev = (int)PyInt_AsLong(stoparg); + if (PyLong_Check(stoparg)) { + stoprev = (int)PyLong_AsLong(stoparg); if (stoprev == -1 && PyErr_Occurred()) { return NULL; } @@ -1521,7 +1537,7 @@ iterrev = rev; while (iterrev != baserev && iterrev != stoprev) { - PyObject *value = PyInt_FromLong(iterrev); + PyObject *value = PyLong_FromLong(iterrev); if (value == NULL) { goto bail; } @@ -1560,7 +1576,7 @@ if (iterrev == stoprev) { stopped = 1; } else { - PyObject *value = PyInt_FromLong(iterrev); + PyObject *value = PyLong_FromLong(iterrev); if (value == NULL) { goto bail; } @@ -1712,7 +1728,8 @@ goto bail; } for (i = 0; i < num_revs; i++) { - Py_ssize_t revnum = PyInt_AsLong(PyList_GET_ITEM(list_revs, i)); + Py_ssize_t revnum = + PyLong_AsLong(PyList_GET_ITEM(list_revs, i)); if (revnum == -1 && PyErr_Occurred()) { goto bail; } @@ -2118,7 +2135,7 @@ raise_revlog_error(); return NULL; } - return PyInt_FromLong(length); + return PyLong_FromLong(length); } static void nt_dealloc(nodetree *self) @@ -2266,7 +2283,7 @@ char *node; int rev; - if (PyInt_Check(value)) { + if (PyLong_Check(value)) { long idx; if (!pylong_to_long(value, &idx)) { return NULL; @@ -2278,7 +2295,7 @@ return NULL; rev = index_find_node(self, node); if (rev >= -1) - return PyInt_FromLong(rev); + return PyLong_FromLong(rev); if (rev == -2) raise_revlog_error(); return NULL; @@ -2310,7 +2327,7 @@ char *node; int rev, i; - if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &node, &nodelen)) + if (!PyArg_ParseTuple(args, "y#", &node, &nodelen)) return NULL; if (nodelen < 1) { @@ -2377,7 +2394,7 @@ raise_revlog_error(); return NULL; } - return PyInt_FromLong(length); + return PyLong_FromLong(length); } static PyObject *index_m_get(indexObject *self, PyObject *args) @@ -2395,14 +2412,14 @@ return NULL; if (rev == -2) Py_RETURN_NONE; - return PyInt_FromLong(rev); + return PyLong_FromLong(rev); } static int index_contains(indexObject *self, PyObject *value) { char *node; - if (PyInt_Check(value)) { + if (PyLong_Check(value)) { long rev; if (!pylong_to_long(value, &rev)) { return -1; @@ -2440,7 +2457,7 @@ return NULL; rev = index_find_node(self, node); if (rev >= -1) - return PyInt_FromLong(rev); + return PyLong_FromLong(rev); if (rev == -2) raise_revlog_error(); return NULL; @@ -2493,7 +2510,7 @@ if (sv < poison) { interesting -= 1; if (sv == allseen) { - PyObject *obj = PyInt_FromLong(v); + PyObject *obj = PyLong_FromLong(v); if (obj == NULL) goto bail; if (PyList_Append(gca, obj) == -1) { @@ -2561,7 +2578,7 @@ } for (i = 0; i < revcount; i++) { - int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i)); + int n = (int)PyLong_AsLong(PyList_GET_ITEM(revs, i)); if (n > maxrev) maxrev = n; } @@ -2586,7 +2603,7 @@ goto bail; for (i = 0; i < revcount; i++) { - int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i)); + int n = (int)PyLong_AsLong(PyList_GET_ITEM(revs, i)); long b = 1l << i; depth[n] = 1; seen[n] = b; @@ -2716,13 +2733,13 @@ bitmask x; long val; - if (!PyInt_Check(obj)) { + if (!PyLong_Check(obj)) { PyErr_SetString(PyExc_TypeError, "arguments must all be ints"); Py_DECREF(obj); goto bail; } - val = PyInt_AsLong(obj); + val = PyLong_AsLong(obj); Py_DECREF(obj); if (val == -1) { ret = PyList_New(0); @@ -2763,7 +2780,7 @@ ret = PyList_New(1); if (ret == NULL) goto bail; - obj = PyInt_FromLong(revs[0]); + obj = PyLong_FromLong(revs[0]); if (obj == NULL) goto bail; PyList_SET_ITEM(ret, 0, obj); @@ -2834,14 +2851,8 @@ Py_ssize_t length = index_length(self) + 1; int ret = 0; -/* Argument changed from PySliceObject* to PyObject* in Python 3. */ -#ifdef IS_PY3K if (PySlice_GetIndicesEx(item, length, &start, &stop, &step, &slicelength) < 0) -#else - if (PySlice_GetIndicesEx((PySliceObject *)item, length, &start, &stop, - &step, &slicelength) < 0) -#endif return -1; if (slicelength <= 0) @@ -2925,7 +2936,7 @@ if (value == NULL) return self->ntinitialized ? nt_delete_node(&self->nt, node) : 0; - rev = PyInt_AsLong(value); + rev = PyLong_AsLong(value); if (rev > INT_MAX || rev < 0) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_ValueError, "rev out of range"); @@ -3027,10 +3038,9 @@ self->entry_size = cl2_entry_size; } - self->nullentry = - Py_BuildValue(PY23("iiiiiiis#iiBBi", "iiiiiiiy#iiBBi"), 0, 0, 0, -1, - -1, -1, -1, nullid, self->nodelen, 0, 0, - comp_mode_inline, comp_mode_inline, rank_unknown); + self->nullentry = Py_BuildValue( + "iiiiiiiy#iiBBi", 0, 0, 0, -1, -1, -1, -1, nullid, self->nodelen, 0, + 0, comp_mode_inline, comp_mode_inline, rank_unknown); if (!self->nullentry) return -1; @@ -3266,10 +3276,7 @@ static Revlog_CAPI CAPI = { /* increment the abi_version field upon each change in the Revlog_CAPI struct or in the ABI of the listed functions */ - 2, - index_length, - index_node, - HgRevlogIndex_GetParents, + 3, index_length, index_node, index_fast_rank, HgRevlogIndex_GetParents, }; void revlog_module_init(PyObject *mod)
--- a/mercurial/cext/util.h Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cext/util.h Tue Apr 05 11:09:03 2022 +0200 @@ -10,17 +10,6 @@ #include "compat.h" -#if PY_MAJOR_VERSION >= 3 -#define IS_PY3K -#endif - -/* helper to switch things like string literal depending on Python version */ -#ifdef IS_PY3K -#define PY23(py2, py3) py3 -#else -#define PY23(py2, py3) py2 -#endif - /* clang-format off */ typedef struct { PyObject_HEAD
--- a/mercurial/cffi/bdiff.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cffi/bdiff.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import struct
--- a/mercurial/cffi/bdiffbuild.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cffi/bdiffbuild.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import cffi import os
--- a/mercurial/cffi/mpatch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cffi/mpatch.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from ..pure.mpatch import * from ..pure.mpatch import mpatchError # silence pyflakes
--- a/mercurial/cffi/mpatchbuild.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cffi/mpatchbuild.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import cffi import os
--- a/mercurial/cffi/osutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cffi/osutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import stat as statmod @@ -34,7 +33,7 @@ attrkinds[lib.VFIFO] = statmod.S_IFIFO attrkinds[lib.VSOCK] = statmod.S_IFSOCK - class stat_res(object): + class stat_res: def __init__(self, st_mode, st_mtime, st_size): self.st_mode = st_mode self.st_mtime = st_mtime
--- a/mercurial/cffi/osutilbuild.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cffi/osutilbuild.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import cffi ffi = cffi.FFI()
--- a/mercurial/changegroup.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/changegroup.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import struct @@ -106,7 +105,7 @@ os.unlink(cleanup) -class cg1unpacker(object): +class cg1unpacker: """Unpacker for cg1 changegroup streams. A changegroup unpacker handles the framing of the revision data in @@ -425,7 +424,7 @@ mfnode = cl.changelogrevision(cset).manifest mfest = ml[mfnode].readdelta() # store file nodes we must see - for f, n in pycompat.iteritems(mfest): + for f, n in mfest.items(): needfiles.setdefault(f, set()).add(n) on_filelog_rev = None @@ -692,7 +691,7 @@ ) -class headerlessfixup(object): +class headerlessfixup: def __init__(self, fh, h): self._h = h self._fh = fh @@ -1004,7 +1003,7 @@ progress.complete() -class cgpacker(object): +class cgpacker: def __init__( self, repo, @@ -1967,7 +1966,7 @@ del needfiles[f] progress.complete() - for f, needs in pycompat.iteritems(needfiles): + for f, needs in needfiles.items(): fl = repo.file(f) for n in needs: try:
--- a/mercurial/changelog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/changelog.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from .node import ( @@ -92,7 +91,7 @@ return b'\n'.join([l.rstrip() for l in desc.splitlines()]).strip(b'\n') -class appender(object): +class appender: """the changelog index must be updated last on disk, so we use this class to delay writes to it""" @@ -162,7 +161,7 @@ return self.fp.__exit__(*args) -class _divertopener(object): +class _divertopener: def __init__(self, opener, target): self._opener = opener self._target = target @@ -189,7 +188,7 @@ @attr.s -class _changelogrevision(object): +class _changelogrevision: # Extensions might modify _defaultextra, so let the constructor below pass # it in extra = attr.ib() @@ -205,7 +204,7 @@ branchinfo = attr.ib(default=(_defaultextra[b'branch'], False)) -class changelogrevision(object): +class changelogrevision: """Holds results of a parsed changelog revision. Changelog revisions consist of multiple pieces of data, including
--- a/mercurial/chgserver.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/chgserver.py Tue Apr 05 11:09:03 2022 +0200 @@ -39,7 +39,6 @@ skiphash = False """ -from __future__ import absolute_import import inspect import os @@ -135,7 +134,7 @@ ignored = set() envitems = [ (k, v) - for k, v in pycompat.iteritems(encoding.environ) + for k, v in encoding.environ.items() if _envre.match(k) and k not in ignored ] envhash = _hashlist(sorted(envitems)) @@ -197,7 +196,7 @@ return _hashlist(pycompat.maplist(trystat, paths))[:12] -class hashstate(object): +class hashstate: """a structure storing confighash, mtimehash, paths used for mtimehash""" def __init__(self, confighash, mtimehash, mtimepaths): @@ -293,7 +292,7 @@ return (newui, newlui) -class channeledsystem(object): +class channeledsystem: """Propagate ui.system() request in the following format: payload length (unsigned int), @@ -321,7 +320,7 @@ def __call__(self, cmd, environ, cwd=None, type=b'system', cmdtable=None): args = [type, cmd, util.abspath(cwd or b'.')] - args.extend(b'%s=%s' % (k, v) for k, v in pycompat.iteritems(environ)) + args.extend(b'%s=%s' % (k, v) for k, v in environ.items()) data = b'\0'.join(args) self.out.write(struct.pack(b'>cI', self.channel, len(data))) self.out.write(data) @@ -409,22 +408,13 @@ # be unbuffered no matter if it is a tty or not. if fn == b'ferr': newfp = fp - elif pycompat.ispy3: + else: # On Python 3, the standard library doesn't offer line-buffered # binary streams, so wrap/unwrap it. if fp.isatty(): newfp = procutil.make_line_buffered(fp) else: newfp = procutil.unwrap_line_buffered(fp) - else: - # Python 2 uses the I/O streams provided by the C library, so - # make it line-buffered explicitly. Otherwise the default would - # be decided on first write(), where fout could be a pager. - if fp.isatty(): - bufsize = 1 # line buffered - else: - bufsize = -1 # system default - newfp = os.fdopen(fp.fileno(), mode, bufsize) if newfp is not fp: setattr(ui, fn, newfp) setattr(self, cn, newfp) @@ -448,17 +438,8 @@ nullfd = os.open(os.devnull, os.O_WRONLY) ui = self.ui for (ch, fp, fd), (cn, fn, mode) in zip(self._oldios, _iochannels): - newfp = getattr(ui, fn) - # On Python 2, newfp and fp may be separate file objects associated - # with the same fd, so we must close newfp while it's associated - # with the client. Otherwise the new associated fd would be closed - # when newfp gets deleted. On Python 3, newfp is just a wrapper - # around fp even if newfp is not fp, so deleting newfp is safe. - if not (pycompat.ispy3 or newfp is fp): - newfp.close() - # restore original fd: fp is open again try: - if (pycompat.ispy3 or newfp is fp) and 'w' in mode: + if 'w' in mode: # Discard buffered data which couldn't be flushed because # of EPIPE. The data should belong to the current session # and should never persist. @@ -636,7 +617,7 @@ return b'%s-%s' % (os.path.join(dirname, basename), hashstr) -class chgunixservicehandler(object): +class chgunixservicehandler: """Set of operations for chg services""" pollinterval = 1 # [sec]
--- a/mercurial/cmdutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/cmdutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import copy as copymod import errno @@ -627,7 +626,7 @@ # 5. finally restore backed-up files try: dirstate = repo.dirstate - for realname, tmpname in pycompat.iteritems(backups): + for realname, tmpname in backups.items(): ui.debug(b'restoring %r to %r\n' % (tmpname, realname)) if dirstate.get_entry(realname).maybe_clean: @@ -667,7 +666,7 @@ return commit(ui, repo, recordinwlock, pats, opts) -class dirnode(object): +class dirnode: """ Represent a directory in user working copy with information required for the purpose of tersing its status. @@ -833,7 +832,7 @@ @attr.s(frozen=True) -class morestatus(object): +class morestatus: reporoot = attr.ib() unfinishedop = attr.ib() unfinishedmsg = attr.ib() @@ -1344,7 +1343,7 @@ return not pat or pat == b'-' -class _unclosablefile(object): +class _unclosablefile: def __init__(self, fp): self._fp = fp
--- a/mercurial/color.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/color.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re
--- a/mercurial/commands.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/commands.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -2470,7 +2469,7 @@ ) def debugcommands(ui, cmd=b'', *args): """list all available commands and options""" - for cmd, vals in sorted(pycompat.iteritems(table)): + for cmd, vals in sorted(table.items()): cmd = cmd.split(b'|')[0] opts = b', '.join([i[1] for i in vals[1]]) ui.write(b'%s: %s\n' % (cmd, opts)) @@ -3911,9 +3910,7 @@ hexremoterev = hex(remoterev) bms = [ bm - for bm, bmr in pycompat.iteritems( - peer.listkeys(b'bookmarks') - ) + for bm, bmr in peer.listkeys(b'bookmarks').items() if bmr == hexremoterev ] @@ -7090,7 +7087,7 @@ c = repo.dirstate.copies() copied, renamed = [], [] - for d, s in pycompat.iteritems(c): + for d, s in c.items(): if s in status.removed: status.removed.remove(s) renamed.append(d)
--- a/mercurial/commandserver.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/commandserver.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import gc @@ -40,7 +39,7 @@ ) -class channeledoutput(object): +class channeledoutput: """ Write data to out in the following format: @@ -69,7 +68,7 @@ return getattr(self.out, attr) -class channeledmessage(object): +class channeledmessage: """ Write encoded message and metadata to out in the following format: @@ -98,7 +97,7 @@ return getattr(self._cout, attr) -class channeledinput(object): +class channeledinput: """ Read data from in_. @@ -201,7 +200,7 @@ ) -class server(object): +class server: """ Listens for commands on fin, runs them and writes the output on a channel based stream to fout. @@ -451,7 +450,7 @@ u.setlogger(b'cmdserver', logger) -class pipeservice(object): +class pipeservice: def __init__(self, ui, repo, opts): self.ui = ui self.repo = repo @@ -526,7 +525,7 @@ raise -class unixservicehandler(object): +class unixservicehandler: """Set of pluggable operations for unix-mode services Almost all methods except for createcmdserver() are called in the main @@ -560,7 +559,7 @@ return server(self.ui, repo, fin, fout, prereposetups) -class unixforkingservice(object): +class unixforkingservice: """ Listens on unix domain socket and forks server per connection """
--- a/mercurial/commit.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/commit.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno
--- a/mercurial/config.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/config.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -15,12 +14,11 @@ from . import ( encoding, error, - pycompat, util, ) -class config(object): +class config: def __init__(self, data=None): self._current_source_level = 0 self._data = {} @@ -111,20 +109,19 @@ return sorted(self._data.keys()) def items(self, section): - items = pycompat.iteritems(self._data.get(section, {})) + items = self._data.get(section, {}).items() return [(k, v[0]) for (k, v) in items] def set(self, section, item, value, source=b""): - if pycompat.ispy3: - assert not isinstance( - section, str - ), b'config section may not be unicode strings on Python 3' - assert not isinstance( - item, str - ), b'config item may not be unicode strings on Python 3' - assert not isinstance( - value, str - ), b'config values may not be unicode strings on Python 3' + assert not isinstance( + section, str + ), b'config section may not be unicode strings on Python 3' + assert not isinstance( + item, str + ), b'config item may not be unicode strings on Python 3' + assert not isinstance( + value, str + ), b'config values may not be unicode strings on Python 3' if section not in self: self._data[section] = util.cowsortdict() else:
--- a/mercurial/configitems.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/configitems.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import functools import re @@ -30,7 +29,7 @@ knownitems.update(items) -class configitem(object): +class configitem: """represent a known config item :section: the official config section where to find this item, @@ -1571,6 +1570,45 @@ default=False, ) coreconfigitem( + b'partial-merge-tools', + b'.*', + default=None, + generic=True, + experimental=True, +) +coreconfigitem( + b'partial-merge-tools', + br'.*\.patterns', + default=dynamicdefault, + generic=True, + priority=-1, + experimental=True, +) +coreconfigitem( + b'partial-merge-tools', + br'.*\.executable$', + default=dynamicdefault, + generic=True, + priority=-1, + experimental=True, +) +coreconfigitem( + b'partial-merge-tools', + br'.*\.order', + default=0, + generic=True, + priority=-1, + experimental=True, +) +coreconfigitem( + b'partial-merge-tools', + br'.*\.args', + default=b"$local $base $other", + generic=True, + priority=-1, + experimental=True, +) +coreconfigitem( b'merge-tools', b'.*', default=None,
--- a/mercurial/context.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/context.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import filecmp @@ -52,7 +51,7 @@ propertycache = util.propertycache -class basectx(object): +class basectx: """A basectx object represents the common logic for its children: changectx: read-only context that is already present in the repo, workingctx: a context that represents the working directory and can @@ -124,7 +123,7 @@ deleted, unknown, ignored = s.deleted, s.unknown, s.ignored deletedset = set(deleted) d = mf1.diff(mf2, match=match, clean=listclean) - for fn, value in pycompat.iteritems(d): + for fn, value in d.items(): if fn in deletedset: continue if value is None: @@ -797,7 +796,7 @@ return self.walk(match) -class basefilectx(object): +class basefilectx: """A filecontext object represents the common logic for its children: filectx: read-only access to a filerevision that is already present in the repo, @@ -3105,7 +3104,7 @@ return scmutil.status(modified, added, removed, [], [], [], []) -class arbitraryfilectx(object): +class arbitraryfilectx: """Allows you to use filectx-like functions on a file in an arbitrary location on disk, possibly not in the working directory. """
--- a/mercurial/copies.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/copies.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import os @@ -18,7 +17,6 @@ match as matchmod, pathutil, policy, - pycompat, util, ) @@ -69,7 +67,7 @@ def _chain(prefix, suffix): """chain two sets of copies 'prefix' and 'suffix'""" result = prefix.copy() - for key, value in pycompat.iteritems(suffix): + for key, value in suffix.items(): result[key] = prefix.get(value, value) return result @@ -409,7 +407,7 @@ if childcopies: newcopies = copies.copy() - for dest, source in pycompat.iteritems(childcopies): + for dest, source in childcopies.items(): prev = copies.get(source) if prev is not None and prev[1] is not None: source = prev[1] @@ -624,7 +622,7 @@ newcopies = copies if childcopies: newcopies = copies.copy() - for dest, source in pycompat.iteritems(childcopies): + for dest, source in childcopies.items(): prev = copies.get(source) if prev is not None and prev[1] is not None: source = prev[1] @@ -722,7 +720,7 @@ # can still exist (e.g. hg cp a b; hg mv a c). In those cases we # arbitrarily pick one of the renames. r = {} - for k, v in sorted(pycompat.iteritems(copies)): + for k, v in sorted(copies.items()): if match and not match(v): continue # remove copies @@ -889,7 +887,7 @@ copy[dst] = src -class branch_copies(object): +class branch_copies: """Information about copies made on one side of a merge/graft. "copy" is a mapping from destination name -> source name, @@ -1081,7 +1079,7 @@ # examine each file copy for a potential directory move, which is # when all the files in a directory are moved to a new directory - for dst, src in pycompat.iteritems(fullcopy): + for dst, src in fullcopy.items(): dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst) if dsrc in invalid: # already seen to be uninteresting @@ -1104,7 +1102,7 @@ if not dirmove: return {}, {} - dirmove = {k + b"/": v + b"/" for k, v in pycompat.iteritems(dirmove)} + dirmove = {k + b"/": v + b"/" for k, v in dirmove.items()} for d in dirmove: repo.ui.debug( @@ -1187,7 +1185,7 @@ copies2 = {} cp = _forwardcopies(base, c2) - for dst, src in pycompat.iteritems(cp): + for dst, src in cp.items(): if src in m1: copies2[dst] = src @@ -1305,5 +1303,5 @@ for dest, __ in list(new_copies.items()): if dest in parent: del new_copies[dest] - for dst, src in pycompat.iteritems(new_copies): + for dst, src in new_copies.items(): wctx[dst].markcopied(src)
--- a/mercurial/crecord.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/crecord.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # This code is based on the Mark Edgington's crecord extension. # (Itself based on Bryan O'Sullivan's record extension.) -from __future__ import absolute_import import os import re @@ -83,7 +82,7 @@ return curses and ui.interface(b"chunkselector") == b"curses" -class patchnode(object): +class patchnode: """abstract class for patch graph nodes (i.e. patchroot, header, hunk, hunkline) """ @@ -602,7 +601,7 @@ """ chunkselector = curseschunkselector(headerlist, ui, operation) - class dummystdscr(object): + class dummystdscr: def clear(self): pass @@ -629,7 +628,7 @@ } -class curseschunkselector(object): +class curseschunkselector: def __init__(self, headerlist, ui, operation=None): # put the headers into a patch object self.headerlist = patch(headerlist)
--- a/mercurial/dagop.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dagop.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import heapq @@ -272,7 +271,7 @@ break -class subsetparentswalker(object): +class subsetparentswalker: r"""Scan adjacent ancestors in the graph given by the subset This computes parent-child relations in the sub graph filtered by @@ -648,7 +647,7 @@ @attr.s(slots=True, frozen=True) -class annotateline(object): +class annotateline: fctx = attr.ib() lineno = attr.ib() # Whether this annotation was the result of a skip-annotate. @@ -657,7 +656,7 @@ @attr.s(slots=True, frozen=True) -class _annotatedfile(object): +class _annotatedfile: # list indexed by lineno - 1 fctxs = attr.ib() linenos = attr.ib()
--- a/mercurial/dagparser.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dagparser.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re import string
--- a/mercurial/debugcommands.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/debugcommands.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import binascii import codecs @@ -493,7 +492,7 @@ b2caps = bundle2.bundle2caps(peer) if b2caps: ui.writenoi18n(b'Bundle2 capabilities:\n') - for key, values in sorted(pycompat.iteritems(b2caps)): + for key, values in sorted(b2caps.items()): ui.write(b' %s\n' % key) for v in values: ui.write(b' %s\n' % v) @@ -1021,7 +1020,7 @@ b'', b'remote-as-revs', b"", - b'use local as remote, with only these these revisions', + b'use local as remote, with only these revisions', ), ] + cmdutil.remoteopts @@ -2385,11 +2384,11 @@ fm_files.end() fm_extras = fm.nested(b'extras') - for f, d in sorted(pycompat.iteritems(ms.allextras())): + for f, d in sorted(ms.allextras().items()): if f in ms: # If file is in mergestate, we have already processed it's extras continue - for k, v in pycompat.iteritems(d): + for k, v in d.items(): fm_extras.startitem() fm_extras.data(file=f) fm_extras.data(key=k) @@ -2406,7 +2405,7 @@ names = set() # since we previously only listed open branches, we will handle that # specially (after this for loop) - for name, ns in pycompat.iteritems(repo.names): + for name, ns in repo.names.items(): if name != b'branches': names.update(ns.listnames(repo)) names.update( @@ -2700,7 +2699,7 @@ fullpaths = opts['full'] files, dirs = set(), set() adddir, addfile = dirs.add, files.add - for f, st in pycompat.iteritems(dirstate): + for f, st in dirstate.items(): if f.startswith(spec) and st.state in acceptable: if fixpaths: f = f.replace(b'/', pycompat.ossep) @@ -2889,7 +2888,7 @@ ui.status(pycompat.bytestr(r) + b'\n') return not r else: - for k, v in sorted(pycompat.iteritems(target.listkeys(namespace))): + for k, v in sorted(target.listkeys(namespace).items()): ui.write( b"%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v)) @@ -4271,7 +4270,7 @@ for opt in cmdutil.remoteopts: del opts[opt[1]] args = {} - for k, v in pycompat.iteritems(opts): + for k, v in opts.items(): if v: args[k] = v args = pycompat.strkwargs(args)
--- a/mercurial/destutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/destutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from . import bookmarks, error, obsutil, scmutil, stack
--- a/mercurial/diffhelper.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/diffhelper.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _
--- a/mercurial/diffutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/diffutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _
--- a/mercurial/dirstate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dirstate.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import contextlib @@ -91,7 +90,7 @@ @interfaceutil.implementer(intdirstate.idirstate) -class dirstate(object): +class dirstate: def __init__( self, opener, @@ -343,7 +342,7 @@ return iter(sorted(self._map)) def items(self): - return pycompat.iteritems(self._map) + return self._map.items() iteritems = items @@ -771,9 +770,7 @@ def _writedirstate(self, tr, st): # notify callbacks about parents change if self._origpl is not None and self._origpl != self._pl: - for c, callback in sorted( - pycompat.iteritems(self._plchangecallbacks) - ): + for c, callback in sorted(self._plchangecallbacks.items()): callback(self, self._origpl, self._pl) self._origpl = None self._map.write(tr, st) @@ -936,7 +933,7 @@ if match.isexact() and self._checkcase: normed = {} - for f, st in pycompat.iteritems(results): + for f, st in results.items(): if st is None: continue @@ -949,7 +946,7 @@ paths.add(f) - for norm, paths in pycompat.iteritems(normed): + for norm, paths in normed.items(): if len(paths) > 1: for path in paths: folded = self._discoverpath( @@ -1311,9 +1308,9 @@ # - match.traversedir does something, because match.traversedir should # be called for every dir in the working dir full = listclean or match.traversedir is not None - for fn, st in pycompat.iteritems( - self.walk(match, subrepos, listunknown, listignored, full=full) - ): + for fn, st in self.walk( + match, subrepos, listunknown, listignored, full=full + ).items(): if not dcontains(fn): if (listignored or mexact(fn)) and dirignore(fn): if listignored:
--- a/mercurial/dirstateguard.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dirstateguard.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os from .i18n import _
--- a/mercurial/dirstatemap.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dirstatemap.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno @@ -13,7 +12,6 @@ error, pathutil, policy, - pycompat, txnutil, util, ) @@ -36,7 +34,7 @@ rangemask = 0x7FFFFFFF -class _dirstatemapcommon(object): +class _dirstatemapcommon: """ Methods that are identical for both implementations of the dirstatemap class, with and without Rust extensions enabled. @@ -355,7 +353,7 @@ util.clearcachedproperty(self, b"dirfoldmap") def items(self): - return pycompat.iteritems(self._map) + return self._map.items() # forward for python2,3 compat iteritems = items @@ -379,7 +377,7 @@ self._dirtyparents = True copies = {} if fold_p2: - for f, s in pycompat.iteritems(self._map): + for f, s in self._map.items(): # Discard "merged" markers when moving away from a merge state if s.p2_info: source = self.copymap.pop(f, None) @@ -502,7 +500,7 @@ f = {} normcase = util.normcase - for name, s in pycompat.iteritems(self._map): + for name, s in self._map.items(): if not s.removed: f[normcase(name)] = name f[b'.'] = b'.' # prevents useless util.fspath() invocation
--- a/mercurial/dirstateutils/docket.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dirstateutils/docket.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import struct @@ -29,7 +28,7 @@ ) -class DirstateDocket(object): +class DirstateDocket: data_filename_pattern = b'dirstate.%s' def __init__(self, parents, data_size, tree_metadata, uuid):
--- a/mercurial/dirstateutils/timestamp.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dirstateutils/timestamp.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import functools import os
--- a/mercurial/dirstateutils/v2.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dirstateutils/v2.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import struct @@ -126,7 +125,7 @@ @attr.s -class Node(object): +class Node: path = attr.ib() entry = attr.ib() parent = attr.ib(default=None)
--- a/mercurial/discovery.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/discovery.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import functools @@ -74,7 +73,7 @@ return (list(common), anyinc, heads or list(srvheads)) -class outgoing(object): +class outgoing: """Represents the result of a findcommonoutgoing() call. Members: @@ -238,7 +237,7 @@ knownnode = cl.hasnode # do not use nodemap until it is filtered # A. register remote heads of branches which are in outgoing set - for branch, heads in pycompat.iteritems(remotemap): + for branch, heads in remotemap.items(): # don't add head info about branches which we don't have locally if branch not in branches: continue @@ -262,14 +261,14 @@ repo, ( (branch, heads[1]) - for branch, heads in pycompat.iteritems(headssum) + for branch, heads in headssum.items() if heads[0] is not None ), ) newmap.update(repo, (ctx.rev() for ctx in missingctx)) - for branch, newheads in pycompat.iteritems(newmap): + for branch, newheads in newmap.items(): headssum[branch][1][:] = newheads - for branch, items in pycompat.iteritems(headssum): + for branch, items in headssum.items(): for l in items: if l is not None: l.sort() @@ -380,9 +379,7 @@ headssum = _oldheadssummary(repo, remoteheads, outgoing, inc) pushop.pushbranchmap = headssum newbranches = [ - branch - for branch, heads in pycompat.iteritems(headssum) - if heads[0] is None + branch for branch, heads in headssum.items() if heads[0] is None ] # 1. Check for new branches on the remote. if newbranches and not newbranch: # new branch requires --new-branch
--- a/mercurial/dispatch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/dispatch.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import errno import getopt @@ -54,7 +53,7 @@ ) -class request(object): +class request: def __init__( self, args, @@ -150,93 +149,76 @@ sys.exit(status & 255) -if pycompat.ispy3: - - def initstdio(): - # stdio streams on Python 3 are io.TextIOWrapper instances proxying another - # buffer. These streams will normalize \n to \r\n by default. Mercurial's - # preferred mechanism for writing output (ui.write()) uses io.BufferedWriter - # instances, which write to the underlying stdio file descriptor in binary - # mode. ui.write() uses \n for line endings and no line ending normalization - # is attempted through this interface. This "just works," even if the system - # preferred line ending is not \n. - # - # But some parts of Mercurial (e.g. hooks) can still send data to sys.stdout - # and sys.stderr. They will inherit the line ending normalization settings, - # potentially causing e.g. \r\n to be emitted. Since emitting \n should - # "just work," here we change the sys.* streams to disable line ending - # normalization, ensuring compatibility with our ui type. - - if sys.stdout is not None: - # write_through is new in Python 3.7. - kwargs = { - "newline": "\n", - "line_buffering": sys.stdout.line_buffering, - } - if util.safehasattr(sys.stdout, "write_through"): - # pytype: disable=attribute-error - kwargs["write_through"] = sys.stdout.write_through - # pytype: enable=attribute-error - sys.stdout = io.TextIOWrapper( - sys.stdout.buffer, - sys.stdout.encoding, - sys.stdout.errors, - **kwargs - ) +def initstdio(): + # stdio streams on Python 3 are io.TextIOWrapper instances proxying another + # buffer. These streams will normalize \n to \r\n by default. Mercurial's + # preferred mechanism for writing output (ui.write()) uses io.BufferedWriter + # instances, which write to the underlying stdio file descriptor in binary + # mode. ui.write() uses \n for line endings and no line ending normalization + # is attempted through this interface. This "just works," even if the system + # preferred line ending is not \n. + # + # But some parts of Mercurial (e.g. hooks) can still send data to sys.stdout + # and sys.stderr. They will inherit the line ending normalization settings, + # potentially causing e.g. \r\n to be emitted. Since emitting \n should + # "just work," here we change the sys.* streams to disable line ending + # normalization, ensuring compatibility with our ui type. - if sys.stderr is not None: - kwargs = { - "newline": "\n", - "line_buffering": sys.stderr.line_buffering, - } - if util.safehasattr(sys.stderr, "write_through"): - # pytype: disable=attribute-error - kwargs["write_through"] = sys.stderr.write_through - # pytype: enable=attribute-error - sys.stderr = io.TextIOWrapper( - sys.stderr.buffer, - sys.stderr.encoding, - sys.stderr.errors, - **kwargs - ) + if sys.stdout is not None: + # write_through is new in Python 3.7. + kwargs = { + "newline": "\n", + "line_buffering": sys.stdout.line_buffering, + } + if util.safehasattr(sys.stdout, "write_through"): + # pytype: disable=attribute-error + kwargs["write_through"] = sys.stdout.write_through + # pytype: enable=attribute-error + sys.stdout = io.TextIOWrapper( + sys.stdout.buffer, sys.stdout.encoding, sys.stdout.errors, **kwargs + ) - if sys.stdin is not None: - # No write_through on read-only stream. - sys.stdin = io.TextIOWrapper( - sys.stdin.buffer, - sys.stdin.encoding, - sys.stdin.errors, - # None is universal newlines mode. - newline=None, - line_buffering=sys.stdin.line_buffering, - ) + if sys.stderr is not None: + kwargs = { + "newline": "\n", + "line_buffering": sys.stderr.line_buffering, + } + if util.safehasattr(sys.stderr, "write_through"): + # pytype: disable=attribute-error + kwargs["write_through"] = sys.stderr.write_through + # pytype: enable=attribute-error + sys.stderr = io.TextIOWrapper( + sys.stderr.buffer, sys.stderr.encoding, sys.stderr.errors, **kwargs + ) - def _silencestdio(): - for fp in (sys.stdout, sys.stderr): - if fp is None: - continue - # Check if the file is okay - try: - fp.flush() - continue - except IOError: - pass - # Otherwise mark it as closed to silence "Exception ignored in" - # message emitted by the interpreter finalizer. - try: - fp.close() - except IOError: - pass + if sys.stdin is not None: + # No write_through on read-only stream. + sys.stdin = io.TextIOWrapper( + sys.stdin.buffer, + sys.stdin.encoding, + sys.stdin.errors, + # None is universal newlines mode. + newline=None, + line_buffering=sys.stdin.line_buffering, + ) -else: - - def initstdio(): - for fp in (sys.stdin, sys.stdout, sys.stderr): - procutil.setbinary(fp) - - def _silencestdio(): - pass +def _silencestdio(): + for fp in (sys.stdout, sys.stderr): + if fp is None: + continue + # Check if the file is okay + try: + fp.flush() + continue + except IOError: + pass + # Otherwise mark it as closed to silence "Exception ignored in" + # message emitted by the interpreter finalizer. + try: + fp.close() + except IOError: + pass def _formatargs(args): @@ -575,7 +557,7 @@ return r.sub(lambda x: replacemap[x.group()], cmd) -class cmdalias(object): +class cmdalias: def __init__(self, ui, name, definition, cmdtable, source): self.name = self.cmd = name self.cmdname = b'' @@ -590,7 +572,7 @@ try: aliases, entry = cmdutil.findcmd(self.name, cmdtable) - for alias, e in pycompat.iteritems(cmdtable): + for alias, e in cmdtable.items(): if e is entry: self.cmd = alias break @@ -758,7 +740,7 @@ raise -class lazyaliasentry(object): +class lazyaliasentry: """like a typical command entry (func, opts, help), but is lazy""" def __init__(self, ui, name, definition, cmdtable, source):
--- a/mercurial/encoding.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/encoding.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import locale import os @@ -47,8 +46,7 @@ _sysstr = pycompat.sysstr -if pycompat.ispy3: - unichr = chr +unichr = chr # These unicode characters are ignored by HFS+ (Apple Technote 1150, # "Unicode Subtleties"), so we need to ignore them in some places for @@ -79,10 +77,8 @@ # encoding.environ is provided read-only, which may not be used to modify # the process environment -_nativeenviron = not pycompat.ispy3 or os.supports_bytes_environ -if not pycompat.ispy3: - environ = os.environ # re-exports -elif _nativeenviron: +_nativeenviron = os.supports_bytes_environ +if _nativeenviron: environ = os.environb # re-exports else: # preferred encoding isn't known yet; use utf-8 to avoid unicode error @@ -99,7 +95,7 @@ # cp65001 is a Windows variant of utf-8, which isn't supported on Python 2. # No idea if it should be rewritten to the canonical name 'utf-8' on Python 3. # https://bugs.python.org/issue13216 -if pycompat.iswindows and not pycompat.ispy3: +if pycompat.iswindows: _encodingrewrites[b'cp65001'] = b'utf-8' try: @@ -271,21 +267,9 @@ # converter functions between native str and byte string. use these if the # character encoding is not aware (e.g. exception message) or is known to # be locale dependent (e.g. date formatting.) -if pycompat.ispy3: - strtolocal = unitolocal - strfromlocal = unifromlocal - strmethod = unimethod -else: - - def strtolocal(s): - # type: (str) -> bytes - return s # pytype: disable=bad-return-type - - def strfromlocal(s): - # type: (bytes) -> str - return s # pytype: disable=bad-return-type - - strmethod = pycompat.identity +strtolocal = unitolocal +strfromlocal = unifromlocal +strmethod = unimethod def lower(s): @@ -345,7 +329,7 @@ if not _nativeenviron: # now encoding and helper functions are available, recreate the environ # dict to be exported to other modules - if pycompat.iswindows and pycompat.ispy3: + if pycompat.iswindows: class WindowsEnviron(dict): """`os.environ` normalizes environment variables to uppercase on windows""" @@ -361,36 +345,34 @@ DRIVE_RE = re.compile(b'^[a-z]:') -if pycompat.ispy3: - # os.getcwd() on Python 3 returns string, but it has os.getcwdb() which - # returns bytes. - if pycompat.iswindows: - # Python 3 on Windows issues a DeprecationWarning about using the bytes - # API when os.getcwdb() is called. - # - # Additionally, py3.8+ uppercases the drive letter when calling - # os.path.realpath(), which is used on ``repo.root``. Since those - # strings are compared in various places as simple strings, also call - # realpath here. See https://bugs.python.org/issue40368 - # - # However this is not reliable, so lets explicitly make this drive - # letter upper case. - # - # note: we should consider dropping realpath here since it seems to - # change the semantic of `getcwd`. +# os.getcwd() on Python 3 returns string, but it has os.getcwdb() which +# returns bytes. +if pycompat.iswindows: + # Python 3 on Windows issues a DeprecationWarning about using the bytes + # API when os.getcwdb() is called. + # + # Additionally, py3.8+ uppercases the drive letter when calling + # os.path.realpath(), which is used on ``repo.root``. Since those + # strings are compared in various places as simple strings, also call + # realpath here. See https://bugs.python.org/issue40368 + # + # However this is not reliable, so lets explicitly make this drive + # letter upper case. + # + # note: we should consider dropping realpath here since it seems to + # change the semantic of `getcwd`. - def getcwd(): - cwd = os.getcwd() # re-exports - cwd = os.path.realpath(cwd) - cwd = strtolocal(cwd) - if DRIVE_RE.match(cwd): - cwd = cwd[0:1].upper() + cwd[1:] - return cwd + def getcwd(): + cwd = os.getcwd() # re-exports + cwd = os.path.realpath(cwd) + cwd = strtolocal(cwd) + if DRIVE_RE.match(cwd): + cwd = cwd[0:1].upper() + cwd[1:] + return cwd - else: - getcwd = os.getcwdb # re-exports + else: - getcwd = os.getcwd # re-exports + getcwd = os.getcwdb # re-exports # How to treat ambiguous-width characters. Set to 'wide' to treat as wide. _wide = _sysstr( @@ -528,7 +510,7 @@ return u + ellipsis -class normcasespecs(object): +class normcasespecs: """what a platform's normcase does to ASCII strings This is specified per platform, and should be consistent with what normcase @@ -601,10 +583,7 @@ # We need to decode/encode U+DCxx codes transparently since invalid UTF-8 # bytes are mapped to that range. -if pycompat.ispy3: - _utf8strict = r'surrogatepass' -else: - _utf8strict = r'strict' +_utf8strict = r'surrogatepass' _utf8len = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4]
--- a/mercurial/error.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/error.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ imports. """ -from __future__ import absolute_import import difflib @@ -40,7 +39,7 @@ return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args) -class Hint(object): +class Hint: """Mix-in to provide a hint of an error This should come first in the inheritance list to consume a hint and @@ -69,14 +68,12 @@ def __bytes__(self): return self.message - if pycompat.ispy3: - - def __str__(self): - # type: () -> str - # the output would be unreadable if the message was translated, - # but do not replace it with encoding.strfromlocal(), which - # may raise another exception. - return pycompat.sysstr(self.__bytes__()) + def __str__(self): + # type: () -> str + # the output would be unreadable if the message was translated, + # but do not replace it with encoding.strfromlocal(), which + # may raise another exception. + return pycompat.sysstr(self.__bytes__()) def format(self): # type: () -> bytes
--- a/mercurial/exchange.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/exchange.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import weakref @@ -223,7 +222,7 @@ return forcebundle1 or not op.remote.capable(b'bundle2') -class pushoperation(object): +class pushoperation: """A object that represent a single push operation Its purpose is to carry push related state and very common operations. @@ -806,7 +805,7 @@ bundler.newpart(b'check:heads', data=iter(pushop.remoteheads)) else: affected = set() - for branch, heads in pycompat.iteritems(pushop.pushbranchmap): + for branch, heads in pushop.pushbranchmap.items(): remoteheads, newheads, unsyncedheads, discardedheads = heads if remoteheads is not None: remote = set(remoteheads) @@ -855,7 +854,7 @@ checks = {p: [] for p in phases.allphases} checks[phases.public].extend(pushop.remotephases.publicheads) checks[phases.draft].extend(pushop.remotephases.draftroots) - if any(pycompat.itervalues(checks)): + if any(checks.values()): for phase in checks: checks[phase].sort() checkdata = phases.binaryencode(checks) @@ -1117,7 +1116,7 @@ part = bundler.newpart(b'pushvars') - for key, value in pycompat.iteritems(shellvars): + for key, value in shellvars.items(): part.addparam(key, value, mandatory=False) @@ -1372,7 +1371,7 @@ pushop.bkresult = 1 -class pulloperation(object): +class pulloperation: """A object that represent a single pull operation It purpose is to carry pull related state and very common operation.
--- a/mercurial/extensions.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/extensions.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import ast import collections @@ -74,7 +73,7 @@ try: mod = _extensions[name] except KeyError: - for k, v in pycompat.iteritems(_extensions): + for k, v in _extensions.items(): if k.endswith(b'.' + name) or k.endswith(b'/' + name): mod = v break @@ -171,7 +170,7 @@ def _validatecmdtable(ui, cmdtable): """Check if extension commands have required attributes""" - for c, e in pycompat.iteritems(cmdtable): + for c, e in cmdtable.items(): f = e[0] missing = [a for a in _cmdfuncattrs if not util.safehasattr(f, a)] if not missing: @@ -579,7 +578,7 @@ ''' assert callable(wrapper) aliases, entry = cmdutil.findcmd(command, table) - for alias, e in pycompat.iteritems(table): + for alias, e in table.items(): if e is entry: key = alias break @@ -622,7 +621,7 @@ raise AttributeError("type '%s' has no property '%s'" % (cls, propname)) -class wrappedfunction(object): +class wrappedfunction: '''context manager for temporarily wrapping a function''' def __init__(self, container, funcname, wrapper): @@ -756,7 +755,7 @@ if name in exts or name in _order or name == b'__init__': continue exts[name] = path - for name, path in pycompat.iteritems(_disabledextensions): + for name, path in _disabledextensions.items(): # If no path was provided for a disabled extension (e.g. "color=!"), # don't replace the path we already found by the scan above. if path: @@ -818,7 +817,7 @@ return { name: gettext(desc) - for name, desc in pycompat.iteritems(__index__.docs) + for name, desc in __index__.docs.items() if name not in _order } except (ImportError, AttributeError): @@ -829,7 +828,7 @@ return {} exts = {} - for name, path in pycompat.iteritems(paths): + for name, path in paths.items(): doc = _disabledhelp(path) if doc and name != b'__index__': exts[name] = doc.splitlines()[0] @@ -876,7 +875,7 @@ a = node.args[0] if isinstance(a, ast.Str): name = pycompat.sysbytes(a.s) - elif pycompat.ispy3 and isinstance(a, ast.Bytes): + elif isinstance(a, ast.Bytes): name = a.s else: continue @@ -918,7 +917,7 @@ ext = _finddisabledcmd(ui, cmd, cmd, path, strict=strict) if not ext: # otherwise, interrogate each extension until there's a match - for name, path in pycompat.iteritems(paths): + for name, path in paths.items(): ext = _finddisabledcmd(ui, cmd, name, path, strict=strict) if ext: break @@ -943,9 +942,7 @@ def notloaded(): '''return short names of extensions that failed to load''' - return [ - name for name, mod in pycompat.iteritems(_extensions) if mod is None - ] + return [name for name, mod in _extensions.items() if mod is None] def moduleversion(module):
--- a/mercurial/exthelper.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/exthelper.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,20 +9,18 @@ ### Extension helper ### ##################################################################### -from __future__ import absolute_import from . import ( commands, error, extensions, - pycompat, registrar, ) from hgdemandimport import tracing -class exthelper(object): +class exthelper: """Helper for modular extension setup A single helper should be instantiated for each module of an @@ -115,7 +113,7 @@ self._extcommandwrappers.extend(other._extcommandwrappers) self._functionwrappers.extend(other._functionwrappers) self.cmdtable.update(other.cmdtable) - for section, items in pycompat.iteritems(other.configtable): + for section, items in other.configtable.items(): if section in self.configtable: self.configtable[section].update(items) else:
--- a/mercurial/fancyopts.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/fancyopts.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import abc import functools @@ -205,7 +204,7 @@ return parsedopts, parsedargs -class customopt(object): # pytype: disable=ignored-metaclass +class customopt: # pytype: disable=ignored-metaclass """Manage defaults and mutations for any type of opt.""" __metaclass__ = abc.ABCMeta
--- a/mercurial/filelog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/filelog.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from .node import nullrev @@ -25,7 +24,7 @@ @interfaceutil.implementer(repository.ifilestorage) -class filelog(object): +class filelog: def __init__(self, opener, path): self._revlog = revlog.revlog( opener,
--- a/mercurial/filemerge.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/filemerge.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import os @@ -85,7 +84,7 @@ ) -class absentfilectx(object): +class absentfilectx: """Represents a file that's ostensibly in a context but is actually not present in it. @@ -1052,6 +1051,7 @@ markerstyle = internalmarkerstyle if mergetype == fullmerge: + _run_partial_resolution_tools(repo, local, other, base) # conflict markers generated by premerge will use 'detailed' # settings if either ui.mergemarkers or the tool's mergemarkers # setting is 'detailed'. This way tools can have basic labels in @@ -1116,6 +1116,73 @@ backup.remove() +def _run_partial_resolution_tools(repo, local, other, base): + """Runs partial-resolution tools on the three inputs and updates them.""" + ui = repo.ui + # Tuples of (order, name, executable path, args) + tools = [] + seen = set() + section = b"partial-merge-tools" + for k, v in ui.configitems(section): + name = k.split(b'.')[0] + if name in seen: + continue + patterns = ui.configlist(section, b'%s.patterns' % name, []) + is_match = True + if patterns: + m = match.match(repo.root, b'', patterns) + is_match = m(local.fctx.path()) + if is_match: + order = ui.configint(section, b'%s.order' % name, 0) + executable = ui.config(section, b'%s.executable' % name, name) + args = ui.config(section, b'%s.args' % name) + tools.append((order, name, executable, args)) + + if not tools: + return + # Sort in configured order (first in tuple) + tools.sort() + + files = [ + (b"local", local.fctx.path(), local.text()), + (b"base", base.fctx.path(), base.text()), + (b"other", other.fctx.path(), other.text()), + ] + + with _maketempfiles(files) as temppaths: + localpath, basepath, otherpath = temppaths + + for order, name, executable, args in tools: + cmd = procutil.shellquote(executable) + replace = { + b'local': localpath, + b'base': basepath, + b'other': otherpath, + } + args = util.interpolate( + br'\$', + replace, + args, + lambda s: procutil.shellquote(util.localpath(s)), + ) + + cmd = b'%s %s' % (cmd, args) + r = ui.system(cmd, cwd=repo.root, blockedtag=b'partial-mergetool') + if r: + raise error.StateError( + b'partial merge tool %s exited with code %d' % (name, r) + ) + local_text = util.readfile(localpath) + other_text = util.readfile(otherpath) + if local_text == other_text: + # No need to run other tools if all conflicts have been resolved + break + + local.set_text(local_text) + base.set_text(util.readfile(basepath)) + other.set_text(other_text) + + def _haltmerge(): msg = _(b'merge halted after failed merge (see hg resolve)') raise error.InterventionRequired(msg) @@ -1199,7 +1266,7 @@ def loadinternalmerge(ui, extname, registrarobj): """Load internal merge tool from specified registrarobj""" - for name, func in pycompat.iteritems(registrarobj._table): + for name, func in registrarobj._table.items(): fullname = b':' + name internals[fullname] = func internals[b'internal:' + name] = func
--- a/mercurial/fileset.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/fileset.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import re @@ -504,7 +503,7 @@ } -class matchctx(object): +class matchctx: def __init__(self, basectx, ctx, cwd, badfn=None): self._basectx = basectx self.ctx = ctx @@ -614,7 +613,7 @@ def loadpredicate(ui, extname, registrarobj): """Load fileset predicates from specified registrarobj""" - for name, func in pycompat.iteritems(registrarobj._table): + for name, func in registrarobj._table.items(): symbols[name] = func
--- a/mercurial/filesetlang.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/filesetlang.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from .pycompat import getattr
--- a/mercurial/formatter.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/formatter.py Tue Apr 05 11:09:03 2022 +0200 @@ -105,11 +105,11 @@ baz: foo, bar """ -from __future__ import absolute_import, print_function import contextlib import itertools import os +import pickle from .i18n import _ from .node import ( @@ -133,8 +133,6 @@ stringutil, ) -pickle = util.pickle - def isprintable(obj): """Check if the given object can be directly passed in to formatter's @@ -143,10 +141,10 @@ Returns False if the object is unsupported or must be pre-processed by formatdate(), formatdict(), or formatlist(). """ - return isinstance(obj, (type(None), bool, int, pycompat.long, float, bytes)) + return isinstance(obj, (type(None), bool, int, int, float, bytes)) -class _nullconverter(object): +class _nullconverter: '''convert non-primitive data types to be processed by formatter''' # set to True if context object should be stored as item @@ -177,7 +175,7 @@ return list(data) -class baseformatter(object): +class baseformatter: # set to True if the formater output a strict format that does not support # arbitrary output in the stream. @@ -295,11 +293,11 @@ def _iteritems(data): '''iterate key-value pairs in stable order''' if isinstance(data, dict): - return sorted(pycompat.iteritems(data)) + return sorted(data.items()) return data -class _plainconverter(object): +class _plainconverter: '''convert non-primitive data types to text''' storecontext = False @@ -454,7 +452,7 @@ self._out.write(b"\n]\n") -class _templateconverter(object): +class _templateconverter: '''convert non-primitive data types to be processed by templater''' storecontext = True @@ -543,7 +541,7 @@ @attr.s(frozen=True) -class templatespec(object): +class templatespec: ref = attr.ib() tmpl = attr.ib() mapfile = attr.ib() @@ -560,8 +558,7 @@ def literal_templatespec(tmpl): - if pycompat.ispy3: - assert not isinstance(tmpl, str), b'tmpl must not be a str' + assert not isinstance(tmpl, str), b'tmpl must not be a str' return templatespec(b'', tmpl, None)
--- a/mercurial/graphmod.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/graphmod.py Tue Apr 05 11:09:03 2022 +0200 @@ -17,7 +17,6 @@ Data depends on type. """ -from __future__ import absolute_import from .node import nullrev from .thirdparty import attr @@ -359,7 +358,7 @@ @attr.s -class asciistate(object): +class asciistate: """State of ascii() graph rendering""" seen = attr.ib(init=False, default=attr.Factory(list))
--- a/mercurial/grep.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/grep.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import difflib import errno @@ -36,7 +35,7 @@ yield linenum, mstart - lstart, mend - lstart, body[lstart:lend] -class linestate(object): +class linestate: def __init__(self, line, linenum, colstart, colend): self.line = line self.linenum = linenum @@ -80,7 +79,7 @@ yield (b'+', b[i]) -class grepsearcher(object): +class grepsearcher: """Search files and revisions for lines matching the given pattern Options:
--- a/mercurial/hbisect.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hbisect.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import contextlib
--- a/mercurial/help.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/help.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import itertools import re @@ -126,7 +125,7 @@ '''return a text listing of the given extensions''' rst = [] if exts: - for name, desc in sorted(pycompat.iteritems(exts)): + for name, desc in sorted(exts.items()): if not showdeprecated and any(w in desc for w in _exclkeywords): continue rst.append(b'%s:%s: %s\n' % (b' ' * indent, name, desc)) @@ -281,7 +280,7 @@ name = names[0] if not filtertopic(ui, name): results[b'topics'].append((names[0], header)) - for cmd, entry in pycompat.iteritems(commands.table): + for cmd, entry in commands.table.items(): if len(entry) == 3: summary = entry[2] else: @@ -298,8 +297,8 @@ continue results[b'commands'].append((cmdname, summary)) for name, docs in itertools.chain( - pycompat.iteritems(extensions.enabled(False)), - pycompat.iteritems(extensions.disabled()), + extensions.enabled(False).items(), + extensions.disabled().items(), ): if not docs: continue @@ -312,7 +311,7 @@ except ImportError: # debug message would be printed in extensions.load() continue - for cmd, entry in pycompat.iteritems(getattr(mod, 'cmdtable', {})): + for cmd, entry in getattr(mod, 'cmdtable', {}).items(): if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])): cmdname = cmdutil.parsealiases(cmd)[0] func = entry[0] @@ -665,7 +664,7 @@ h = {} # Command -> string showing synonyms syns = {} - for c, e in pycompat.iteritems(cmdtable): + for c, e in cmdtable.items(): fs = cmdutil.parsealiases(c) f = fs[0] syns[f] = fs
--- a/mercurial/hg.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hg.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -1535,7 +1534,7 @@ ] -class cachedlocalrepo(object): +class cachedlocalrepo: """Holds a localrepository that can be cached and reused.""" def __init__(self, repo):
--- a/mercurial/hgweb/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os @@ -37,7 +36,7 @@ - list of virtual:real tuples (multi-repo view) """ - if isinstance(config, pycompat.unicode): + if isinstance(config, str): raise error.ProgrammingError( b'Mercurial only supports encoded strings: %r' % config ) @@ -55,7 +54,7 @@ return hgwebdir_mod.hgwebdir(config, baseui=baseui) -class httpservice(object): +class httpservice: def __init__(self, ui, app, opts): self.ui = ui self.app = app
--- a/mercurial/hgweb/common.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/common.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import base64 import errno @@ -116,7 +115,7 @@ self.message = message -class continuereader(object): +class continuereader: """File object wrapper to handle HTTP 100-continue. This is used by servers so they automatically handle Expect: 100-continue
--- a/mercurial/hgweb/hgweb_mod.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/hgweb_mod.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import os @@ -111,7 +110,7 @@ return templateutil.mappinglist(reversed(breadcrumb)) -class requestcontext(object): +class requestcontext: """Holds state/context for an individual request. Servers can be multi-threaded. Holding state on the WSGI application @@ -236,7 +235,7 @@ return self.res.sendresponse() -class hgweb(object): +class hgweb: """HTTP server for individual repositories. Instances of this class serve HTTP responses for a particular @@ -413,7 +412,7 @@ if cmd == b'archive': fn = req.qsparams[b'node'] - for type_, spec in pycompat.iteritems(webutil.archivespecs): + for type_, spec in webutil.archivespecs.items(): ext = spec[2] if fn.endswith(ext): req.qsparams[b'node'] = fn[: -len(ext)]
--- a/mercurial/hgweb/hgwebdir_mod.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/hgwebdir_mod.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import gc import os @@ -269,7 +268,7 @@ return templateutil.mappinggenerator(_indexentriesgen, args=args) -class hgwebdir(object): +class hgwebdir: """HTTP server for multiple repositories. Given a configuration, different repositories will be served depending @@ -461,12 +460,9 @@ if real: # Re-parse the WSGI environment to take into account our # repository path component. - uenv = req.rawenv - if pycompat.ispy3: - uenv = { - k.decode('latin1'): v - for k, v in pycompat.iteritems(uenv) - } + uenv = { + k.decode('latin1'): v for k, v in req.rawenv.items() + } req = requestmod.parserequestfromenv( uenv, reponame=virtualrepo,
--- a/mercurial/hgweb/request.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/request.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import # import wsgiref.validate @@ -22,7 +21,7 @@ ) -class multidict(object): +class multidict: """A dict like object that can store multiple values for a key. Used to store parsed request parameters. @@ -78,11 +77,11 @@ return vals[0] def asdictoflists(self): - return {k: list(v) for k, v in pycompat.iteritems(self._items)} + return {k: list(v) for k, v in self._items.items()} @attr.s(frozen=True) -class parsedrequest(object): +class parsedrequest: """Represents a parsed WSGI request. Contains both parsed parameters as well as a handle on the input stream. @@ -161,24 +160,22 @@ # TODO enable this once we fix internal violations. # wsgiref.validate.check_environ(env) - # PEP-0333 states that environment keys and values are native strings - # (bytes on Python 2 and str on Python 3). The code points for the Unicode - # strings on Python 3 must be between \00000-\000FF. We deal with bytes - # in Mercurial, so mass convert string keys and values to bytes. - if pycompat.ispy3: + # PEP-0333 states that environment keys and values are native strings. + # The code points for the Unicode strings on Python 3 must be between + # \00000-\000FF. We deal with bytes in Mercurial, so mass convert string + # keys and values to bytes. + def tobytes(s): + if not isinstance(s, str): + return s + if pycompat.iswindows: + # This is what mercurial.encoding does for os.environ on + # Windows. + return encoding.strtolocal(s) + else: + # This is what is documented to be used for os.environ on Unix. + return pycompat.fsencode(s) - def tobytes(s): - if not isinstance(s, str): - return s - if pycompat.iswindows: - # This is what mercurial.encoding does for os.environ on - # Windows. - return encoding.strtolocal(s) - else: - # This is what is documented to be used for os.environ on Unix. - return pycompat.fsencode(s) - - env = {tobytes(k): tobytes(v) for k, v in pycompat.iteritems(env)} + env = {tobytes(k): tobytes(v) for k, v in env.items()} # Some hosting solutions are emulating hgwebdir, and dispatching directly # to an hgweb instance using this environment variable. This was always @@ -312,7 +309,7 @@ # perform case normalization for us. We just rewrite underscore to dash # so keys match what likely went over the wire. headers = [] - for k, v in pycompat.iteritems(env): + for k, v in env.items(): if k.startswith(b'HTTP_'): headers.append((k[len(b'HTTP_') :].replace(b'_', b'-'), v)) @@ -358,7 +355,7 @@ ) -class offsettrackingwriter(object): +class offsettrackingwriter: """A file object like object that is append only and tracks write count. Instances are bound to a callable. This callable is called with data @@ -391,7 +388,7 @@ return self._offset -class wsgiresponse(object): +class wsgiresponse: """Represents a response to a WSGI request. A response consists of a status line, headers, and a body.
--- a/mercurial/hgweb/server.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/server.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import importlib @@ -53,7 +52,7 @@ return urlreq.unquote(path), query -class _error_logger(object): +class _error_logger: def __init__(self, handler): self.handler = handler @@ -186,18 +185,11 @@ env['REMOTE_ADDR'] = self.client_address[0] env['QUERY_STRING'] = query or '' - if pycompat.ispy3: - if self.headers.get_content_type() is None: - env['CONTENT_TYPE'] = self.headers.get_default_type() - else: - env['CONTENT_TYPE'] = self.headers.get_content_type() - length = self.headers.get('content-length') + if self.headers.get_content_type() is None: + env['CONTENT_TYPE'] = self.headers.get_default_type() else: - if self.headers.typeheader is None: - env['CONTENT_TYPE'] = self.headers.type - else: - env['CONTENT_TYPE'] = self.headers.typeheader - length = self.headers.getheader('content-length') + env['CONTENT_TYPE'] = self.headers.get_content_type() + length = self.headers.get('content-length') if length: env['CONTENT_LENGTH'] = length for header in [ @@ -351,7 +343,7 @@ _mixin = socketserver.ForkingMixIn else: - class _mixin(object): + class _mixin: pass
--- a/mercurial/hgweb/webcommands.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/webcommands.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import copy import mimetypes @@ -47,7 +46,7 @@ commands = {} -class webcommand(object): +class webcommand: """Decorator used to register a web command handler. The decorator takes as its positional arguments the name/path the @@ -564,7 +563,7 @@ l = len(path) abspath = b"/" + path - for full, n in pycompat.iteritems(mf): + for full, n in mf.items(): # the virtual path (working copy path) used for the full # (repository) path f = decodepath(full) @@ -1521,7 +1520,7 @@ early, other = [], [] primary = lambda s: s.partition(b'|')[0] - for c, e in pycompat.iteritems(commands.table): + for c, e in commands.table.items(): doc = _getdoc(e) if b'DEPRECATED' in doc or c.startswith(b'debug'): continue
--- a/mercurial/hgweb/webutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/webutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import copy import difflib @@ -57,7 +56,7 @@ allowed = ui.configlist(b'web', b'allow-archive', untrusted=True) archives = [] - for typ, spec in pycompat.iteritems(archivespecs): + for typ, spec in archivespecs.items(): if typ in allowed or ui.configbool( b'web', b'allow' + typ, untrusted=True ): @@ -100,7 +99,7 @@ step *= 10 -class revnav(object): +class revnav: def __init__(self, repo): """Navigation generation object @@ -864,7 +863,7 @@ def itermaps(self, context): separator = self._start - for key, value in sorted(pycompat.iteritems(self._vars)): + for key, value in sorted(self._vars.items()): yield { b'name': key, b'value': pycompat.bytestr(value),
--- a/mercurial/hgweb/wsgicgi.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/wsgicgi.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # This was originally copied from the public domain code at # http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side -from __future__ import absolute_import import os @@ -24,7 +23,7 @@ procutil.setbinary(procutil.stdin) procutil.setbinary(procutil.stdout) - environ = dict(pycompat.iteritems(os.environ)) # re-exports + environ = dict(os.environ.items()) # re-exports environ.setdefault('PATH_INFO', '') if environ.get('SERVER_SOFTWARE', '').startswith('Microsoft-IIS'): # IIS includes script_name in PATH_INFO
--- a/mercurial/hgweb/wsgiheaders.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hgweb/wsgiheaders.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,7 +9,6 @@ # Regular expression that matches `special' characters in parameters, the # existence of which force quoting of the parameter value. -from __future__ import absolute_import, print_function import re @@ -30,7 +29,7 @@ return param -class Headers(object): +class Headers: """Manage a collection of HTTP response headers""" def __init__(self, headers=None):
--- a/mercurial/hook.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/hook.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import errno @@ -167,7 +166,7 @@ else: env[b'HGPLAIN'] = b'' - for k, v in pycompat.iteritems(args): + for k, v in args.items(): # transaction changes can accumulate MBs of data, so skip it # for external hooks if k == b'changes':
--- a/mercurial/httpconnection.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/httpconnection.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os @@ -27,7 +26,7 @@ urlreq = util.urlreq # moved here from url.py to avoid a cycle -class httpsendfile(object): +class httpsendfile: """This is a wrapper around the objects returned by python's "open". Its purpose is to send file-like objects via HTTP. @@ -94,7 +93,7 @@ bestuser = None bestlen = 0 bestauth = None - for group, auth in pycompat.iteritems(groups): + for group, auth in groups.items(): if user and user != auth.get(b'username', user): # If a username was set in the URI, the entry username # must either match it or be unset
--- a/mercurial/httppeer.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/httppeer.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import io @@ -14,6 +13,7 @@ import socket import struct +from concurrent import futures from .i18n import _ from .pycompat import getattr from . import ( @@ -62,7 +62,7 @@ return result -class _multifile(object): +class _multifile: def __init__(self, *fileobjs): for f in fileobjs: if not util.safehasattr(f, b'length'): @@ -231,15 +231,6 @@ return req, cu, qs -def _reqdata(req): - """Get request data, if any. If no data, returns None.""" - if pycompat.ispy3: - return req.data - if not req.has_data(): - return None - return req.get_data() - - def sendrequest(ui, opener, req): """Send a prepared HTTP request. @@ -274,7 +265,7 @@ % b' %d bytes of commands arguments in headers' % hgargssize ) - data = _reqdata(req) + data = req.data if data is not None: length = getattr(data, 'length', None) if length is None: @@ -538,12 +529,12 @@ raise exception -class queuedcommandfuture(pycompat.futures.Future): +class queuedcommandfuture(futures.Future): """Wraps result() on command futures to trigger submission on call.""" def result(self, timeout=None): if self.done(): - return pycompat.futures.Future.result(self, timeout) + return futures.Future.result(self, timeout) self._peerexecutor.sendcommands()
--- a/mercurial/i18n.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/i18n.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import gettext as gettextmod import locale @@ -86,9 +85,9 @@ cache = _msgcache.setdefault(encoding.encoding, {}) if message not in cache: - if type(message) is pycompat.unicode: + if type(message) is str: # goofy unicode docstrings in test - paragraphs = message.split(u'\n\n') # type: List[pycompat.unicode] + paragraphs = message.split(u'\n\n') # type: List[str] else: # should be ascii, but we have unicode docstrings in test, which # are converted to utf-8 bytes on Python 3.
--- a/mercurial/interfaces/dirstate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/interfaces/dirstate.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import contextlib from . import util as interfaceutil
--- a/mercurial/interfaces/repository.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/interfaces/repository.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from ..i18n import _ from .. import error @@ -389,7 +388,7 @@ @interfaceutil.implementer(ipeerbase) -class peer(object): +class peer: """Base class for peer repositories.""" limitedarguments = False
--- a/mercurial/interfaces/util.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/interfaces/util.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,7 +9,6 @@ # bookkeeping for declaring interfaces. So, we use stubs for various # zope.interface primitives unless instructed otherwise. -from __future__ import absolute_import from .. import encoding @@ -21,11 +20,11 @@ implementer = zi.implementer else: - class Attribute(object): + class Attribute: def __init__(self, __name__, __doc__=b''): pass - class Interface(object): + class Interface: def __init__( self, name, bases=(), attrs=None, __doc__=None, __module__=None ):
--- a/mercurial/keepalive.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/keepalive.py Tue Apr 05 11:09:03 2022 +0200 @@ -82,7 +82,6 @@ # $Id: keepalive.py,v 1.14 2006/04/04 21:00:32 mstenner Exp $ -from __future__ import absolute_import, print_function import collections import errno @@ -108,7 +107,7 @@ DEBUG = None -class ConnectionManager(object): +class ConnectionManager: """ The connection manager must be able to: * keep track of all existing @@ -171,7 +170,7 @@ return dict(self._hostmap) -class KeepAliveHandler(object): +class KeepAliveHandler: def __init__(self, timeout=None): self._cm = ConnectionManager() self._timeout = timeout @@ -194,7 +193,7 @@ def close_all(self): """close all open connections""" - for host, conns in pycompat.iteritems(self._cm.get_all()): + for host, conns in self._cm.get_all().items(): for h in conns: self._cm.remove(h) h.close() @@ -399,12 +398,8 @@ # modification from socket.py def __init__(self, sock, debuglevel=0, strict=0, method=None): - extrakw = {} - if not pycompat.ispy3: - extrakw['strict'] = True - extrakw['buffering'] = True httplib.HTTPResponse.__init__( - self, sock, debuglevel=debuglevel, method=method, **extrakw + self, sock, debuglevel=debuglevel, method=method ) self.fileno = sock.fileno self.code = None @@ -794,7 +789,7 @@ global DEBUG dbbackup = DEBUG - class FakeLogger(object): + class FakeLogger: def debug(self, msg, *args): print(msg % args)
--- a/mercurial/linelog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/linelog.py Tue Apr 05 11:09:03 2022 +0200 @@ -18,7 +18,6 @@ deletion is performed on the file, a jump instruction is used to patch in a new body of annotate information. """ -from __future__ import absolute_import, print_function import abc import struct @@ -34,7 +33,7 @@ @attr.s -class lineinfo(object): +class lineinfo: # Introducing revision of this line. rev = attr.ib() # Line number for this line in its introducing revision. @@ -44,7 +43,7 @@ @attr.s -class annotateresult(object): +class annotateresult: rev = attr.ib() lines = attr.ib() _eof = attr.ib() @@ -53,7 +52,7 @@ return iter(self.lines) -class _llinstruction(object): # pytype: disable=ignored-metaclass +class _llinstruction: # pytype: disable=ignored-metaclass __metaclass__ = abc.ABCMeta @@ -234,7 +233,7 @@ raise NotImplementedError(b'Unimplemented opcode %r' % opcode) -class linelog(object): +class linelog: """Efficient cache for per-line history information.""" def __init__(self, program=None, maxrev=0):
--- a/mercurial/localrepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/localrepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import functools @@ -16,6 +15,7 @@ import time import weakref +from concurrent import futures from .i18n import _ from .node import ( bin, @@ -251,7 +251,7 @@ @interfaceutil.implementer(repository.ipeercommandexecutor) -class localcommandexecutor(object): +class localcommandexecutor: def __init__(self, peer): self._peer = peer self._sent = False @@ -278,7 +278,7 @@ # method on the peer and return a resolved future. fn = getattr(self._peer, pycompat.sysstr(command)) - f = pycompat.futures.Future() + f = futures.Future() try: result = fn(**pycompat.strkwargs(args)) @@ -1215,7 +1215,7 @@ @interfaceutil.implementer(repository.ilocalrepositoryfilestorage) -class revlogfilestorage(object): +class revlogfilestorage: """File storage when using revlogs.""" def file(self, path): @@ -1226,7 +1226,7 @@ @interfaceutil.implementer(repository.ilocalrepositoryfilestorage) -class revlognarrowfilestorage(object): +class revlognarrowfilestorage: """File storage when using revlogs and narrow files.""" def file(self, path): @@ -1259,7 +1259,7 @@ @interfaceutil.implementer(repository.ilocalrepositorymain) -class localrepository(object): +class localrepository: """Main class for representing local repositories. All local repositories are instances of this class. @@ -2044,7 +2044,7 @@ # This simplifies its cache management by having one decorated # function (this one) and the rest simply fetch things from it. - class tagscache(object): + class tagscache: def __init__(self): # These two define the set of tags for this repository. tags # maps tag name to node; tagtypes maps tag name to 'global' or @@ -2068,7 +2068,7 @@ else: tags = self._tagscache.tags rev = self.changelog.rev - for k, v in pycompat.iteritems(tags): + for k, v in tags.items(): try: # ignore tags to unknown nodes rev(v) @@ -2103,13 +2103,12 @@ # writing to the cache), but the rest of Mercurial wants them in # local encoding. tags = {} - for (name, (node, hist)) in pycompat.iteritems(alltags): + for (name, (node, hist)) in alltags.items(): if node != self.nullid: tags[encoding.tolocal(name)] = node tags[b'tip'] = self.changelog.tip() tagtypes = { - encoding.tolocal(name): value - for (name, value) in pycompat.iteritems(tagtypes) + encoding.tolocal(name): value for (name, value) in tagtypes.items() } return (tags, tagtypes) @@ -2128,7 +2127,7 @@ '''return a list of tags ordered by revision''' if not self._tagscache.tagslist: l = [] - for t, n in pycompat.iteritems(self.tags()): + for t, n in self.tags().items(): l.append((self.changelog.rev(n), t, n)) self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)] @@ -2138,9 +2137,9 @@ '''return the tags associated with a node''' if not self._tagscache.nodetagscache: nodetagscache = {} - for t, n in pycompat.iteritems(self._tagscache.tags): + for t, n in self._tagscache.tags.items(): nodetagscache.setdefault(n, []).append(t) - for tags in pycompat.itervalues(nodetagscache): + for tags in nodetagscache.values(): tags.sort() self._tagscache.nodetagscache = nodetagscache return self._tagscache.nodetagscache.get(node, []) @@ -2256,7 +2255,7 @@ mf = matchmod.match(self.root, b'', [pat]) fn = None params = cmd - for name, filterfn in pycompat.iteritems(self._datafilters): + for name, filterfn in self._datafilters.items(): if cmd.startswith(name): fn = filterfn params = cmd[len(name) :].lstrip() @@ -3913,7 +3912,7 @@ # # But we have to allow the close() method because some constructors # of repos call close() on repo references. - class poisonedrepository(object): + class poisonedrepository: def __getattribute__(self, item): if item == 'close': return object.__getattribute__(self, item)
--- a/mercurial/lock.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/lock.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import errno @@ -174,7 +173,7 @@ return l -class lock(object): +class lock: """An advisory lock held by one process to control access to a set of files. Non-cooperating processes or incorrectly written scripts can ignore Mercurial's locking scheme and stomp all over the
--- a/mercurial/logcmdutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/logcmdutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import itertools import os @@ -228,7 +227,7 @@ ) -class changesetdiffer(object): +class changesetdiffer: """Generate diff of changeset with pre-configured filtering functions""" def _makefilematcher(self, ctx): @@ -262,7 +261,7 @@ return b' '.join(labels) -class changesetprinter(object): +class changesetprinter: '''show changeset information when templating not requested.''' def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False): @@ -328,7 +327,7 @@ if branch != b'default': self.ui.write(columns[b'branch'] % branch, label=b'log.branch') - for nsname, ns in pycompat.iteritems(self.repo.names): + for nsname, ns in self.repo.names.items(): # branches has special logic already handled above, so here we just # skip it if nsname == b'branches': @@ -707,7 +706,7 @@ @attr.s -class walkopts(object): +class walkopts: """Options to configure a set of revisions and file matcher factory to scan revision/file history """ @@ -992,7 +991,7 @@ opts[b'_patslog'] = list(wopts.pats) expr = [] - for op, val in sorted(pycompat.iteritems(opts)): + for op, val in sorted(opts.items()): if not val: continue revop, listop = _opt2logrevset[op]
--- a/mercurial/logexchange.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/logexchange.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,12 +6,10 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .node import hex from . import ( - pycompat, util, vfs as vfsmod, ) @@ -78,7 +76,7 @@ if oldpath != remotepath: f.write(b'%s\0%s\0%s\n' % (node, oldpath, rname)) - for name, node in sorted(pycompat.iteritems(names)): + for name, node in sorted(names.items()): if nametype == b"branches": for n in node: f.write(b'%s\0%s\0%s\n' % (n, remotepath, name)) @@ -160,7 +158,7 @@ with remoterepo.commandexecutor() as e: branchmap = e.callcommand(b'branchmap', {}).result() - for branch, nodes in pycompat.iteritems(branchmap): + for branch, nodes in branchmap.items(): bmap[branch] = [] for node in nodes: if node in repo and not repo[node].obsolete():
--- a/mercurial/loggingutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/loggingutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno @@ -74,7 +73,7 @@ return b'*' in tracked or event in tracked -class filelogger(object): +class filelogger: """Basic logger backed by physical file with optional rotation""" def __init__(self, vfs, name, tracked, maxfiles=0, maxsize=0): @@ -105,7 +104,7 @@ ) -class fileobjectlogger(object): +class fileobjectlogger: """Basic logger backed by file-like object""" def __init__(self, fp, tracked): @@ -130,7 +129,7 @@ ) -class proxylogger(object): +class proxylogger: """Forward log events to another logger to be set later""" def __init__(self):
--- a/mercurial/lsprof.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/lsprof.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,10 +1,7 @@ -from __future__ import absolute_import, print_function - import _lsprof import sys from .pycompat import getattr -from . import pycompat Profiler = _lsprof.Profiler @@ -25,7 +22,7 @@ return Stats(p.getstats()) -class Stats(object): +class Stats: """XXX docstring""" def __init__(self, data): @@ -120,13 +117,11 @@ def label(code): if isinstance(code, str): - if sys.version_info.major >= 3: - code = code.encode('latin-1') - return code + return code.encode('latin-1') try: mname = _fn2mod[code.co_filename] except KeyError: - for k, v in list(pycompat.iteritems(sys.modules)): + for k, v in list(sys.modules.items()): if v is None: continue if not isinstance(getattr(v, '__file__', None), str): @@ -139,7 +134,4 @@ res = '%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name) - if sys.version_info.major >= 3: - res = res.encode('latin-1') - - return res + return res.encode('latin-1')
--- a/mercurial/lsprofcalltree.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/lsprofcalltree.py Tue Apr 05 11:09:03 2022 +0200 @@ -10,7 +10,6 @@ of the GNU General Public License, incorporated herein by reference. """ -from __future__ import absolute_import from . import pycompat @@ -27,7 +26,7 @@ ) -class KCacheGrind(object): +class KCacheGrind: def __init__(self, profiler): self.data = profiler.getstats() self.out_file = None
--- a/mercurial/mail.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/mail.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import email import email.charset @@ -468,43 +467,28 @@ return mimetextqp(s, 'plain', cs) -if pycompat.ispy3: - - Generator = email.generator.BytesGenerator - - def parse(fp): - # type: (Any) -> email.message.Message - ep = email.parser.Parser() - # disable the "universal newlines" mode, which isn't binary safe. - # I have no idea if ascii/surrogateescape is correct, but that's - # what the standard Python email parser does. - fp = io.TextIOWrapper( - fp, encoding='ascii', errors='surrogateescape', newline=chr(10) - ) - try: - return ep.parse(fp) - finally: - fp.detach() - - def parsebytes(data): - # type: (bytes) -> email.message.Message - ep = email.parser.BytesParser() - return ep.parsebytes(data) +Generator = email.generator.BytesGenerator -else: - - Generator = email.generator.Generator +def parse(fp): + # type: (Any) -> email.message.Message + ep = email.parser.Parser() + # disable the "universal newlines" mode, which isn't binary safe. + # I have no idea if ascii/surrogateescape is correct, but that's + # what the standard Python email parser does. + fp = io.TextIOWrapper( + fp, encoding='ascii', errors='surrogateescape', newline=chr(10) + ) + try: + return ep.parse(fp) + finally: + fp.detach() - def parse(fp): - # type: (Any) -> email.message.Message - ep = email.parser.Parser() - return ep.parse(fp) - def parsebytes(data): - # type: (str) -> email.message.Message - ep = email.parser.Parser() - return ep.parsestr(data) +def parsebytes(data): + # type: (bytes) -> email.message.Message + ep = email.parser.BytesParser() + return ep.parsebytes(data) def headdecode(s):
--- a/mercurial/manifest.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/manifest.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import heapq import itertools @@ -85,7 +84,7 @@ return b''.join(lines) -class lazymanifestiter(object): +class lazymanifestiter: def __init__(self, lm): self.pos = 0 self.lm = lm @@ -108,7 +107,7 @@ __next__ = next -class lazymanifestiterentries(object): +class lazymanifestiterentries: def __init__(self, lm): self.lm = lm self.pos = 0 @@ -159,7 +158,7 @@ _manifestflags = {b'', b'l', b't', b'x'} -class _lazymanifest(object): +class _lazymanifest: """A pure python manifest backed by a byte string. It is supplimented with internal lists as it is modified, until it is compacted back to a pure byte string. @@ -474,7 +473,7 @@ @interfaceutil.implementer(repository.imanifestdict) -class manifestdict(object): +class manifestdict: def __init__(self, nodelen, data=b''): self._nodelen = nodelen self._lm = _lazymanifest(nodelen, data) @@ -797,7 +796,7 @@ @interfaceutil.implementer(repository.imanifestdict) -class treemanifest(object): +class treemanifest: def __init__(self, nodeconstants, dir=b'', text=b''): self._dir = dir self.nodeconstants = nodeconstants @@ -827,9 +826,7 @@ def _loadalllazy(self): selfdirs = self._dirs subpath = self._subpath - for d, (node, readsubtree, docopy) in pycompat.iteritems( - self._lazydirs - ): + for d, (node, readsubtree, docopy) in self._lazydirs.items(): if docopy: selfdirs[d] = readsubtree(subpath(d), node).copy() else: @@ -868,11 +865,11 @@ differs, load it in both """ toloadlazy = [] - for d, v1 in pycompat.iteritems(t1._lazydirs): + for d, v1 in t1._lazydirs.items(): v2 = t2._lazydirs.get(d) if not v2 or v2[0] != v1[0]: toloadlazy.append(d) - for d, v1 in pycompat.iteritems(t2._lazydirs): + for d, v1 in t2._lazydirs.items(): if d not in t1._lazydirs: toloadlazy.append(d) @@ -954,7 +951,7 @@ if p in self._files: yield self._subpath(p), n else: - for f, sn in pycompat.iteritems(n): + for f, sn in n.items(): yield f, sn iteritems = items @@ -1105,11 +1102,10 @@ def _copyfunc(s): self._load() s._lazydirs = { - d: (n, r, True) - for d, (n, r, c) in pycompat.iteritems(self._lazydirs) + d: (n, r, True) for d, (n, r, c) in self._lazydirs.items() } sdirs = s._dirs - for d, v in pycompat.iteritems(self._dirs): + for d, v in self._dirs.items(): sdirs[d] = v.copy() s._files = dict.copy(self._files) s._flags = dict.copy(self._flags) @@ -1137,7 +1133,7 @@ t1._load() t2._load() self._loaddifflazy(t1, t2) - for d, m1 in pycompat.iteritems(t1._dirs): + for d, m1 in t1._dirs.items(): if d in t2._dirs: m2 = t2._dirs[d] _filesnotin(m1, m2) @@ -1250,7 +1246,7 @@ ret._flags[fn] = self._flags[fn] visit = self._loadchildrensetlazy(visit) - for dir, subm in pycompat.iteritems(self._dirs): + for dir, subm in self._dirs.items(): if visit and dir[:-1] not in visit: continue m = subm._matches_inner(match) @@ -1295,15 +1291,15 @@ t2._load() self._loaddifflazy(t1, t2) - for d, m1 in pycompat.iteritems(t1._dirs): + for d, m1 in t1._dirs.items(): m2 = t2._dirs.get(d, emptytree) stack.append((m1, m2)) - for d, m2 in pycompat.iteritems(t2._dirs): + for d, m2 in t2._dirs.items(): if d not in t1._dirs: stack.append((emptytree, m2)) - for fn, n1 in pycompat.iteritems(t1._files): + for fn, n1 in t1._files.items(): fl1 = t1._flags.get(fn, b'') n2 = t2._files.get(fn, None) fl2 = t2._flags.get(fn, b'') @@ -1312,7 +1308,7 @@ elif clean: result[t1._subpath(fn)] = None - for fn, n2 in pycompat.iteritems(t2._files): + for fn, n2 in t2._files.items(): if fn not in t1._files: fl2 = t2._flags.get(fn, b'') result[t2._subpath(fn)] = ((None, b''), (n2, fl2)) @@ -1362,9 +1358,7 @@ """ self._load() flags = self.flags - lazydirs = [ - (d[:-1], v[0], b't') for d, v in pycompat.iteritems(self._lazydirs) - ] + lazydirs = [(d[:-1], v[0], b't') for d, v in self._lazydirs.items()] dirs = [(d[:-1], self._dirs[d]._node, b't') for d in self._dirs] files = [(f, self._files[f], flags(f)) for f in self._files] return _text(sorted(dirs + files + lazydirs)) @@ -1393,7 +1387,7 @@ visit = self._loadchildrensetlazy(visit) if visit == b'this' or visit == b'all': visit = None - for d, subm in pycompat.iteritems(self._dirs): + for d, subm in self._dirs.items(): if visit and d[:-1] not in visit: continue subp1 = getnode(m1, d) @@ -1416,7 +1410,7 @@ self._load() # OPT: use visitchildrenset to avoid loading everything. self._loadalllazy() - for d, subm in pycompat.iteritems(self._dirs): + for d, subm in self._dirs.items(): for subtree in subm.walksubtrees(matcher=matcher): yield subtree @@ -1556,7 +1550,7 @@ @interfaceutil.implementer(repository.imanifeststorage) -class manifestrevlog(object): +class manifestrevlog: """A revlog that stores manifest texts. This is responsible for caching the full-text manifest contents. """ @@ -1914,7 +1908,7 @@ @interfaceutil.implementer(repository.imanifestlog) -class manifestlog(object): +class manifestlog: """A collection class representing the collection of manifest snapshots referenced by commits in the repository. @@ -2013,7 +2007,7 @@ @interfaceutil.implementer(repository.imanifestrevisionwritable) -class memmanifestctx(object): +class memmanifestctx: def __init__(self, manifestlog): self._manifestlog = manifestlog self._manifestdict = manifestdict(manifestlog.nodeconstants.nodelen) @@ -2043,7 +2037,7 @@ @interfaceutil.implementer(repository.imanifestrevisionstored) -class manifestctx(object): +class manifestctx: """A class representing a single revision of a manifest, including its contents, its parent revs, and its linkrev. """ @@ -2123,7 +2117,7 @@ @interfaceutil.implementer(repository.imanifestrevisionwritable) -class memtreemanifestctx(object): +class memtreemanifestctx: def __init__(self, manifestlog, dir=b''): self._manifestlog = manifestlog self._dir = dir @@ -2158,7 +2152,7 @@ @interfaceutil.implementer(repository.imanifestrevisionstored) -class treemanifestctx(object): +class treemanifestctx: def __init__(self, manifestlog, dir, node): self._manifestlog = manifestlog self._dir = dir @@ -2249,7 +2243,7 @@ m0 = self._manifestlog.get(self._dir, store.node(r0)).read() m1 = self.read() md = treemanifest(self._manifestlog.nodeconstants, dir=self._dir) - for f, ((n0, fl0), (n1, fl1)) in pycompat.iteritems(m0.diff(m1)): + for f, ((n0, fl0), (n1, fl1)) in m0.diff(m1).items(): if n1: md[f] = n1 if fl1:
--- a/mercurial/match.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/match.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import bisect import copy @@ -383,7 +382,7 @@ return kindpats -class basematcher(object): +class basematcher: def __init__(self, badfn=None): if badfn is not None: self.bad = badfn @@ -584,10 +583,7 @@ if b'' in prefix_set: return True - if pycompat.ispy3: - sl = ord(b'/') - else: - sl = '/' + sl = ord(b'/') # We already checked that path isn't in prefix_set exactly, so # `path[len(pf)] should never raise IndexError. @@ -663,7 +659,7 @@ # This is basically a reimplementation of pathutil.dirs that stores the # children instead of just a count of them, plus a small optional optimization # to avoid some directories we don't need. -class _dirchildren(object): +class _dirchildren: def __init__(self, paths, onlyinclude=None): self._dirs = {} self._onlyinclude = onlyinclude or [] @@ -1615,7 +1611,7 @@ patterns = [] fp = open(filepath, b'rb') - for lineno, line in enumerate(util.iterfile(fp), start=1): + for lineno, line in enumerate(fp, start=1): if b"#" in line: global _commentre if not _commentre: @@ -1642,7 +1638,7 @@ continue linesyntax = syntax - for s, rels in pycompat.iteritems(syntaxes): + for s, rels in syntaxes.items(): if line.startswith(rels): linesyntax = rels line = line[len(rels) :]
--- a/mercurial/mdiff.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/mdiff.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re import struct @@ -38,7 +37,7 @@ # TODO: this looks like it could be an attrs, which might help pytype -class diffopts(object): +class diffopts: """context is the number of context lines text treats all files as text showfunc enables diff -p output
--- a/mercurial/merge.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/merge.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import errno @@ -67,7 +66,7 @@ ) -class _unknowndirschecker(object): +class _unknowndirschecker: """ Look for any unknown files or directories that may have a path conflict with a file. If any path prefix of the file exists as a file or link, @@ -538,7 +537,7 @@ raise error.StateError(msg % f) -class mergeresult(object): +class mergeresult: """An object representing result of merging manifests. It has information about what actions need to be performed on dirstate @@ -626,9 +625,7 @@ args, msg = self._actionmapping[a][f] yield f, args, msg else: - for f, (args, msg) in pycompat.iteritems( - self._actionmapping[a] - ): + for f, (args, msg) in self._actionmapping[a].items(): yield f, args, msg def len(self, actions=None): @@ -644,10 +641,10 @@ def filemap(self, sort=False): if sorted: - for key, val in sorted(pycompat.iteritems(self._filemapping)): + for key, val in sorted(self._filemapping.items()): yield key, val else: - for key, val in pycompat.iteritems(self._filemapping): + for key, val in self._filemapping.items(): yield key, val def addcommitinfo(self, filename, key, value): @@ -672,15 +669,15 @@ """returns a dictionary of actions to be perfomed with action as key and a list of files and related arguments as values""" res = collections.defaultdict(list) - for a, d in pycompat.iteritems(self._actionmapping): - for f, (args, msg) in pycompat.iteritems(d): + for a, d in self._actionmapping.items(): + for f, (args, msg) in d.items(): res[a].append((f, args, msg)) return res def setactions(self, actions): self._filemapping = actions self._actionmapping = collections.defaultdict(dict) - for f, (act, data, msg) in pycompat.iteritems(self._filemapping): + for f, (act, data, msg) in self._filemapping.items(): self._actionmapping[act][f] = data, msg def hasconflicts(self): @@ -787,7 +784,7 @@ relevantfiles = set(ma.diff(m2).keys()) # For copied and moved files, we need to add the source file too. - for copykey, copyvalue in pycompat.iteritems(branch_copies1.copy): + for copykey, copyvalue in branch_copies1.copy.items(): if copyvalue in relevantfiles: relevantfiles.add(copykey) for movedirkey in branch_copies1.movewithdir: @@ -797,7 +794,7 @@ diff = m1.diff(m2, match=matcher) - for f, ((n1, fl1), (n2, fl2)) in pycompat.iteritems(diff): + for f, ((n1, fl1), (n2, fl2)) in diff.items(): if n1 and n2: # file exists on both local and remote side if f not in ma: # TODO: what if they're renamed from different sources? @@ -1470,7 +1467,7 @@ @attr.s(frozen=True) -class updateresult(object): +class updateresult: updatedcount = attr.ib() mergedcount = attr.ib() removedcount = attr.ib() @@ -1512,7 +1509,7 @@ ms = wctx.mergestate(clean=True) ms.start(wctx.p1().node(), mctx.node(), labels) - for f, op in pycompat.iteritems(mresult.commitinfo): + for f, op in mresult.commitinfo.items(): # the other side of filenode was choosen while merging, store this in # mergestate so that it can be reused on commit ms.addcommitinfo(f, op) @@ -2073,7 +2070,7 @@ _checkcollision(repo, wc.manifest(), mresult) # divergent renames - for f, fl in sorted(pycompat.iteritems(mresult.diverge)): + for f, fl in sorted(mresult.diverge.items()): repo.ui.warn( _( b"note: possible conflict - %s was renamed " @@ -2085,7 +2082,7 @@ repo.ui.warn(b" %s\n" % nf) # rename and delete - for f, fl in sorted(pycompat.iteritems(mresult.renamedelete)): + for f, fl in sorted(mresult.renamedelete.items()): repo.ui.warn( _( b"note: possible conflict - %s was deleted " @@ -2125,7 +2122,7 @@ if updatedirstate: if extraactions: - for k, acts in pycompat.iteritems(extraactions): + for k, acts in extraactions.items(): for a in acts: mresult.addfile(a[0], k, *a[1:]) if k == mergestatemod.ACTION_GET and wantfiledata: @@ -2196,10 +2193,10 @@ getfiledata = None else: now_sec = now[0] - for f, m in pycompat.iteritems(getfiledata): + for f, m in getfiledata.items(): if m is not None and m[2][0] >= now_sec: ambiguous_mtime[f] = (m[0], m[1], None) - for f, m in pycompat.iteritems(ambiguous_mtime): + for f, m in ambiguous_mtime.items(): getfiledata[f] = m repo.setparents(fp1, fp2)
--- a/mercurial/mergestate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/mergestate.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import collections import errno import shutil @@ -15,7 +13,6 @@ from . import ( error, filemerge, - pycompat, util, ) from .utils import hashutil @@ -103,7 +100,7 @@ CHANGE_MODIFIED = b'modified' -class MergeAction(object): +class MergeAction: """represent an "action" merge need to take for a given file Attributes: @@ -197,7 +194,7 @@ ) -class _mergestate_base(object): +class _mergestate_base: """track 3-way merge state of individual files The merge state is stored on disk when needed. Two files are used: one with @@ -365,7 +362,7 @@ def unresolved(self): """Obtain the paths of unresolved files.""" - for f, entry in pycompat.iteritems(self._state): + for f, entry in self._state.items(): if entry[0] in ( MERGE_RECORD_UNRESOLVED, MERGE_RECORD_UNRESOLVED_PATH, @@ -469,7 +466,7 @@ """return counts for updated, merged and removed files in this session""" updated, merged, removed = 0, 0, 0 - for r, action in pycompat.itervalues(self._results): + for r, action in self._results.values(): if r is None: updated += 1 elif r == 0: @@ -492,7 +489,7 @@ ACTION_ADD_MODIFIED: [], ACTION_GET: [], } - for f, (r, action) in pycompat.iteritems(self._results): + for f, (r, action) in self._results.items(): if action is not None: actions[action].append((f, None, b"merge result")) return actions @@ -692,7 +689,7 @@ # the type of state that is stored, and capital-letter records are used # to prevent older versions of Mercurial that do not support the feature # from loading them. - for filename, v in pycompat.iteritems(self._state): + for filename, v in self._state.items(): if v[0] in ( MERGE_RECORD_UNRESOLVED_PATH, MERGE_RECORD_RESOLVED_PATH, @@ -716,9 +713,9 @@ else: # Normal files. These are stored in 'F' records. records.append((RECORD_MERGED, b'\0'.join([filename] + v))) - for filename, extras in sorted(pycompat.iteritems(self._stateextras)): + for filename, extras in sorted(self._stateextras.items()): rawextras = b'\0'.join( - b'%s\0%s' % (k, v) for k, v in pycompat.iteritems(extras) + b'%s\0%s' % (k, v) for k, v in extras.items() ) records.append( (RECORD_FILE_VALUES, b'%s\0%s' % (filename, rawextras))
--- a/mercurial/mergeutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/mergeutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _
--- a/mercurial/metadata.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/metadata.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import multiprocessing import struct @@ -23,7 +22,7 @@ ) -class ChangingFiles(object): +class ChangingFiles: """A class recording the changes made to files by a changeset Actions performed on files are gathered into 3 sets:
--- a/mercurial/minifileset.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/minifileset.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from . import (
--- a/mercurial/minirst.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/minirst.py Tue Apr 05 11:09:03 2022 +0200 @@ -18,7 +18,6 @@ when adding support for new constructs. """ -from __future__ import absolute_import import re
--- a/mercurial/namespaces.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/namespaces.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,8 +1,5 @@ -from __future__ import absolute_import - from .i18n import _ from . import ( - pycompat, registrar, templatekw, util, @@ -19,7 +16,7 @@ return [val] -class namespaces(object): +class namespaces: """provides an interface to register and operate on multiple namespaces. See the namespace class below for details on the namespace object. @@ -87,7 +84,7 @@ return self._names.get(namespace, default) def items(self): - return pycompat.iteritems(self._names) + return self._names.items() iteritems = items @@ -120,14 +117,14 @@ Raises a KeyError if there is no such node. """ - for ns, v in pycompat.iteritems(self._names): + for ns, v in self._names.items(): n = v.singlenode(repo, name) if n: return n raise KeyError(_(b'no such name: %s') % name) -class namespace(object): +class namespace: """provides an interface to a namespace Namespaces are basically generic many-to-many mapping between some
--- a/mercurial/narrowspec.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/narrowspec.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from .pycompat import getattr
--- a/mercurial/node.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/node.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import binascii @@ -32,7 +31,7 @@ wdirrev = 0x7FFFFFFF -class sha1nodeconstants(object): +class sha1nodeconstants: nodelen = 20 # In hex, this is '0000000000000000000000000000000000000000'
--- a/mercurial/obsolete.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/obsolete.py Tue Apr 05 11:09:03 2022 +0200 @@ -67,7 +67,6 @@ comment associated with each format for details. """ -from __future__ import absolute_import import errno import struct @@ -249,7 +248,7 @@ # if content cannot be translated to nodeid drop the data. parents = None - metadata = tuple(sorted(pycompat.iteritems(metadata))) + metadata = tuple(sorted(metadata.items())) yield (pre, sucs, flags, metadata, date, parents) @@ -279,7 +278,7 @@ """Return encoded metadata string to string mapping. Assume no ':' in key and no '\0' in both key and value.""" - for key, value in pycompat.iteritems(meta): + for key, value in meta.items(): if b':' in key or b'\0' in key: raise ValueError(b"':' and '\0' are forbidden in metadata key'") if b'\0' in value: @@ -542,7 +541,7 @@ ) -class obsstore(object): +class obsstore: """Store obsolete markers Markers can be accessed with two mappings: @@ -653,7 +652,7 @@ 'in-marker cycle with %s' % pycompat.sysstr(hex(prec)) ) - metadata = tuple(sorted(pycompat.iteritems(metadata))) + metadata = tuple(sorted(metadata.items())) for k, v in metadata: try: # might be better to reject non-ASCII keys
--- a/mercurial/obsutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/obsutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re @@ -19,7 +18,6 @@ encoding, error, phases, - pycompat, util, ) from .utils import dateutil @@ -58,7 +56,7 @@ usingsha256 = 2 -class marker(object): +class marker: """Wrap obsolete marker raw data""" def __init__(self, repo, data): @@ -998,7 +996,7 @@ base[tuple(nsuccset)] = n return [ {b'divergentnodes': divset, b'commonpredecessor': b} - for divset, b in pycompat.iteritems(base) + for divset, b in base.items() ]
--- a/mercurial/parser.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/parser.py Tue Apr 05 11:09:03 2022 +0200 @@ -16,7 +16,6 @@ # an action is a tree node name, a tree label, and an optional match # __call__(program) parses program into a labeled tree -from __future__ import absolute_import, print_function from .i18n import _ from . import ( @@ -26,7 +25,7 @@ from .utils import stringutil -class parser(object): +class parser: def __init__(self, elements, methods=None): self._elements = elements self._methods = methods @@ -416,7 +415,7 @@ return inst.message -class alias(object): +class alias: """Parsed result of alias""" def __init__(self, name, args, err, replacement): @@ -430,7 +429,7 @@ self.warned = False -class basealiasrules(object): +class basealiasrules: """Parsing and expansion rule set of aliases This is a helper for fileset/revset/template aliases. A concrete rule set
--- a/mercurial/patch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/patch.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import collections import contextlib @@ -150,7 +149,7 @@ def remainder(cur): yield chunk(cur) - class fiter(object): + class fiter: def __init__(self, fp): self.fp = fp @@ -343,7 +342,7 @@ return data -class patchmeta(object): +class patchmeta: """Patched file metadata 'op' is the performed operation within ADD, DELETE, RENAME, MODIFY @@ -436,7 +435,7 @@ return gitpatches -class linereader(object): +class linereader: # simple class to allow pushing lines back into the input stream def __init__(self, fp): self.fp = fp @@ -457,7 +456,7 @@ return iter(self.readline, b'') -class abstractbackend(object): +class abstractbackend: def __init__(self, ui): self.ui = ui @@ -593,7 +592,7 @@ return sorted(self.changed) -class filestore(object): +class filestore: def __init__(self, maxsize=None): self.opener = None self.files = {} @@ -682,7 +681,7 @@ eolmodes = [b'strict', b'crlf', b'lf', b'auto'] -class patchfile(object): +class patchfile: def __init__(self, ui, gp, backend, store, eolmode=b'strict'): self.fname = gp.path self.eolmode = eolmode @@ -915,7 +914,7 @@ return len(self.rej) -class header(object): +class header: """patch header""" diffgit_re = re.compile(b'diff --git a/(.*) b/(.*)$') @@ -995,7 +994,7 @@ ) -class recordhunk(object): +class recordhunk: """patch hunk XXX shouldn't we merge this with the other hunk class? @@ -1260,7 +1259,7 @@ # Remove comment lines patchfp = open(patchfn, 'rb') ncpatchfp = stringio() - for line in util.iterfile(patchfp): + for line in patchfp: line = util.fromnativeeol(line) if not line.startswith(b'#'): ncpatchfp.write(line) @@ -1343,18 +1342,14 @@ fixoffset += chunk.removed - chunk.added return ( sum( - [ - h - for h in pycompat.itervalues(applied) - if h[0].special() or len(h) > 1 - ], + [h for h in applied.values() if h[0].special() or len(h) > 1], [], ), {}, ) -class hunk(object): +class hunk: def __init__(self, desc, num, lr, context): self.number = num self.desc = desc @@ -1582,7 +1577,7 @@ return old, oldstart, new, newstart -class binhunk(object): +class binhunk: """A binary patch file.""" def __init__(self, lr, fname): @@ -1763,7 +1758,7 @@ +9 """ - class parser(object): + class parser: """patch parsing state machine""" def __init__(self): @@ -2348,7 +2343,7 @@ ui.debug(b'Using external patch tool: %s\n' % cmd) fp = procutil.popen(cmd, b'rb') try: - for line in util.iterfile(fp): + for line in fp: line = line.rstrip() ui.note(line + b'\n') if line.startswith(b'patching file '): @@ -2644,11 +2639,7 @@ if copysourcematch: # filter out copies where source side isn't inside the matcher # (copies.pathcopies() already filtered out the destination) - copy = { - dst: src - for dst, src in pycompat.iteritems(copy) - if copysourcematch(src) - } + copy = {dst: src for dst, src in copy.items() if copysourcematch(src)} modifiedset = set(modified) addedset = set(added)
--- a/mercurial/pathutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pathutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import contextlib import errno import os @@ -33,7 +31,7 @@ return encoding.hfsignoreclean(s.lower()) -class pathauditor(object): +class pathauditor: """ensure that a filesystem path contains no banned components. the following properties of a path are checked: @@ -316,7 +314,7 @@ yield b'' -class dirs(object): +class dirs: '''a multiset of directory names from a set of file paths''' def __init__(self, map, only_tracked=False): @@ -326,7 +324,7 @@ self._dirs = {} addpath = self.addpath if isinstance(map, dict) and only_tracked: - for f, s in pycompat.iteritems(map): + for f, s in map.items(): if s.state != b'r': addpath(f) elif only_tracked:
--- a/mercurial/phases.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/phases.py Tue Apr 05 11:09:03 2022 +0200 @@ -100,7 +100,6 @@ """ -from __future__ import absolute_import import errno import struct @@ -220,7 +219,7 @@ The revision lists are encoded as (phase, root) pairs. """ binarydata = [] - for phase, nodes in pycompat.iteritems(phasemapping): + for phase, nodes in phasemapping.items(): for head in nodes: binarydata.append(_fphasesentry.pack(phase, head)) return b''.join(binarydata) @@ -344,7 +343,7 @@ data.insert(low + 1, (pycompat.xrange(rev, rev + 1), t)) -class phasecache(object): +class phasecache: def __init__(self, repo, phasedefaults, _load=True): # type: (localrepo.localrepository, Optional[Phasedefaults], bool) -> None if _load: @@ -364,9 +363,7 @@ self.invalidate() self.loadphaserevs(repo) return any( - revs - for phase, revs in pycompat.iteritems(self.phaseroots) - if phase != public + revs for phase, revs in self.phaseroots.items() if phase != public ) def nonpublicphaseroots(self, repo): @@ -384,7 +381,7 @@ return set().union( *[ revs - for phase, revs in pycompat.iteritems(self.phaseroots) + for phase, revs in self.phaseroots.items() if phase != public ] ) @@ -529,7 +526,7 @@ f.close() def _write(self, fp): - for phase, roots in pycompat.iteritems(self.phaseroots): + for phase, roots in self.phaseroots.items(): for h in sorted(roots): fp.write(b'%i %s\n' % (phase, hex(h))) self.dirty = False @@ -613,7 +610,7 @@ def retractboundary(self, repo, tr, targetphase, nodes): oldroots = { phase: revs - for phase, revs in pycompat.iteritems(self.phaseroots) + for phase, revs in self.phaseroots.items() if phase <= targetphase } if tr is None: @@ -691,7 +688,7 @@ """ filtered = False has_node = repo.changelog.index.has_node # to filter unknown nodes - for phase, nodes in pycompat.iteritems(self.phaseroots): + for phase, nodes in self.phaseroots.items(): missing = sorted(node for node in nodes if not has_node(node)) if missing: for mnode in missing: @@ -855,7 +852,7 @@ # build list from dictionary draftroots = [] has_node = repo.changelog.index.has_node # to filter unknown nodes - for nhex, phase in pycompat.iteritems(roots): + for nhex, phase in roots.items(): if nhex == b'publishing': # ignore data related to publish option continue node = bin(nhex) @@ -882,7 +879,7 @@ return publicheads, draftroots -class remotephasessummary(object): +class remotephasessummary: """summarize phase information on the remote side :publishing: True is the remote is publishing
--- a/mercurial/policy.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/policy.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import sys @@ -54,11 +53,8 @@ policy = b'cffi' # Environment variable can always force settings. -if sys.version_info[0] >= 3: - if 'HGMODULEPOLICY' in os.environ: - policy = os.environ['HGMODULEPOLICY'].encode('utf-8') -else: - policy = os.environ.get('HGMODULEPOLICY', policy) +if 'HGMODULEPOLICY' in os.environ: + policy = os.environ['HGMODULEPOLICY'].encode('utf-8') def _importfrom(pkgname, modname):
--- a/mercurial/posix.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/posix.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import fcntl @@ -60,21 +59,7 @@ umask = os.umask(0) os.umask(umask) -if not pycompat.ispy3: - - def posixfile(name, mode='r', buffering=-1): - fp = open(name, mode=mode, buffering=buffering) - # The position when opening in append mode is implementation defined, so - # make it consistent by always seeking to the end. - if 'a' in mode: - fp.seek(0, os.SEEK_END) - return fp - - -else: - # The underlying file object seeks as required in Python 3: - # https://github.com/python/cpython/blob/v3.7.3/Modules/_io/fileio.c#L474 - posixfile = open +posixfile = open def split(p): @@ -679,7 +664,7 @@ pass -class cachestat(object): +class cachestat: def __init__(self, path): self.stat = os.stat(path)
--- a/mercurial/profiling.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/profiling.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import contextlib @@ -174,7 +173,7 @@ statprof.display(fp, data=data, format=displayformat, **kwargs) -class profile(object): +class profile: """Start profiling. Profiling is active when the context manager is active. When the context @@ -232,7 +231,7 @@ self._fp = open(path, b'wb') elif pycompat.iswindows: # parse escape sequence by win32print() - class uifp(object): + class uifp: def __init__(self, ui): self._ui = ui
--- a/mercurial/progress.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/progress.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import threading @@ -85,7 +84,7 @@ raise -class progbar(object): +class progbar: def __init__(self, ui): self.ui = ui self._refreshlock = threading.Lock()
--- a/mercurial/pure/base85.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pure/base85.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import struct
--- a/mercurial/pure/bdiff.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pure/bdiff.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import difflib import re
--- a/mercurial/pure/charencode.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pure/charencode.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import array @@ -68,10 +67,7 @@ raise ValueError -if pycompat.ispy3: - _utf8strict = r'surrogatepass' -else: - _utf8strict = r'strict' +_utf8strict = r'surrogatepass' def jsonescapeu8fallback(u8chars, paranoid):
--- a/mercurial/pure/mpatch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pure/mpatch.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,13 +5,12 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import +import io import struct -from .. import pycompat -stringio = pycompat.bytesio +stringio = io.BytesIO class mpatchError(Exception):
--- a/mercurial/pure/osutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pure/osutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, division import ctypes import ctypes.util @@ -221,7 +220,7 @@ err.errno, '%s: %s' % (encoding.strfromlocal(name), err.strerror) ) - class posixfile(object): + class posixfile: """a file object aiming for POSIX-like semantics CPython's open() returns a file that was opened *without* setting the
--- a/mercurial/pure/parsers.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pure/parsers.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,8 +5,8 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import +import io import stat import struct import zlib @@ -18,7 +18,6 @@ from ..thirdparty import attr from .. import ( error, - pycompat, revlogutils, util, ) @@ -26,7 +25,7 @@ from ..revlogutils import nodemap as nodemaputil from ..revlogutils import constants as revlog_constants -stringio = pycompat.bytesio +stringio = io.BytesIO _pack = struct.pack @@ -64,7 +63,7 @@ @attr.s(slots=True, init=False) -class DirstateItem(object): +class DirstateItem: """represent a dirstate entry It hold multiple attributes @@ -561,7 +560,7 @@ return int(q & 0xFFFF) -class BaseIndexObject(object): +class BaseIndexObject: # Can I be passed to an algorithme implemented in Rust ? rust_ext_compat = 0 # Format of an index entry according to Python's `struct` language @@ -959,7 +958,7 @@ cs = stringio() write = cs.write write(b"".join(pl)) - for f, e in pycompat.iteritems(dmap): + for f, e in dmap.items(): if f in copymap: f = b"%s\0%s" % (f, copymap[f]) e = _pack(
--- a/mercurial/pushkey.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pushkey.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from . import ( bookmarks,
--- a/mercurial/pvec.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pvec.py Tue Apr 05 11:09:03 2022 +0200 @@ -48,7 +48,6 @@ different branches ''' -from __future__ import absolute_import from .node import nullrev from . import ( @@ -181,7 +180,7 @@ return pvec(util.b85encode(bs)) -class pvec(object): +class pvec: def __init__(self, hashorctx): if isinstance(hashorctx, bytes): self._bs = hashorctx
--- a/mercurial/pycompat.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/pycompat.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,15 +8,26 @@ This contains aliases to hide python version-specific details from the core. """ -from __future__ import absolute_import +import builtins +import codecs +import concurrent.futures as futures +import functools import getopt +import http.client as httplib +import http.cookiejar as cookielib import inspect +import io import json import os +import queue import shlex +import socketserver +import struct import sys import tempfile +import xmlrpc.client as xmlrpclib + ispy3 = sys.version_info[0] >= 3 ispypy = '__pypy__' in sys.builtin_module_names @@ -27,36 +38,12 @@ TYPE_CHECKING = typing.TYPE_CHECKING -if not ispy3: - import cookielib - import cPickle as pickle - import httplib - import Queue as queue - import SocketServer as socketserver - import xmlrpclib - - from .thirdparty.concurrent import futures - - def future_set_exception_info(f, exc_info): - f.set_exception_info(*exc_info) - # this is close enough for our usage - FileNotFoundError = OSError +def future_set_exception_info(f, exc_info): + f.set_exception(exc_info[0]) -else: - import builtins - import concurrent.futures as futures - import http.cookiejar as cookielib - import http.client as httplib - import pickle - import queue as queue - import socketserver - import xmlrpc.client as xmlrpclib - def future_set_exception_info(f, exc_info): - f.set_exception(exc_info[0]) - - FileNotFoundError = builtins.FileNotFoundError +FileNotFoundError = builtins.FileNotFoundError def identity(a): @@ -98,402 +85,297 @@ return _rapply(f, xs) -if ispy3: - import builtins - import codecs - import functools - import io - import struct - - if os.name == r'nt' and sys.version_info >= (3, 6): - # MBCS (or ANSI) filesystem encoding must be used as before. - # Otherwise non-ASCII filenames in existing repositories would be - # corrupted. - # This must be set once prior to any fsencode/fsdecode calls. - sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr +if os.name == r'nt': + # MBCS (or ANSI) filesystem encoding must be used as before. + # Otherwise non-ASCII filenames in existing repositories would be + # corrupted. + # This must be set once prior to any fsencode/fsdecode calls. + sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr - fsencode = os.fsencode - fsdecode = os.fsdecode - oscurdir = os.curdir.encode('ascii') - oslinesep = os.linesep.encode('ascii') - osname = os.name.encode('ascii') - ospathsep = os.pathsep.encode('ascii') - ospardir = os.pardir.encode('ascii') - ossep = os.sep.encode('ascii') - osaltsep = os.altsep - if osaltsep: - osaltsep = osaltsep.encode('ascii') - osdevnull = os.devnull.encode('ascii') +fsencode = os.fsencode +fsdecode = os.fsdecode +oscurdir = os.curdir.encode('ascii') +oslinesep = os.linesep.encode('ascii') +osname = os.name.encode('ascii') +ospathsep = os.pathsep.encode('ascii') +ospardir = os.pardir.encode('ascii') +ossep = os.sep.encode('ascii') +osaltsep = os.altsep +if osaltsep: + osaltsep = osaltsep.encode('ascii') +osdevnull = os.devnull.encode('ascii') - sysplatform = sys.platform.encode('ascii') - sysexecutable = sys.executable - if sysexecutable: - sysexecutable = os.fsencode(sysexecutable) - bytesio = io.BytesIO - # TODO deprecate stringio name, as it is a lie on Python 3. - stringio = bytesio +sysplatform = sys.platform.encode('ascii') +sysexecutable = sys.executable +if sysexecutable: + sysexecutable = os.fsencode(sysexecutable) + - def maplist(*args): - return list(map(*args)) +def maplist(*args): + return list(map(*args)) + - def rangelist(*args): - return list(range(*args)) +def rangelist(*args): + return list(range(*args)) + - def ziplist(*args): - return list(zip(*args)) +def ziplist(*args): + return list(zip(*args)) + - rawinput = input - getargspec = inspect.getfullargspec +rawinput = input +getargspec = inspect.getfullargspec - long = int +long = int - if getattr(sys, 'argv', None) is not None: - # On POSIX, the char** argv array is converted to Python str using - # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which - # isn't directly callable from Python code. In practice, os.fsencode() - # can be used instead (this is recommended by Python's documentation - # for sys.argv). - # - # On Windows, the wchar_t **argv is passed into the interpreter as-is. - # Like POSIX, we need to emulate what Py_EncodeLocale() would do. But - # there's an additional wrinkle. What we really want to access is the - # ANSI codepage representation of the arguments, as this is what - # `int main()` would receive if Python 3 didn't define `int wmain()` - # (this is how Python 2 worked). To get that, we encode with the mbcs - # encoding, which will pass CP_ACP to the underlying Windows API to - # produce bytes. - if os.name == r'nt': - sysargv = [a.encode("mbcs", "ignore") for a in sys.argv] - else: - sysargv = [fsencode(a) for a in sys.argv] +if getattr(sys, 'argv', None) is not None: + # On POSIX, the char** argv array is converted to Python str using + # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which + # isn't directly callable from Python code. In practice, os.fsencode() + # can be used instead (this is recommended by Python's documentation + # for sys.argv). + # + # On Windows, the wchar_t **argv is passed into the interpreter as-is. + # Like POSIX, we need to emulate what Py_EncodeLocale() would do. But + # there's an additional wrinkle. What we really want to access is the + # ANSI codepage representation of the arguments, as this is what + # `int main()` would receive if Python 3 didn't define `int wmain()` + # (this is how Python 2 worked). To get that, we encode with the mbcs + # encoding, which will pass CP_ACP to the underlying Windows API to + # produce bytes. + if os.name == r'nt': + sysargv = [a.encode("mbcs", "ignore") for a in sys.argv] + else: + sysargv = [fsencode(a) for a in sys.argv] - bytechr = struct.Struct('>B').pack - byterepr = b'%r'.__mod__ - - class bytestr(bytes): - """A bytes which mostly acts as a Python 2 str +bytechr = struct.Struct('>B').pack +byterepr = b'%r'.__mod__ - >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1) - ('', 'foo', 'ascii', '1') - >>> s = bytestr(b'foo') - >>> assert s is bytestr(s) - __bytes__() should be called if provided: +class bytestr(bytes): + """A bytes which mostly acts as a Python 2 str - >>> class bytesable(object): - ... def __bytes__(self): - ... return b'bytes' - >>> bytestr(bytesable()) - 'bytes' + >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1) + ('', 'foo', 'ascii', '1') + >>> s = bytestr(b'foo') + >>> assert s is bytestr(s) + + __bytes__() should be called if provided: - There's no implicit conversion from non-ascii str as its encoding is - unknown: + >>> class bytesable: + ... def __bytes__(self): + ... return b'bytes' + >>> bytestr(bytesable()) + 'bytes' - >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS - Traceback (most recent call last): - ... - UnicodeEncodeError: ... - - Comparison between bytestr and bytes should work: + There's no implicit conversion from non-ascii str as its encoding is + unknown: - >>> assert bytestr(b'foo') == b'foo' - >>> assert b'foo' == bytestr(b'foo') - >>> assert b'f' in bytestr(b'foo') - >>> assert bytestr(b'f') in b'foo' + >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + UnicodeEncodeError: ... - Sliced elements should be bytes, not integer: + Comparison between bytestr and bytes should work: - >>> s[1], s[:2] - (b'o', b'fo') - >>> list(s), list(reversed(s)) - ([b'f', b'o', b'o'], [b'o', b'o', b'f']) - - As bytestr type isn't propagated across operations, you need to cast - bytes to bytestr explicitly: + >>> assert bytestr(b'foo') == b'foo' + >>> assert b'foo' == bytestr(b'foo') + >>> assert b'f' in bytestr(b'foo') + >>> assert bytestr(b'f') in b'foo' - >>> s = bytestr(b'foo').upper() - >>> t = bytestr(s) - >>> s[0], t[0] - (70, b'F') + Sliced elements should be bytes, not integer: - Be careful to not pass a bytestr object to a function which expects - bytearray-like behavior. + >>> s[1], s[:2] + (b'o', b'fo') + >>> list(s), list(reversed(s)) + ([b'f', b'o', b'o'], [b'o', b'o', b'f']) - >>> t = bytes(t) # cast to bytes - >>> assert type(t) is bytes - """ + As bytestr type isn't propagated across operations, you need to cast + bytes to bytestr explicitly: - # Trick pytype into not demanding Iterable[int] be passed to __new__(), - # since the appropriate bytes format is done internally. - # - # https://github.com/google/pytype/issues/500 - if TYPE_CHECKING: + >>> s = bytestr(b'foo').upper() + >>> t = bytestr(s) + >>> s[0], t[0] + (70, b'F') - def __init__(self, s=b''): - pass + Be careful to not pass a bytestr object to a function which expects + bytearray-like behavior. + + >>> t = bytes(t) # cast to bytes + >>> assert type(t) is bytes + """ - def __new__(cls, s=b''): - if isinstance(s, bytestr): - return s - if not isinstance( - s, (bytes, bytearray) - ) and not hasattr( # hasattr-py3-only - s, u'__bytes__' - ): - s = str(s).encode('ascii') - return bytes.__new__(cls, s) + # Trick pytype into not demanding Iterable[int] be passed to __new__(), + # since the appropriate bytes format is done internally. + # + # https://github.com/google/pytype/issues/500 + if TYPE_CHECKING: - def __getitem__(self, key): - s = bytes.__getitem__(self, key) - if not isinstance(s, bytes): - s = bytechr(s) + def __init__(self, s=b''): + pass + + def __new__(cls, s=b''): + if isinstance(s, bytestr): return s - - def __iter__(self): - return iterbytestr(bytes.__iter__(self)) - - def __repr__(self): - return bytes.__repr__(self)[1:] # drop b'' + if not isinstance( + s, (bytes, bytearray) + ) and not hasattr( # hasattr-py3-only + s, u'__bytes__' + ): + s = str(s).encode('ascii') + return bytes.__new__(cls, s) - def iterbytestr(s): - """Iterate bytes as if it were a str object of Python 2""" - return map(bytechr, s) - - def maybebytestr(s): - """Promote bytes to bytestr""" - if isinstance(s, bytes): - return bytestr(s) + def __getitem__(self, key): + s = bytes.__getitem__(self, key) + if not isinstance(s, bytes): + s = bytechr(s) return s - def sysbytes(s): - """Convert an internal str (e.g. keyword, __doc__) back to bytes + def __iter__(self): + return iterbytestr(bytes.__iter__(self)) - This never raises UnicodeEncodeError, but only ASCII characters - can be round-trip by sysstr(sysbytes(s)). - """ - if isinstance(s, bytes): - return s - return s.encode('utf-8') + def __repr__(self): + return bytes.__repr__(self)[1:] # drop b'' - def sysstr(s): - """Return a keyword str to be passed to Python functions such as - getattr() and str.encode() - This never raises UnicodeDecodeError. Non-ascii characters are - considered invalid and mapped to arbitrary but unique code points - such that 'sysstr(a) != sysstr(b)' for all 'a != b'. - """ - if isinstance(s, builtins.str): - return s - return s.decode('latin-1') +def iterbytestr(s): + """Iterate bytes as if it were a str object of Python 2""" + return map(bytechr, s) + - def strurl(url): - """Converts a bytes url back to str""" - if isinstance(url, bytes): - return url.decode('ascii') - return url +def maybebytestr(s): + """Promote bytes to bytestr""" + if isinstance(s, bytes): + return bytestr(s) + return s - def bytesurl(url): - """Converts a str url to bytes by encoding in ascii""" - if isinstance(url, str): - return url.encode('ascii') - return url + +def sysbytes(s): + """Convert an internal str (e.g. keyword, __doc__) back to bytes - def raisewithtb(exc, tb): - """Raise exception with the given traceback""" - raise exc.with_traceback(tb) + This never raises UnicodeEncodeError, but only ASCII characters + can be round-trip by sysstr(sysbytes(s)). + """ + if isinstance(s, bytes): + return s + return s.encode('utf-8') - def getdoc(obj): - """Get docstring as bytes; may be None so gettext() won't confuse it - with _('')""" - doc = getattr(obj, '__doc__', None) - if doc is None: - return doc - return sysbytes(doc) - def _wrapattrfunc(f): - @functools.wraps(f) - def w(object, name, *args): - return f(object, sysstr(name), *args) - - return w +def sysstr(s): + """Return a keyword str to be passed to Python functions such as + getattr() and str.encode() - # these wrappers are automagically imported by hgloader - delattr = _wrapattrfunc(builtins.delattr) - getattr = _wrapattrfunc(builtins.getattr) - hasattr = _wrapattrfunc(builtins.hasattr) - setattr = _wrapattrfunc(builtins.setattr) - xrange = builtins.range - unicode = str - - def open(name, mode=b'r', buffering=-1, encoding=None): - return builtins.open(name, sysstr(mode), buffering, encoding) - - safehasattr = _wrapattrfunc(builtins.hasattr) + This never raises UnicodeDecodeError. Non-ascii characters are + considered invalid and mapped to arbitrary but unique code points + such that 'sysstr(a) != sysstr(b)' for all 'a != b'. + """ + if isinstance(s, builtins.str): + return s + return s.decode('latin-1') - def _getoptbwrapper(orig, args, shortlist, namelist): - """ - Takes bytes arguments, converts them to unicode, pass them to - getopt.getopt(), convert the returned values back to bytes and then - return them for Python 3 compatibility as getopt.getopt() don't accepts - bytes on Python 3. - """ - args = [a.decode('latin-1') for a in args] - shortlist = shortlist.decode('latin-1') - namelist = [a.decode('latin-1') for a in namelist] - opts, args = orig(args, shortlist, namelist) - opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts] - args = [a.encode('latin-1') for a in args] - return opts, args + +def strurl(url): + """Converts a bytes url back to str""" + if isinstance(url, bytes): + return url.decode('ascii') + return url + - def strkwargs(dic): - """ - Converts the keys of a python dictonary to str i.e. unicodes so that - they can be passed as keyword arguments as dictionaries with bytes keys - can't be passed as keyword arguments to functions on Python 3. - """ - dic = {k.decode('latin-1'): v for k, v in dic.items()} - return dic +def bytesurl(url): + """Converts a str url to bytes by encoding in ascii""" + if isinstance(url, str): + return url.encode('ascii') + return url - def byteskwargs(dic): - """ - Converts keys of python dictionaries to bytes as they were converted to - str to pass that dictonary as a keyword argument on Python 3. - """ - dic = {k.encode('latin-1'): v for k, v in dic.items()} - return dic - # TODO: handle shlex.shlex(). - def shlexsplit(s, comments=False, posix=True): - """ - Takes bytes argument, convert it to str i.e. unicodes, pass that into - shlex.split(), convert the returned value to bytes and return that for - Python 3 compatibility as shelx.split() don't accept bytes on Python 3. - """ - ret = shlex.split(s.decode('latin-1'), comments, posix) - return [a.encode('latin-1') for a in ret] +def raisewithtb(exc, tb): + """Raise exception with the given traceback""" + raise exc.with_traceback(tb) + - iteritems = lambda x: x.items() - itervalues = lambda x: x.values() +def getdoc(obj): + """Get docstring as bytes; may be None so gettext() won't confuse it + with _('')""" + doc = getattr(obj, '__doc__', None) + if doc is None: + return doc + return sysbytes(doc) - # Python 3.5's json.load and json.loads require str. We polyfill its - # code for detecting encoding from bytes. - if sys.version_info[0:2] < (3, 6): - def _detect_encoding(b): - bstartswith = b.startswith - if bstartswith((codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE)): - return 'utf-32' - if bstartswith((codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE)): - return 'utf-16' - if bstartswith(codecs.BOM_UTF8): - return 'utf-8-sig' +def _wrapattrfunc(f): + @functools.wraps(f) + def w(object, name, *args): + return f(object, sysstr(name), *args) + + return w + - if len(b) >= 4: - if not b[0]: - # 00 00 -- -- - utf-32-be - # 00 XX -- -- - utf-16-be - return 'utf-16-be' if b[1] else 'utf-32-be' - if not b[1]: - # XX 00 00 00 - utf-32-le - # XX 00 00 XX - utf-16-le - # XX 00 XX -- - utf-16-le - return 'utf-16-le' if b[2] or b[3] else 'utf-32-le' - elif len(b) == 2: - if not b[0]: - # 00 XX - utf-16-be - return 'utf-16-be' - if not b[1]: - # XX 00 - utf-16-le - return 'utf-16-le' - # default - return 'utf-8' +# these wrappers are automagically imported by hgloader +delattr = _wrapattrfunc(builtins.delattr) +getattr = _wrapattrfunc(builtins.getattr) +hasattr = _wrapattrfunc(builtins.hasattr) +setattr = _wrapattrfunc(builtins.setattr) +xrange = builtins.range +unicode = str - def json_loads(s, *args, **kwargs): - if isinstance(s, (bytes, bytearray)): - s = s.decode(_detect_encoding(s), 'surrogatepass') - return json.loads(s, *args, **kwargs) +def open(name, mode=b'r', buffering=-1, encoding=None): + return builtins.open(name, sysstr(mode), buffering, encoding) - else: - json_loads = json.loads -else: - import cStringIO +safehasattr = _wrapattrfunc(builtins.hasattr) + - xrange = xrange - unicode = unicode - bytechr = chr - byterepr = repr - bytestr = str - iterbytestr = iter - maybebytestr = identity - sysbytes = identity - sysstr = identity - strurl = identity - bytesurl = identity - open = open - delattr = delattr - getattr = getattr - hasattr = hasattr - setattr = setattr +def _getoptbwrapper(orig, args, shortlist, namelist): + """ + Takes bytes arguments, converts them to unicode, pass them to + getopt.getopt(), convert the returned values back to bytes and then + return them for Python 3 compatibility as getopt.getopt() don't accepts + bytes on Python 3. + """ + args = [a.decode('latin-1') for a in args] + shortlist = shortlist.decode('latin-1') + namelist = [a.decode('latin-1') for a in namelist] + opts, args = orig(args, shortlist, namelist) + opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts] + args = [a.encode('latin-1') for a in args] + return opts, args - # this can't be parsed on Python 3 - exec(b'def raisewithtb(exc, tb):\n raise exc, None, tb\n') - def fsencode(filename): - """ - Partial backport from os.py in Python 3, which only accepts bytes. - In Python 2, our paths should only ever be bytes, a unicode path - indicates a bug. - """ - if isinstance(filename, str): - return filename - else: - raise TypeError("expect str, not %s" % type(filename).__name__) - - # In Python 2, fsdecode() has a very chance to receive bytes. So it's - # better not to touch Python 2 part as it's already working fine. - fsdecode = identity +def strkwargs(dic): + """ + Converts the keys of a python dictonary to str i.e. unicodes so that + they can be passed as keyword arguments as dictionaries with bytes keys + can't be passed as keyword arguments to functions on Python 3. + """ + dic = {k.decode('latin-1'): v for k, v in dic.items()} + return dic - def getdoc(obj): - return getattr(obj, '__doc__', None) - - _notset = object() - def safehasattr(thing, attr): - return getattr(thing, attr, _notset) is not _notset +def byteskwargs(dic): + """ + Converts keys of python dictionaries to bytes as they were converted to + str to pass that dictonary as a keyword argument on Python 3. + """ + dic = {k.encode('latin-1'): v for k, v in dic.items()} + return dic - def _getoptbwrapper(orig, args, shortlist, namelist): - return orig(args, shortlist, namelist) - - strkwargs = identity - byteskwargs = identity - oscurdir = os.curdir - oslinesep = os.linesep - osname = os.name - ospathsep = os.pathsep - ospardir = os.pardir - ossep = os.sep - osaltsep = os.altsep - osdevnull = os.devnull - long = long - if getattr(sys, 'argv', None) is not None: - sysargv = sys.argv - sysplatform = sys.platform - sysexecutable = sys.executable - shlexsplit = shlex.split - bytesio = cStringIO.StringIO - stringio = bytesio - maplist = map - rangelist = range - ziplist = zip - rawinput = raw_input - getargspec = inspect.getargspec - iteritems = lambda x: x.iteritems() - itervalues = lambda x: x.itervalues() - json_loads = json.loads +# TODO: handle shlex.shlex(). +def shlexsplit(s, comments=False, posix=True): + """ + Takes bytes argument, convert it to str i.e. unicodes, pass that into + shlex.split(), convert the returned value to bytes and return that for + Python 3 compatibility as shelx.split() don't accept bytes on Python 3. + """ + ret = shlex.split(s.decode('latin-1'), comments, posix) + return [a.encode('latin-1') for a in ret] + + +iteritems = lambda x: x.items() +itervalues = lambda x: x.values() + +json_loads = json.loads isjython = sysplatform.startswith(b'java')
--- a/mercurial/rcutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/rcutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os
--- a/mercurial/registrar.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/registrar.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from . import ( configitems, @@ -22,7 +21,7 @@ configitem = configitems.getitemregister -class _funcregistrarbase(object): +class _funcregistrarbase: """Base of decorator to register a function for specific purpose This decorator stores decorated functions into own dict 'table'.
--- a/mercurial/repair.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/repair.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno @@ -380,7 +379,7 @@ return [c.node() for c in repo.set(b'roots(%ld)', tostrip)] -class stripcallback(object): +class stripcallback: """used as a transaction postclose callback""" def __init__(self, ui, repo, backup, topic):
--- a/mercurial/repocache.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/repocache.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import gc @@ -20,7 +19,7 @@ ) -class repoloader(object): +class repoloader: """Load repositories in background thread This is designed for a forking server. A cached repo cannot be obtained
--- a/mercurial/repoview.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/repoview.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import copy import weakref @@ -262,7 +261,7 @@ return cl -class filteredchangelogmixin(object): +class filteredchangelogmixin: def tiprev(self): """filtered version of revlog.tiprev""" for i in pycompat.xrange(len(self) - 1, -2, -1): @@ -362,7 +361,7 @@ return super(filteredchangelogmixin, self).flags(rev) -class repoview(object): +class repoview: """Provide a read/write view of a repo through a filtered changelog This object is used to access a filtered version of a repository without
--- a/mercurial/requirements.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/requirements.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import # obsolete experimental requirements: # - manifestv2: An experimental new manifest format that allowed
--- a/mercurial/revlog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlog.py Tue Apr 05 11:09:03 2022 +0200 @@ -12,7 +12,6 @@ and O(changes) merge between branches. """ -from __future__ import absolute_import import binascii import collections @@ -172,7 +171,7 @@ @interfaceutil.implementer(repository.irevisiondelta) @attr.s(slots=True) -class revlogrevisiondelta(object): +class revlogrevisiondelta: node = attr.ib() p1node = attr.ib() p2node = attr.ib() @@ -188,7 +187,7 @@ @interfaceutil.implementer(repository.iverifyproblem) @attr.s(frozen=True) -class revlogproblem(object): +class revlogproblem: warning = attr.ib(default=None) error = attr.ib(default=None) node = attr.ib(default=None) @@ -238,7 +237,7 @@ ) -class revlog(object): +class revlog: """ the underlying revision storage object @@ -438,9 +437,7 @@ self._flagprocessors[REVIDX_ELLIPSIS] = ellipsisprocessor # revlog v0 doesn't have flag processors - for flag, processor in pycompat.iteritems( - opts.get(b'flagprocessors', {}) - ): + for flag, processor in opts.get(b'flagprocessors', {}).items(): flagutil.insertflagprocessor(flag, processor, self._flagprocessors) if self._chunkcachesize <= 0: @@ -869,8 +866,10 @@ the revlog which do not persist the rank. """ rank = self.index[rev][ENTRY_RANK] - if rank == RANK_UNKNOWN: + if self._format_version != CHANGELOGV2 or rank == RANK_UNKNOWN: return None + if rev == nullrev: + return 0 # convention return rank def chainbase(self, rev): @@ -1043,7 +1042,7 @@ heads = [self.rev(n) for n in heads] # we want the ancestors, but inclusive - class lazyset(object): + class lazyset: def __init__(self, lazyvalues): self.addedvalues = set() self.lazyvalues = lazyvalues @@ -1304,7 +1303,7 @@ # But, obviously its parents aren't. for p in self.parents(n): heads.pop(p, None) - heads = [head for head, flag in pycompat.iteritems(heads) if flag] + heads = [head for head, flag in heads.items() if flag] roots = list(roots) assert orderedout assert roots @@ -2469,9 +2468,12 @@ elif p1r == nullrev and p2r != nullrev: rank = 1 + self.fast_rank(p2r) else: # merge node - pmin, pmax = sorted((p1r, p2r)) - rank = 1 + self.fast_rank(pmax) - rank += sum(1 for _ in self.findmissingrevs([pmax], [pmin])) + if rustdagop is not None and self.index.rust_ext_compat: + rank = rustdagop.rank(self.index, p1r, p2r) + else: + pmin, pmax = sorted((p1r, p2r)) + rank = 1 + self.fast_rank(pmax) + rank += sum(1 for _ in self.findmissingrevs([pmax], [pmin])) e = revlogutils.entry( flags=flags,
--- a/mercurial/revlogutils/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from ..thirdparty import attr from ..interfaces import repository @@ -63,7 +62,7 @@ @attr.s(slots=True, frozen=True) -class revisioninfo(object): +class revisioninfo: """Information about a revision that allows building its fulltext node: expected hash of the revision p1, p2: parent revs of the revision
--- a/mercurial/revlogutils/constants.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/constants.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. """Helper class to compute deltas stored inside revlogs""" -from __future__ import absolute_import import struct
--- a/mercurial/revlogutils/deltas.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/deltas.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # GNU General Public License version 2 or any later version. """Helper class to compute deltas stored inside revlogs""" -from __future__ import absolute_import import collections import struct @@ -39,7 +38,7 @@ LIMIT_DELTA2TEXT = 2 -class _testrevlog(object): +class _testrevlog: """minimalist fake revlog to use in doctests""" def __init__(self, data, density=0.5, mingap=0, snapshot=()): @@ -545,7 +544,7 @@ @attr.s(slots=True, frozen=True) -class _deltainfo(object): +class _deltainfo: distance = attr.ib() deltalen = attr.ib() data = attr.ib() @@ -928,7 +927,7 @@ yield (prev,) -class deltacomputer(object): +class deltacomputer: def __init__(self, revlog): self.revlog = revlog
--- a/mercurial/revlogutils/docket.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/docket.py Tue Apr 05 11:09:03 2022 +0200 @@ -15,7 +15,6 @@ # # * a data file, containing variable width data for these revisions, -from __future__ import absolute_import import errno import os @@ -26,7 +25,6 @@ encoding, error, node, - pycompat, util, ) @@ -57,12 +55,7 @@ if inst.errno != errno.ENOENT: raise seed = b'04' # chosen by a fair dice roll. garanteed to be random - if pycompat.ispy3: - iter_seed = iter(seed) - else: - # pytype: disable=wrong-arg-types - iter_seed = (ord(c) for c in seed) - # pytype: enable=wrong-arg-types + iter_seed = iter(seed) # some basic circular sum hashing on 64 bits int_seed = 0 low_mask = int('1' * 35, 2) @@ -71,10 +64,7 @@ low_part = (int_seed & low_mask) << 28 int_seed = high_part + low_part + i r = random.Random() - if pycompat.ispy3: - r.seed(int_seed, version=1) - else: - r.seed(int_seed) + r.seed(int_seed, version=1) # once we drop python 3.8 support we can simply use r.randbytes raw = r.getrandbits(id_size * 4) assert id_size == 8 @@ -109,7 +99,7 @@ S_OLD_UID = struct.Struct('>BL') -class RevlogDocket(object): +class RevlogDocket: """metadata associated with revlog""" def __init__(
--- a/mercurial/revlogutils/flagutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/flagutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from ..i18n import _
--- a/mercurial/revlogutils/nodemap.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/nodemap.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import re @@ -114,7 +113,7 @@ tr.addfinalize(callback_id, lambda tr: persist_nodemap(tr, revlog)) -class _NoTransaction(object): +class _NoTransaction: """transaction like object to update the nodemap outside a transaction""" def __init__(self): @@ -305,7 +304,7 @@ S_HEADER = struct.Struct(">BQQQQ") -class NodeMapDocket(object): +class NodeMapDocket: """metadata associated with persistent nodemap data The persistent data may come from disk or be on their way to disk.
--- a/mercurial/revlogutils/randomaccessfile.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/randomaccessfile.py Tue Apr 05 11:09:03 2022 +0200 @@ -23,7 +23,7 @@ return (n & (n - 1) == 0) and n != 0 -class randomaccessfile(object): +class randomaccessfile: """Accessing arbitrary chuncks of data within a file, with some caching""" def __init__(
--- a/mercurial/revlogutils/revlogv0.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/revlogv0.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from ..node import sha1nodeconstants
--- a/mercurial/revlogutils/sidedata.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revlogutils/sidedata.py Tue Apr 05 11:09:03 2022 +0200 @@ -30,7 +30,6 @@ the concept. """ -from __future__ import absolute_import import collections import struct
--- a/mercurial/revset.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revset.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re @@ -595,7 +594,7 @@ bms.add(repo[bmrev].rev()) else: matchrevs = set() - for name, bmrev in pycompat.iteritems(repo._bookmarks): + for name, bmrev in repo._bookmarks.items(): if matcher(name): matchrevs.add(bmrev) for bmrev in matchrevs: @@ -1707,7 +1706,7 @@ ) namespaces.add(repo.names[pattern]) else: - for name, ns in pycompat.iteritems(repo.names): + for name, ns in repo.names.items(): if matcher(name): namespaces.add(ns) @@ -2804,7 +2803,7 @@ def loadpredicate(ui, extname, registrarobj): """Load revset predicates from specified registrarobj""" - for name, func in pycompat.iteritems(registrarobj._table): + for name, func in registrarobj._table.items(): symbols[name] = func if func._safe: safesymbols.add(name)
--- a/mercurial/revsetlang.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/revsetlang.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import string @@ -613,7 +612,7 @@ tree = _aliasrules.expand(aliases, tree) # warn about problematic (but not referred) aliases if warn is not None: - for name, alias in sorted(pycompat.iteritems(aliases)): + for name, alias in sorted(aliases.items()): if alias.error and not alias.warned: warn(_(b'warning: %s\n') % (alias.error)) alias.warned = True
--- a/mercurial/rewriteutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/rewriteutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re
--- a/mercurial/scmposix.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/scmposix.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import array import errno import fcntl
--- a/mercurial/scmutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/scmutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import glob @@ -63,7 +62,7 @@ @attr.s(slots=True, repr=False) -class status(object): +class status: """Struct with a list of files per status. The 'deleted', 'unknown' and 'ignored' properties are only @@ -109,7 +108,7 @@ del subpaths[subpath] missing.add(subpath) - for subpath, ctx in sorted(pycompat.iteritems(subpaths)): + for subpath, ctx in sorted(subpaths.items()): yield subpath, ctx.sub(subpath) # Yield an empty subrepo based on ctx1 for anything only in ctx2. That way, @@ -228,7 +227,7 @@ except (AttributeError, IndexError): # it might be anything, for example a string reason = inst.reason - if isinstance(reason, pycompat.unicode): + if isinstance(reason, str): # SSLError of Python 2.7.9 contains a unicode reason = encoding.unitolocal(reason) ui.error(_(b"abort: error: %s\n") % stringutil.forcebytestr(reason)) @@ -324,7 +323,7 @@ return abort, warn -class casecollisionauditor(object): +class casecollisionauditor: def __init__(self, ui, abort, dirstate): self._ui = ui self._abort = abort @@ -1020,7 +1019,7 @@ return origvfs.join(filepath) -class _containsnode(object): +class _containsnode: """proxy __contains__(node) to container.__contains__ which accepts revs""" def __init__(self, repo, revcontainer): @@ -1337,7 +1336,7 @@ ignored=False, full=False, ) - for abs, st in pycompat.iteritems(walkresults): + for abs, st in walkresults.items(): entry = dirstate.get_entry(abs) if (not entry.any_tracked) and audit_path.check(abs): unknown.append(abs) @@ -1384,7 +1383,7 @@ with repo.wlock(): wctx.forget(deleted) wctx.add(unknown) - for new, old in pycompat.iteritems(renames): + for new, old in renames.items(): wctx.copy(old, new) @@ -1510,12 +1509,9 @@ # Merge old parent and old working dir copies oldcopies = copiesmod.pathcopies(newctx, oldctx, match) oldcopies.update(copies) - copies = { - dst: oldcopies.get(src, src) - for dst, src in pycompat.iteritems(oldcopies) - } + copies = {dst: oldcopies.get(src, src) for dst, src in oldcopies.items()} # Adjust the dirstate copies - for dst, src in pycompat.iteritems(copies): + for dst, src in copies.items(): if src not in newctx or dst in newctx or not ds.get_entry(dst).added: src = None ds.copy(src, dst) @@ -1571,7 +1567,7 @@ fp.write(b"%s\n" % r) -class filecachesubentry(object): +class filecachesubentry: def __init__(self, path, stat): self.path = path self.cachestat = None @@ -1627,7 +1623,7 @@ raise -class filecacheentry(object): +class filecacheentry: def __init__(self, paths, stat=True): self._entries = [] for path in paths: @@ -1645,7 +1641,7 @@ entry.refresh() -class filecache(object): +class filecache: """A property like decorator that tracks files under .hg/ for updates. On first access, the files defined as arguments are stat()ed and the @@ -1802,7 +1798,7 @@ return data -class progress(object): +class progress: def __init__(self, ui, updatebar, topic, unit=b"", total=None): self.ui = ui self.pos = 0 @@ -1867,7 +1863,7 @@ return ui.configbool(b'format', b'generaldelta') -class simplekeyvaluefile(object): +class simplekeyvaluefile: """A simple file with key=value lines Keys must be alphanumerics and start with a letter, values must not
--- a/mercurial/scmwindows.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/scmwindows.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import os from . import ( @@ -54,7 +52,11 @@ # next look for a system rcpath in the registry value = util.lookupreg( - b'SOFTWARE\\Mercurial', None, winreg.HKEY_LOCAL_MACHINE + # pytype: disable=module-attr + b'SOFTWARE\\Mercurial', + None, + winreg.HKEY_LOCAL_MACHINE + # pytype: enable=module-attr ) if value and isinstance(value, bytes): value = util.localpath(value)
--- a/mercurial/server.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/server.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os
--- a/mercurial/setdiscovery.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/setdiscovery.py Tue Apr 05 11:09:03 2022 +0200 @@ -40,7 +40,6 @@ classified with it (since all ancestors or descendants will be marked as well). """ -from __future__ import absolute_import import collections import random @@ -107,7 +106,7 @@ return set(sample[:desiredlen]) -class partialdiscovery(object): +class partialdiscovery: """an object representing ongoing discovery Feed with data from the remote repository, this object keep track of the
--- a/mercurial/shelve.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/shelve.py Tue Apr 05 11:09:03 2022 +0200 @@ -20,7 +20,6 @@ shelved change has a distinct name. For details, see the help for "hg shelve". """ -from __future__ import absolute_import import collections import errno @@ -69,7 +68,7 @@ shelveuser = b'shelve@localhost' -class ShelfDir(object): +class ShelfDir: def __init__(self, repo, for_backups=False): if for_backups: self.vfs = vfsmod.vfs(repo.vfs.join(backupdir)) @@ -102,7 +101,7 @@ return sorted(info, reverse=True) -class Shelf(object): +class Shelf: """Represents a shelf, including possibly multiple files storing it. Old shelves will have a .patch and a .hg file. Newer shelves will @@ -214,7 +213,7 @@ self.vfs.tryunlink(self.name + b'.' + ext) -class shelvedstate(object): +class shelvedstate: """Handle persistence during unshelving operations. Handles saving and restoring a shelved state. Ensures that different
--- a/mercurial/similar.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/similar.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,12 +5,10 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from . import ( mdiff, - pycompat, ) @@ -98,7 +96,7 @@ copies[a] = (r, myscore) progress.complete() - for dest, v in pycompat.iteritems(copies): + for dest, v in copies.items(): source, bscore = v yield source, dest, bscore
--- a/mercurial/simplemerge.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/simplemerge.py Tue Apr 05 11:09:03 2022 +0200 @@ -16,7 +16,6 @@ # mbp: "you know that thing where cvs gives you conflict markers?" # s: "i hate that." -from __future__ import absolute_import from .i18n import _ from . import ( @@ -63,7 +62,7 @@ return True -class Merge3Text(object): +class Merge3Text: """3-way merge of texts. Given strings BASE, OTHER, THIS, tries to produce a combined text @@ -469,7 +468,7 @@ return lines -class MergeInput(object): +class MergeInput: def __init__(self, fctx, label=None, label_detail=None): self.fctx = fctx self.label = label @@ -491,6 +490,9 @@ self._text = self.fctx.decodeddata() return self._text + def set_text(self, text): + self._text = text + def simplemerge( local,
--- a/mercurial/smartset.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/smartset.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .pycompat import getattr from . import ( @@ -21,7 +20,7 @@ return pycompat.sysbytes(type(o).__name__).lstrip(b'_') -class abstractsmartset(object): +class abstractsmartset: def __nonzero__(self): """True if the smartset is not empty""" raise NotImplementedError()
--- a/mercurial/sparse.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/sparse.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os @@ -555,7 +554,7 @@ ) # Check for files that were only in the dirstate. - for file, state in pycompat.iteritems(dirstate): + for file, state in dirstate.items(): if not file in files: old = origsparsematch(file) new = sparsematch(file)
--- a/mercurial/sshpeer.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/sshpeer.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re import uuid @@ -48,7 +47,7 @@ display(_(b"remote: "), l, b'\n') -class doublepipe(object): +class doublepipe: """Operate a side-channel pipe in addition of a main one The side-channel pipe contains server output to be forwarded to the user @@ -473,10 +472,10 @@ else: wireargs[k] = args[k] del args[k] - for k, v in sorted(pycompat.iteritems(wireargs)): + for k, v in sorted(wireargs.items()): self._pipeo.write(b"%s %d\n" % (k, len(v))) if isinstance(v, dict): - for dk, dv in pycompat.iteritems(v): + for dk, dv in v.items(): self._pipeo.write(b"%s %d\n" % (dk, len(dv))) self._pipeo.write(dv) else:
--- a/mercurial/sslutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/sslutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import hashlib import os
--- a/mercurial/stack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/stack.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,8 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import - def getstack(repo, rev=None): """return a sorted smartrev of the stack containing either rev if it is
--- a/mercurial/state.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/state.py Tue Apr 05 11:09:03 2022 +0200 @@ -17,7 +17,6 @@ the data. """ -from __future__ import absolute_import import contextlib @@ -40,7 +39,7 @@ assert t -class cmdstate(object): +class cmdstate: """a wrapper class to store the state of commands like `rebase`, `graft`, `histedit`, `shelve` etc. Extensions can also use this to write state files. @@ -103,7 +102,7 @@ return self._repo.vfs.exists(self.fname) -class _statecheck(object): +class _statecheck: """a utility class that deals with multistep operations like graft, histedit, bisect, update etc and check whether such commands are in an unfinished conditition or not and return appropriate message
--- a/mercurial/statichttprepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/statichttprepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno @@ -35,7 +34,7 @@ urlreq = util.urlreq -class httprangereader(object): +class httprangereader: def __init__(self, url, opener): # we assume opener has HTTPRangeHandler self.url = url
--- a/mercurial/statprof.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/statprof.py Tue Apr 05 11:09:03 2022 +0200 @@ -101,7 +101,6 @@ main thread's work patterns. """ # no-check-code -from __future__ import absolute_import, division, print_function import collections import contextlib @@ -155,7 +154,7 @@ ## Collection data structures -class ProfileState(object): +class ProfileState: def __init__(self, frequency=None): self.reset(frequency) self.track = b'cpu' @@ -203,7 +202,7 @@ state = ProfileState() -class CodeSite(object): +class CodeSite: cache = {} __slots__ = ('path', 'lineno', 'function', 'source') @@ -261,7 +260,7 @@ return '%s:%s' % (self.filename(), self.function) -class Sample(object): +class Sample: __slots__ = ('stack', 'time') def __init__(self, stack, time): @@ -435,7 +434,7 @@ ## Reporting API -class SiteStats(object): +class SiteStats: def __init__(self, site): self.site = site self.selfcount = 0 @@ -475,7 +474,7 @@ if i == 0: sitestat.addself() - return [s for s in pycompat.itervalues(stats)] + return [s for s in stats.values()] class DisplayFormats: @@ -574,7 +573,7 @@ # compute sums for each function functiondata = [] - for fname, sitestats in pycompat.iteritems(grouped): + for fname, sitestats in grouped.items(): total_cum_sec = 0 total_self_sec = 0 total_percent = 0 @@ -608,9 +607,7 @@ # only show line numbers for significant locations (>1% time spent) if stat.selfpercent() > 1: source = stat.site.getsource(25) - if sys.version_info.major >= 3 and not isinstance( - source, bytes - ): + if not isinstance(source, bytes): source = pycompat.bytestr(source) stattuple = ( @@ -653,7 +650,7 @@ else: children[site] = 1 - parents = [(parent, count) for parent, count in pycompat.iteritems(parents)] + parents = [(parent, count) for parent, count in parents.items()] parents.sort(reverse=True, key=lambda x: x[1]) for parent, count in parents: fp.write( @@ -697,7 +694,7 @@ ) ) - children = [(child, count) for child, count in pycompat.iteritems(children)] + children = [(child, count) for child, count in children.items()] children.sort(reverse=True, key=lambda x: x[1]) for child, count in children: fp.write( @@ -711,7 +708,7 @@ def display_hotpath(data, fp, limit=0.05, **kwargs): - class HotNode(object): + class HotNode: def __init__(self, site): self.site = site self.count = 0 @@ -746,9 +743,7 @@ def _write(node, depth, multiple_siblings): site = node.site visiblechildren = [ - c - for c in pycompat.itervalues(node.children) - if c.count >= (limit * root.count) + c for c in node.children.values() if c.count >= (limit * root.count) ] if site: indent = depth * 2 - 1 @@ -784,9 +779,7 @@ ) finalstring = liststring + codestring - childrensamples = sum( - [c.count for c in pycompat.itervalues(node.children)] - ) + childrensamples = sum([c.count for c in node.children.values()]) # Make frames that performed more than 10% of the operation red if node.count - childrensamples > (0.1 * root.count): finalstring = b'\033[91m' + finalstring + b'\033[0m' @@ -828,7 +821,7 @@ fd, path = pycompat.mkstemp() with open(path, b"w+") as file: - for line, count in pycompat.iteritems(lines): + for line, count in lines.items(): file.write(b"%s %d\n" % (line, count)) if outputfile is None:
--- a/mercurial/store.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/store.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import functools @@ -145,7 +144,7 @@ cmap[xchr(x)] = e + xchr(x).lower() dmap = {} - for k, v in pycompat.iteritems(cmap): + for k, v in cmap.items(): dmap[v] = k def decode(s): @@ -456,7 +455,7 @@ FILETYPE_OTHER = FILEFLAGS_OTHER -class basicstore(object): +class basicstore: '''base class for local repository stores''' def __init__(self, path, vfstype): @@ -602,7 +601,7 @@ return [b'requires', b'00changelog.i'] + [b'store/' + f for f in _data] -class fncache(object): +class fncache: # the filename used to be partially encoded # hence the encodedir/decodedir dance def __init__(self, vfs): @@ -662,7 +661,7 @@ """make sure there is no empty string in entries""" if b'' in self.entries: fp.seek(0) - for n, line in enumerate(util.iterfile(fp)): + for n, line in enumerate(fp): if not line.rstrip(b'\n'): t = _(b'invalid entry in fncache, line %d') % (n + 1) if warn:
--- a/mercurial/streamclone.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/streamclone.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import errno @@ -517,7 +516,7 @@ nodemap.post_stream_cleanup(repo) -class streamcloneapplier(object): +class streamcloneapplier: """Class to manage applying streaming clone bundles. We need to wrap ``applybundlev1()`` in a dedicated type to enable bundle
--- a/mercurial/strip.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/strip.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from .i18n import _ from .pycompat import getattr from . import ( @@ -195,7 +193,7 @@ # a revision we have to only delete the bookmark and not strip # anything. revsets cannot detect that case. nodetobookmarks = {} - for mark, node in pycompat.iteritems(repomarks): + for mark, node in repomarks.items(): nodetobookmarks.setdefault(node, []).append(mark) for marks in nodetobookmarks.values(): if bookmarks.issuperset(marks):
--- a/mercurial/subrepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/subrepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import copy import errno @@ -221,7 +220,7 @@ # subrepo classes need to implement the following abstract class: -class abstractsubrepo(object): +class abstractsubrepo: def __init__(self, ctx, path): """Initialize abstractsubrepo part @@ -1771,7 +1770,7 @@ for b in rev2branch[self._state[1]]: if b.startswith(b'refs/remotes/origin/'): return True - for b, revision in pycompat.iteritems(branch2rev): + for b, revision in branch2rev.items(): if b.startswith(b'refs/remotes/origin/'): if self._gitisancestor(self._state[1], revision): return True
--- a/mercurial/subrepoutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/subrepoutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os @@ -191,7 +190,7 @@ repo.ui.debug(b" subrepo %s: %s %s\n" % (s, msg, r)) promptssrc = filemerge.partextras(labels) - for s, l in sorted(pycompat.iteritems(s1)): + for s, l in sorted(s1.items()): a = sa.get(s, nullstate) ld = l # local state with possible dirty flag for compares if wctx.sub(s).dirty():
--- a/mercurial/tagmerge.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/tagmerge.py Tue Apr 05 11:09:03 2022 +0200 @@ -71,7 +71,6 @@ # - put blocks whose nodes come all from p2 first # - write the tag blocks in the sorted order -from __future__ import absolute_import from .i18n import _ from . import (
--- a/mercurial/tags.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/tags.py Tue Apr 05 11:09:03 2022 +0200 @@ -10,7 +10,6 @@ # Eventually, it could take care of updating (adding/removing/moving) # tags too. -from __future__ import absolute_import import errno import io @@ -26,7 +25,6 @@ encoding, error, match as matchmod, - pycompat, scmutil, util, ) @@ -355,7 +353,7 @@ if tagtype is None: assert tagtypes is None - for name, nodehist in pycompat.iteritems(filetags): + for name, nodehist in filetags.items(): if name not in alltags: alltags[name] = nodehist if tagtype is not None: @@ -508,7 +506,7 @@ if unknown_entries: fixed_nodemap = fnodescache.refresh_invalid_nodes(unknown_entries) - for node, fnode in pycompat.iteritems(fixed_nodemap): + for node, fnode in fixed_nodemap.items(): if fnode != repo.nullid: cachefnode[node] = fnode @@ -550,7 +548,7 @@ # we keep them in UTF-8 throughout this module. If we converted # them local encoding on input, we would lose info writing them to # the cache. - for (name, (node, hist)) in sorted(pycompat.iteritems(cachetags)): + for (name, (node, hist)) in sorted(cachetags.items()): for n in hist: cachefile.write(b"%s %s\n" % (hex(n), name)) cachefile.write(b"%s %s\n" % (hex(node), name)) @@ -686,7 +684,7 @@ _fnodesmissingrec = b'\xff' * 24 -class hgtagsfnodescache(object): +class hgtagsfnodescache: """Persistent cache mapping revisions to .hgtags filenodes. The cache is an array of records. Each item in the array corresponds to
--- a/mercurial/templatefilters.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/templatefilters.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os import re @@ -335,7 +334,7 @@ return b'false' elif obj is True: return b'true' - elif isinstance(obj, (int, pycompat.long, float)): + elif isinstance(obj, (int, int, float)): return pycompat.bytestr(obj) elif isinstance(obj, bytes): return b'"%s"' % encoding.jsonescape(obj, paranoid=paranoid) @@ -347,7 +346,7 @@ out = [ b'"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid), json(v, paranoid)) - for k, v in sorted(pycompat.iteritems(obj)) + for k, v in sorted(obj.items()) ] return b'{' + b', '.join(out) + b'}' elif util.safehasattr(obj, b'__iter__'): @@ -373,9 +372,7 @@ """Any text. Returns the input text rendered as a sequence of XML entities. """ - text = pycompat.unicode( - text, pycompat.sysstr(encoding.encoding), r'replace' - ) + text = str(text, pycompat.sysstr(encoding.encoding), r'replace') return b''.join([b'&#%d;' % ord(c) for c in text]) @@ -549,7 +546,7 @@ def loadfilter(ui, extname, registrarobj): """Load template filter from specified registrarobj""" - for name, func in pycompat.iteritems(registrarobj._table): + for name, func in registrarobj._table.items(): filters[name] = func
--- a/mercurial/templatefuncs.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/templatefuncs.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re @@ -89,7 +88,7 @@ data.update( (k, evalfuncarg(context, mapping, v)) - for k, v in pycompat.iteritems(args[b'kwargs']) + for k, v in args[b'kwargs'].items() ) return templateutil.hybriddict(data) @@ -911,7 +910,7 @@ def loadfunction(ui, extname, registrarobj): """Load template function from specified registrarobj""" - for name, func in pycompat.iteritems(registrarobj._table): + for name, func in registrarobj._table.items(): funcs[name] = func
--- a/mercurial/templatekw.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/templatekw.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from .node import ( @@ -603,7 +602,7 @@ # 'name' for iterating over namespaces, templatename for local reference return lambda v: {b'name': v, ns.templatename: v} - for k, ns in pycompat.iteritems(repo.names): + for k, ns in repo.names.items(): names = ns.names(repo, ctx.node()) f = _showcompatlist(context, mapping, b'name', names) namespaces[k] = _hybrid(f, names, makensmapfn(ns), pycompat.identity) @@ -686,12 +685,12 @@ d = {b'name': k} if len(ps) == 1: d[b'url'] = ps[0].rawloc - sub_opts = pycompat.iteritems(ps[0].suboptions) + sub_opts = ps[0].suboptions.items() sub_opts = util.sortdict(sorted(sub_opts)) d.update(sub_opts) path_dict = util.sortdict() for p in ps: - sub_opts = util.sortdict(sorted(pycompat.iteritems(p.suboptions))) + sub_opts = util.sortdict(sorted(p.suboptions.items())) path_dict[b'url'] = p.rawloc path_dict.update(sub_opts) d[b'urls'] = [path_dict] @@ -1024,7 +1023,7 @@ def loadkeyword(ui, extname, registrarobj): """Load template keyword from specified registrarobj""" - for name, func in pycompat.iteritems(registrarobj._table): + for name, func in registrarobj._table.items(): keywords[name] = func
--- a/mercurial/templater.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/templater.py Tue Apr 05 11:09:03 2022 +0200 @@ -65,7 +65,6 @@ operation. """ -from __future__ import absolute_import, print_function import abc import os @@ -531,8 +530,7 @@ def compiledict(xs): return util.sortdict( - (k, compileexp(x, context, curmethods)) - for k, x in pycompat.iteritems(xs) + (k, compileexp(x, context, curmethods)) for k, x in xs.items() ) def compilelist(xs): @@ -628,7 +626,7 @@ return s[1:-1] -class resourcemapper(object): # pytype: disable=ignored-metaclass +class resourcemapper: # pytype: disable=ignored-metaclass """Mapper of internal template resources""" __metaclass__ = abc.ABCMeta @@ -665,7 +663,7 @@ return {} -class engine(object): +class engine: """template expansion engine. template expansion works like this. a map file contains key=value @@ -709,7 +707,7 @@ newres = self._resources.availablekeys(newmapping) mapping = { k: v - for k, v in pycompat.iteritems(origmapping) + for k, v in origmapping.items() if ( k in knownres # not a symbol per self.symbol() or newres.isdisjoint(self._defaultrequires(k)) @@ -921,7 +919,7 @@ return cache, tmap, aliases -class loader(object): +class loader: """Load template fragments optionally from a map file""" def __init__(self, cache, aliases): @@ -996,7 +994,7 @@ return syms -class templater(object): +class templater: def __init__( self, filters=None,
--- a/mercurial/templateutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/templateutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import abc import types @@ -32,7 +31,7 @@ pass -class wrapped(object): # pytype: disable=ignored-metaclass +class wrapped: # pytype: disable=ignored-metaclass """Object requiring extra conversion prior to displaying or processing as value @@ -109,7 +108,7 @@ """ -class mappable(object): # pytype: disable=ignored-metaclass +class mappable: # pytype: disable=ignored-metaclass """Object which can be converted to a single template mapping""" __metaclass__ = abc.ABCMeta @@ -311,7 +310,7 @@ if util.safehasattr(self._values, b'get'): values = { k: v - for k, v in pycompat.iteritems(self._values) + for k, v in self._values.items() if select(self._wrapvalue(k, v)) } else: @@ -343,10 +342,7 @@ # TODO: make it non-recursive for trivial lists/dicts xs = self._values if util.safehasattr(xs, b'get'): - return { - k: unwrapvalue(context, mapping, v) - for k, v in pycompat.iteritems(xs) - } + return {k: unwrapvalue(context, mapping, v) for k, v in xs.items()} return [unwrapvalue(context, mapping, x) for x in xs] @@ -538,7 +534,7 @@ items.append( { k: unwrapvalue(context, lm, v) - for k, v in pycompat.iteritems(nm) + for k, v in nm.items() if k not in knownres } ) @@ -716,7 +712,7 @@ This exists for backward compatibility with the old-style template. Use hybriddict() for new template keywords. """ - c = [{key: k, value: v} for k, v in pycompat.iteritems(data)] + c = [{key: k, value: v} for k, v in data.items()] f = _showcompatlist(context, mapping, name, c, plural, separator) return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
--- a/mercurial/testing/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/testing/__init__.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,8 +1,3 @@ -from __future__ import ( - absolute_import, - division, -) - import os import time
--- a/mercurial/testing/revlog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/testing/revlog.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import unittest # picked from test-parse-index2, copied rather than imported
--- a/mercurial/testing/storage.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/testing/storage.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import unittest
--- a/mercurial/thirdparty/concurrent/LICENSE Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python -alone or in any derivative version, provided, however, that PSF's -License Agreement and PSF's notice of copyright, i.e., "Copyright (c) -2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights -Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement.
--- a/mercurial/thirdparty/concurrent/futures/__init__.py Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -# Copyright 2009 Brian Quinlan. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Execute computations asynchronously using threads or processes.""" - -from __future__ import absolute_import - -__author__ = 'Brian Quinlan (brian@sweetapp.com)' - -from ._base import ( - FIRST_COMPLETED, - FIRST_EXCEPTION, - ALL_COMPLETED, - CancelledError, - TimeoutError, - Future, - Executor, - wait, - as_completed, -) -from .thread import ThreadPoolExecutor - -try: - from .process import ProcessPoolExecutor -except ImportError: - # some platforms don't have multiprocessing - pass
--- a/mercurial/thirdparty/concurrent/futures/_base.py Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,669 +0,0 @@ -# Copyright 2009 Brian Quinlan. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -from __future__ import absolute_import - -import collections -import logging -import threading -import itertools -import time -import types - -__author__ = 'Brian Quinlan (brian@sweetapp.com)' - -FIRST_COMPLETED = 'FIRST_COMPLETED' -FIRST_EXCEPTION = 'FIRST_EXCEPTION' -ALL_COMPLETED = 'ALL_COMPLETED' -_AS_COMPLETED = '_AS_COMPLETED' - -# Possible future states (for internal use by the futures package). -PENDING = 'PENDING' -RUNNING = 'RUNNING' -# The future was cancelled by the user... -CANCELLED = 'CANCELLED' -# ...and _Waiter.add_cancelled() was called by a worker. -CANCELLED_AND_NOTIFIED = 'CANCELLED_AND_NOTIFIED' -FINISHED = 'FINISHED' - -_FUTURE_STATES = [ - PENDING, - RUNNING, - CANCELLED, - CANCELLED_AND_NOTIFIED, - FINISHED -] - -_STATE_TO_DESCRIPTION_MAP = { - PENDING: "pending", - RUNNING: "running", - CANCELLED: "cancelled", - CANCELLED_AND_NOTIFIED: "cancelled", - FINISHED: "finished" -} - -# Logger for internal use by the futures package. -LOGGER = logging.getLogger("concurrent.futures") - -class Error(Exception): - """Base class for all future-related exceptions.""" - pass - -class CancelledError(Error): - """The Future was cancelled.""" - pass - -class TimeoutError(Error): - """The operation exceeded the given deadline.""" - pass - -class _Waiter(object): - """Provides the event that wait() and as_completed() block on.""" - def __init__(self): - self.event = threading.Event() - self.finished_futures = [] - - def add_result(self, future): - self.finished_futures.append(future) - - def add_exception(self, future): - self.finished_futures.append(future) - - def add_cancelled(self, future): - self.finished_futures.append(future) - -class _AsCompletedWaiter(_Waiter): - """Used by as_completed().""" - - def __init__(self): - super(_AsCompletedWaiter, self).__init__() - self.lock = threading.Lock() - - def add_result(self, future): - with self.lock: - super(_AsCompletedWaiter, self).add_result(future) - self.event.set() - - def add_exception(self, future): - with self.lock: - super(_AsCompletedWaiter, self).add_exception(future) - self.event.set() - - def add_cancelled(self, future): - with self.lock: - super(_AsCompletedWaiter, self).add_cancelled(future) - self.event.set() - -class _FirstCompletedWaiter(_Waiter): - """Used by wait(return_when=FIRST_COMPLETED).""" - - def add_result(self, future): - super(_FirstCompletedWaiter, self).add_result(future) - self.event.set() - - def add_exception(self, future): - super(_FirstCompletedWaiter, self).add_exception(future) - self.event.set() - - def add_cancelled(self, future): - super(_FirstCompletedWaiter, self).add_cancelled(future) - self.event.set() - -class _AllCompletedWaiter(_Waiter): - """Used by wait(return_when=FIRST_EXCEPTION and ALL_COMPLETED).""" - - def __init__(self, num_pending_calls, stop_on_exception): - self.num_pending_calls = num_pending_calls - self.stop_on_exception = stop_on_exception - self.lock = threading.Lock() - super(_AllCompletedWaiter, self).__init__() - - def _decrement_pending_calls(self): - with self.lock: - self.num_pending_calls -= 1 - if not self.num_pending_calls: - self.event.set() - - def add_result(self, future): - super(_AllCompletedWaiter, self).add_result(future) - self._decrement_pending_calls() - - def add_exception(self, future): - super(_AllCompletedWaiter, self).add_exception(future) - if self.stop_on_exception: - self.event.set() - else: - self._decrement_pending_calls() - - def add_cancelled(self, future): - super(_AllCompletedWaiter, self).add_cancelled(future) - self._decrement_pending_calls() - -class _AcquireFutures(object): - """A context manager that does an ordered acquire of Future conditions.""" - - def __init__(self, futures): - self.futures = sorted(futures, key=id) - - def __enter__(self): - for future in self.futures: - future._condition.acquire() - - def __exit__(self, *args): - for future in self.futures: - future._condition.release() - -def _create_and_install_waiters(fs, return_when): - if return_when == _AS_COMPLETED: - waiter = _AsCompletedWaiter() - elif return_when == FIRST_COMPLETED: - waiter = _FirstCompletedWaiter() - else: - pending_count = sum( - f._state not in [CANCELLED_AND_NOTIFIED, FINISHED] for f in fs) - - if return_when == FIRST_EXCEPTION: - waiter = _AllCompletedWaiter(pending_count, stop_on_exception=True) - elif return_when == ALL_COMPLETED: - waiter = _AllCompletedWaiter(pending_count, stop_on_exception=False) - else: - raise ValueError("Invalid return condition: %r" % return_when) - - for f in fs: - f._waiters.append(waiter) - - return waiter - - -def _yield_finished_futures(fs, waiter, ref_collect): - """ - Iterate on the list *fs*, yielding finished futures one by one in - reverse order. - Before yielding a future, *waiter* is removed from its waiters - and the future is removed from each set in the collection of sets - *ref_collect*. - - The aim of this function is to avoid keeping stale references after - the future is yielded and before the iterator resumes. - """ - while fs: - f = fs[-1] - for futures_set in ref_collect: - futures_set.remove(f) - with f._condition: - f._waiters.remove(waiter) - del f - # Careful not to keep a reference to the popped value - yield fs.pop() - - -def as_completed(fs, timeout=None): - """An iterator over the given futures that yields each as it completes. - - Args: - fs: The sequence of Futures (possibly created by different Executors) to - iterate over. - timeout: The maximum number of seconds to wait. If None, then there - is no limit on the wait time. - - Returns: - An iterator that yields the given Futures as they complete (finished or - cancelled). If any given Futures are duplicated, they will be returned - once. - - Raises: - TimeoutError: If the entire result iterator could not be generated - before the given timeout. - """ - if timeout is not None: - end_time = timeout + time.time() - - fs = set(fs) - total_futures = len(fs) - with _AcquireFutures(fs): - finished = set( - f for f in fs - if f._state in [CANCELLED_AND_NOTIFIED, FINISHED]) - pending = fs - finished - waiter = _create_and_install_waiters(fs, _AS_COMPLETED) - finished = list(finished) - try: - for f in _yield_finished_futures(finished, waiter, - ref_collect=(fs,)): - f = [f] - yield f.pop() - - while pending: - if timeout is None: - wait_timeout = None - else: - wait_timeout = end_time - time.time() - if wait_timeout < 0: - raise TimeoutError( - '%d (of %d) futures unfinished' % ( - len(pending), total_futures)) - - waiter.event.wait(wait_timeout) - - with waiter.lock: - finished = waiter.finished_futures - waiter.finished_futures = [] - waiter.event.clear() - - # reverse to keep finishing order - finished.reverse() - for f in _yield_finished_futures(finished, waiter, - ref_collect=(fs, pending)): - f = [f] - yield f.pop() - - finally: - # Remove waiter from unfinished futures - for f in fs: - with f._condition: - f._waiters.remove(waiter) - -DoneAndNotDoneFutures = collections.namedtuple( - 'DoneAndNotDoneFutures', 'done not_done') -def wait(fs, timeout=None, return_when=ALL_COMPLETED): - """Wait for the futures in the given sequence to complete. - - Args: - fs: The sequence of Futures (possibly created by different Executors) to - wait upon. - timeout: The maximum number of seconds to wait. If None, then there - is no limit on the wait time. - return_when: Indicates when this function should return. The options - are: - - FIRST_COMPLETED - Return when any future finishes or is - cancelled. - FIRST_EXCEPTION - Return when any future finishes by raising an - exception. If no future raises an exception - then it is equivalent to ALL_COMPLETED. - ALL_COMPLETED - Return when all futures finish or are cancelled. - - Returns: - A named 2-tuple of sets. The first set, named 'done', contains the - futures that completed (is finished or cancelled) before the wait - completed. The second set, named 'not_done', contains uncompleted - futures. - """ - with _AcquireFutures(fs): - done = set(f for f in fs - if f._state in [CANCELLED_AND_NOTIFIED, FINISHED]) - not_done = set(fs) - done - - if (return_when == FIRST_COMPLETED) and done: - return DoneAndNotDoneFutures(done, not_done) - elif (return_when == FIRST_EXCEPTION) and done: - if any(f for f in done - if not f.cancelled() and f.exception() is not None): - return DoneAndNotDoneFutures(done, not_done) - - if len(done) == len(fs): - return DoneAndNotDoneFutures(done, not_done) - - waiter = _create_and_install_waiters(fs, return_when) - - waiter.event.wait(timeout) - for f in fs: - with f._condition: - f._waiters.remove(waiter) - - done.update(waiter.finished_futures) - return DoneAndNotDoneFutures(done, set(fs) - done) - -class Future(object): - """Represents the result of an asynchronous computation.""" - - def __init__(self): - """Initializes the future. Should not be called by clients.""" - self._condition = threading.Condition() - self._state = PENDING - self._result = None - self._exception = None - self._traceback = None - self._waiters = [] - self._done_callbacks = [] - - def _invoke_callbacks(self): - for callback in self._done_callbacks: - try: - callback(self) - except Exception: - LOGGER.exception('exception calling callback for %r', self) - except BaseException: - # Explicitly let all other new-style exceptions through so - # that we can catch all old-style exceptions with a simple - # "except:" clause below. - # - # All old-style exception objects are instances of - # types.InstanceType, but "except types.InstanceType:" does - # not catch old-style exceptions for some reason. Thus, the - # only way to catch all old-style exceptions without catching - # any new-style exceptions is to filter out the new-style - # exceptions, which all derive from BaseException. - raise - except: - # Because of the BaseException clause above, this handler only - # executes for old-style exception objects. - LOGGER.exception('exception calling callback for %r', self) - - def __repr__(self): - with self._condition: - if self._state == FINISHED: - if self._exception: - return '<%s at %#x state=%s raised %s>' % ( - self.__class__.__name__, - id(self), - _STATE_TO_DESCRIPTION_MAP[self._state], - self._exception.__class__.__name__) - else: - return '<%s at %#x state=%s returned %s>' % ( - self.__class__.__name__, - id(self), - _STATE_TO_DESCRIPTION_MAP[self._state], - self._result.__class__.__name__) - return '<%s at %#x state=%s>' % ( - self.__class__.__name__, - id(self), - _STATE_TO_DESCRIPTION_MAP[self._state]) - - def cancel(self): - """Cancel the future if possible. - - Returns True if the future was cancelled, False otherwise. A future - cannot be cancelled if it is running or has already completed. - """ - with self._condition: - if self._state in [RUNNING, FINISHED]: - return False - - if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]: - return True - - self._state = CANCELLED - self._condition.notify_all() - - self._invoke_callbacks() - return True - - def cancelled(self): - """Return True if the future was cancelled.""" - with self._condition: - return self._state in [CANCELLED, CANCELLED_AND_NOTIFIED] - - def running(self): - """Return True if the future is currently executing.""" - with self._condition: - return self._state == RUNNING - - def done(self): - """Return True of the future was cancelled or finished executing.""" - with self._condition: - return self._state in [CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED] - - def __get_result(self): - if self._exception: - if isinstance(self._exception, types.InstanceType): - # The exception is an instance of an old-style class, which - # means type(self._exception) returns types.ClassType instead - # of the exception's actual class type. - exception_type = self._exception.__class__ - else: - exception_type = type(self._exception) - raise exception_type, self._exception, self._traceback - else: - return self._result - - def add_done_callback(self, fn): - """Attaches a callable that will be called when the future finishes. - - Args: - fn: A callable that will be called with this future as its only - argument when the future completes or is cancelled. The callable - will always be called by a thread in the same process in which - it was added. If the future has already completed or been - cancelled then the callable will be called immediately. These - callables are called in the order that they were added. - """ - with self._condition: - if self._state not in [CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED]: - self._done_callbacks.append(fn) - return - fn(self) - - def result(self, timeout=None): - """Return the result of the call that the future represents. - - Args: - timeout: The number of seconds to wait for the result if the future - isn't done. If None, then there is no limit on the wait time. - - Returns: - The result of the call that the future represents. - - Raises: - CancelledError: If the future was cancelled. - TimeoutError: If the future didn't finish executing before the given - timeout. - Exception: If the call raised then that exception will be raised. - """ - with self._condition: - if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]: - raise CancelledError() - elif self._state == FINISHED: - return self.__get_result() - - self._condition.wait(timeout) - - if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]: - raise CancelledError() - elif self._state == FINISHED: - return self.__get_result() - else: - raise TimeoutError() - - def exception_info(self, timeout=None): - """Return a tuple of (exception, traceback) raised by the call that the - future represents. - - Args: - timeout: The number of seconds to wait for the exception if the - future isn't done. If None, then there is no limit on the wait - time. - - Returns: - The exception raised by the call that the future represents or None - if the call completed without raising. - - Raises: - CancelledError: If the future was cancelled. - TimeoutError: If the future didn't finish executing before the given - timeout. - """ - with self._condition: - if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]: - raise CancelledError() - elif self._state == FINISHED: - return self._exception, self._traceback - - self._condition.wait(timeout) - - if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]: - raise CancelledError() - elif self._state == FINISHED: - return self._exception, self._traceback - else: - raise TimeoutError() - - def exception(self, timeout=None): - """Return the exception raised by the call that the future represents. - - Args: - timeout: The number of seconds to wait for the exception if the - future isn't done. If None, then there is no limit on the wait - time. - - Returns: - The exception raised by the call that the future represents or None - if the call completed without raising. - - Raises: - CancelledError: If the future was cancelled. - TimeoutError: If the future didn't finish executing before the given - timeout. - """ - return self.exception_info(timeout)[0] - - # The following methods should only be used by Executors and in tests. - def set_running_or_notify_cancel(self): - """Mark the future as running or process any cancel notifications. - - Should only be used by Executor implementations and unit tests. - - If the future has been cancelled (cancel() was called and returned - True) then any threads waiting on the future completing (though calls - to as_completed() or wait()) are notified and False is returned. - - If the future was not cancelled then it is put in the running state - (future calls to running() will return True) and True is returned. - - This method should be called by Executor implementations before - executing the work associated with this future. If this method returns - False then the work should not be executed. - - Returns: - False if the Future was cancelled, True otherwise. - - Raises: - RuntimeError: if this method was already called or if set_result() - or set_exception() was called. - """ - with self._condition: - if self._state == CANCELLED: - self._state = CANCELLED_AND_NOTIFIED - for waiter in self._waiters: - waiter.add_cancelled(self) - # self._condition.notify_all() is not necessary because - # self.cancel() triggers a notification. - return False - elif self._state == PENDING: - self._state = RUNNING - return True - else: - LOGGER.critical('Future %s in unexpected state: %s', - id(self), - self._state) - raise RuntimeError('Future in unexpected state') - - def set_result(self, result): - """Sets the return value of work associated with the future. - - Should only be used by Executor implementations and unit tests. - """ - with self._condition: - self._result = result - self._state = FINISHED - for waiter in self._waiters: - waiter.add_result(self) - self._condition.notify_all() - self._invoke_callbacks() - - def set_exception_info(self, exception, traceback): - """Sets the result of the future as being the given exception - and traceback. - - Should only be used by Executor implementations and unit tests. - """ - with self._condition: - self._exception = exception - self._traceback = traceback - self._state = FINISHED - for waiter in self._waiters: - waiter.add_exception(self) - self._condition.notify_all() - self._invoke_callbacks() - - def set_exception(self, exception): - """Sets the result of the future as being the given exception. - - Should only be used by Executor implementations and unit tests. - """ - self.set_exception_info(exception, None) - -class Executor(object): - """This is an abstract base class for concrete asynchronous executors.""" - - def submit(self, fn, *args, **kwargs): - """Submits a callable to be executed with the given arguments. - - Schedules the callable to be executed as fn(*args, **kwargs) and returns - a Future instance representing the execution of the callable. - - Returns: - A Future representing the given call. - """ - raise NotImplementedError() - - def map(self, fn, *iterables, **kwargs): - """Returns an iterator equivalent to map(fn, iter). - - Args: - fn: A callable that will take as many arguments as there are - passed iterables. - timeout: The maximum number of seconds to wait. If None, then there - is no limit on the wait time. - - Returns: - An iterator equivalent to: map(func, *iterables) but the calls may - be evaluated out-of-order. - - Raises: - TimeoutError: If the entire result iterator could not be generated - before the given timeout. - Exception: If fn(*args) raises for any values. - """ - timeout = kwargs.get('timeout') - if timeout is not None: - end_time = timeout + time.time() - - fs = [self.submit(fn, *args) for args in itertools.izip(*iterables)] - - # Yield must be hidden in closure so that the futures are submitted - # before the first iterator value is required. - def result_iterator(): - try: - # reverse to keep finishing order - fs.reverse() - while fs: - # Careful not to keep a reference to the popped future - if timeout is None: - yield fs.pop().result() - else: - yield fs.pop().result(end_time - time.time()) - finally: - for future in fs: - future.cancel() - return result_iterator() - - def shutdown(self, wait=True): - """Clean-up the resources associated with the Executor. - - It is safe to call this method several times. Otherwise, no other - methods can be called after this one. - - Args: - wait: If True then shutdown will not return until all running - futures have finished executing and the resources used by the - executor have been reclaimed. - """ - pass - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.shutdown(wait=True) - return False
--- a/mercurial/thirdparty/concurrent/futures/process.py Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,365 +0,0 @@ -# Copyright 2009 Brian Quinlan. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Implements ProcessPoolExecutor. - -The follow diagram and text describe the data-flow through the system: - -|======================= In-process =====================|== Out-of-process ==| - -+----------+ +----------+ +--------+ +-----------+ +---------+ -| | => | Work Ids | => | | => | Call Q | => | | -| | +----------+ | | +-----------+ | | -| | | ... | | | | ... | | | -| | | 6 | | | | 5, call() | | | -| | | 7 | | | | ... | | | -| Process | | ... | | Local | +-----------+ | Process | -| Pool | +----------+ | Worker | | #1..n | -| Executor | | Thread | | | -| | +----------- + | | +-----------+ | | -| | <=> | Work Items | <=> | | <= | Result Q | <= | | -| | +------------+ | | +-----------+ | | -| | | 6: call() | | | | ... | | | -| | | future | | | | 4, result | | | -| | | ... | | | | 3, except | | | -+----------+ +------------+ +--------+ +-----------+ +---------+ - -Executor.submit() called: -- creates a uniquely numbered _WorkItem and adds it to the "Work Items" dict -- adds the id of the _WorkItem to the "Work Ids" queue - -Local worker thread: -- reads work ids from the "Work Ids" queue and looks up the corresponding - WorkItem from the "Work Items" dict: if the work item has been cancelled then - it is simply removed from the dict, otherwise it is repackaged as a - _CallItem and put in the "Call Q". New _CallItems are put in the "Call Q" - until "Call Q" is full. NOTE: the size of the "Call Q" is kept small because - calls placed in the "Call Q" can no longer be cancelled with Future.cancel(). -- reads _ResultItems from "Result Q", updates the future stored in the - "Work Items" dict and deletes the dict entry - -Process #1..n: -- reads _CallItems from "Call Q", executes the calls, and puts the resulting - _ResultItems in "Request Q" -""" - -from __future__ import absolute_import - -import atexit -from . import _base -import Queue as queue -import multiprocessing -import threading -import weakref -import sys - -__author__ = 'Brian Quinlan (brian@sweetapp.com)' - -# Workers are created as daemon threads and processes. This is done to allow the -# interpreter to exit when there are still idle processes in a -# ProcessPoolExecutor's process pool (i.e. shutdown() was not called). However, -# allowing workers to die with the interpreter has two undesirable properties: -# - The workers would still be running during interpretor shutdown, -# meaning that they would fail in unpredictable ways. -# - The workers could be killed while evaluating a work item, which could -# be bad if the callable being evaluated has external side-effects e.g. -# writing to a file. -# -# To work around this problem, an exit handler is installed which tells the -# workers to exit when their work queues are empty and then waits until the -# threads/processes finish. - -_threads_queues = weakref.WeakKeyDictionary() -_shutdown = False - -def _python_exit(): - global _shutdown - _shutdown = True - items = list(_threads_queues.items()) if _threads_queues else () - for t, q in items: - q.put(None) - for t, q in items: - t.join(sys.maxint) - -# Controls how many more calls than processes will be queued in the call queue. -# A smaller number will mean that processes spend more time idle waiting for -# work while a larger number will make Future.cancel() succeed less frequently -# (Futures in the call queue cannot be cancelled). -EXTRA_QUEUED_CALLS = 1 - -class _WorkItem(object): - def __init__(self, future, fn, args, kwargs): - self.future = future - self.fn = fn - self.args = args - self.kwargs = kwargs - -class _ResultItem(object): - def __init__(self, work_id, exception=None, result=None): - self.work_id = work_id - self.exception = exception - self.result = result - -class _CallItem(object): - def __init__(self, work_id, fn, args, kwargs): - self.work_id = work_id - self.fn = fn - self.args = args - self.kwargs = kwargs - -def _process_worker(call_queue, result_queue): - """Evaluates calls from call_queue and places the results in result_queue. - - This worker is run in a separate process. - - Args: - call_queue: A multiprocessing.Queue of _CallItems that will be read and - evaluated by the worker. - result_queue: A multiprocessing.Queue of _ResultItems that will written - to by the worker. - shutdown: A multiprocessing.Event that will be set as a signal to the - worker that it should exit when call_queue is empty. - """ - while True: - call_item = call_queue.get(block=True) - if call_item is None: - # Wake up queue management thread - result_queue.put(None) - return - try: - r = call_item.fn(*call_item.args, **call_item.kwargs) - except: - e = sys.exc_info()[1] - result_queue.put(_ResultItem(call_item.work_id, - exception=e)) - else: - result_queue.put(_ResultItem(call_item.work_id, - result=r)) - -def _add_call_item_to_queue(pending_work_items, - work_ids, - call_queue): - """Fills call_queue with _WorkItems from pending_work_items. - - This function never blocks. - - Args: - pending_work_items: A dict mapping work ids to _WorkItems e.g. - {5: <_WorkItem...>, 6: <_WorkItem...>, ...} - work_ids: A queue.Queue of work ids e.g. Queue([5, 6, ...]). Work ids - are consumed and the corresponding _WorkItems from - pending_work_items are transformed into _CallItems and put in - call_queue. - call_queue: A multiprocessing.Queue that will be filled with _CallItems - derived from _WorkItems. - """ - while True: - if call_queue.full(): - return - try: - work_id = work_ids.get(block=False) - except queue.Empty: - return - else: - work_item = pending_work_items[work_id] - - if work_item.future.set_running_or_notify_cancel(): - call_queue.put(_CallItem(work_id, - work_item.fn, - work_item.args, - work_item.kwargs), - block=True) - else: - del pending_work_items[work_id] - continue - -def _queue_management_worker(executor_reference, - processes, - pending_work_items, - work_ids_queue, - call_queue, - result_queue): - """Manages the communication between this process and the worker processes. - - This function is run in a local thread. - - Args: - executor_reference: A weakref.ref to the ProcessPoolExecutor that owns - this thread. Used to determine if the ProcessPoolExecutor has been - garbage collected and that this function can exit. - process: A list of the multiprocessing.Process instances used as - workers. - pending_work_items: A dict mapping work ids to _WorkItems e.g. - {5: <_WorkItem...>, 6: <_WorkItem...>, ...} - work_ids_queue: A queue.Queue of work ids e.g. Queue([5, 6, ...]). - call_queue: A multiprocessing.Queue that will be filled with _CallItems - derived from _WorkItems for processing by the process workers. - result_queue: A multiprocessing.Queue of _ResultItems generated by the - process workers. - """ - nb_shutdown_processes = [0] - def shutdown_one_process(): - """Tell a worker to terminate, which will in turn wake us again""" - call_queue.put(None) - nb_shutdown_processes[0] += 1 - while True: - _add_call_item_to_queue(pending_work_items, - work_ids_queue, - call_queue) - - result_item = result_queue.get(block=True) - if result_item is not None: - work_item = pending_work_items[result_item.work_id] - del pending_work_items[result_item.work_id] - - if result_item.exception: - work_item.future.set_exception(result_item.exception) - else: - work_item.future.set_result(result_item.result) - # Delete references to object. See issue16284 - del work_item - # Check whether we should start shutting down. - executor = executor_reference() - # No more work items can be added if: - # - The interpreter is shutting down OR - # - The executor that owns this worker has been collected OR - # - The executor that owns this worker has been shutdown. - if _shutdown or executor is None or executor._shutdown_thread: - # Since no new work items can be added, it is safe to shutdown - # this thread if there are no pending work items. - if not pending_work_items: - while nb_shutdown_processes[0] < len(processes): - shutdown_one_process() - # If .join() is not called on the created processes then - # some multiprocessing.Queue methods may deadlock on Mac OS - # X. - for p in processes: - p.join() - call_queue.close() - return - del executor - -_system_limits_checked = False -_system_limited = None -def _check_system_limits(): - global _system_limits_checked, _system_limited - if _system_limits_checked: - if _system_limited: - raise NotImplementedError(_system_limited) - _system_limits_checked = True - try: - import os - nsems_max = os.sysconf("SC_SEM_NSEMS_MAX") - except (AttributeError, ValueError): - # sysconf not available or setting not available - return - if nsems_max == -1: - # indetermine limit, assume that limit is determined - # by available memory only - return - if nsems_max >= 256: - # minimum number of semaphores available - # according to POSIX - return - _system_limited = "system provides too few semaphores (%d available, 256 necessary)" % nsems_max - raise NotImplementedError(_system_limited) - - -class ProcessPoolExecutor(_base.Executor): - def __init__(self, max_workers=None): - """Initializes a new ProcessPoolExecutor instance. - - Args: - max_workers: The maximum number of processes that can be used to - execute the given calls. If None or not given then as many - worker processes will be created as the machine has processors. - """ - _check_system_limits() - - if max_workers is None: - self._max_workers = multiprocessing.cpu_count() - else: - if max_workers <= 0: - raise ValueError("max_workers must be greater than 0") - - self._max_workers = max_workers - - # Make the call queue slightly larger than the number of processes to - # prevent the worker processes from idling. But don't make it too big - # because futures in the call queue cannot be cancelled. - self._call_queue = multiprocessing.Queue(self._max_workers + - EXTRA_QUEUED_CALLS) - self._result_queue = multiprocessing.Queue() - self._work_ids = queue.Queue() - self._queue_management_thread = None - self._processes = set() - - # Shutdown is a two-step process. - self._shutdown_thread = False - self._shutdown_lock = threading.Lock() - self._queue_count = 0 - self._pending_work_items = {} - - def _start_queue_management_thread(self): - # When the executor gets lost, the weakref callback will wake up - # the queue management thread. - def weakref_cb(_, q=self._result_queue): - q.put(None) - if self._queue_management_thread is None: - self._queue_management_thread = threading.Thread( - target=_queue_management_worker, - args=(weakref.ref(self, weakref_cb), - self._processes, - self._pending_work_items, - self._work_ids, - self._call_queue, - self._result_queue)) - self._queue_management_thread.daemon = True - self._queue_management_thread.start() - _threads_queues[self._queue_management_thread] = self._result_queue - - def _adjust_process_count(self): - for _ in range(len(self._processes), self._max_workers): - p = multiprocessing.Process( - target=_process_worker, - args=(self._call_queue, - self._result_queue)) - p.start() - self._processes.add(p) - - def submit(self, fn, *args, **kwargs): - with self._shutdown_lock: - if self._shutdown_thread: - raise RuntimeError('cannot schedule new futures after shutdown') - - f = _base.Future() - w = _WorkItem(f, fn, args, kwargs) - - self._pending_work_items[self._queue_count] = w - self._work_ids.put(self._queue_count) - self._queue_count += 1 - # Wake up queue management thread - self._result_queue.put(None) - - self._start_queue_management_thread() - self._adjust_process_count() - return f - submit.__doc__ = _base.Executor.submit.__doc__ - - def shutdown(self, wait=True): - with self._shutdown_lock: - self._shutdown_thread = True - if self._queue_management_thread: - # Wake up queue management thread - self._result_queue.put(None) - if wait: - self._queue_management_thread.join(sys.maxint) - # To reduce the risk of openning too many files, remove references to - # objects that use file descriptors. - self._queue_management_thread = None - self._call_queue = None - self._result_queue = None - self._processes = None - shutdown.__doc__ = _base.Executor.shutdown.__doc__ - -atexit.register(_python_exit)
--- a/mercurial/thirdparty/concurrent/futures/thread.py Tue Apr 05 10:55:28 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -# Copyright 2009 Brian Quinlan. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Implements ThreadPoolExecutor.""" - -from __future__ import absolute_import - -import atexit -from . import _base -import itertools -import Queue as queue -import threading -import weakref -import sys - -try: - from multiprocessing import cpu_count -except ImportError: - # some platforms don't have multiprocessing - def cpu_count(): - return None - -__author__ = 'Brian Quinlan (brian@sweetapp.com)' - -# Workers are created as daemon threads. This is done to allow the interpreter -# to exit when there are still idle threads in a ThreadPoolExecutor's thread -# pool (i.e. shutdown() was not called). However, allowing workers to die with -# the interpreter has two undesirable properties: -# - The workers would still be running during interpretor shutdown, -# meaning that they would fail in unpredictable ways. -# - The workers could be killed while evaluating a work item, which could -# be bad if the callable being evaluated has external side-effects e.g. -# writing to a file. -# -# To work around this problem, an exit handler is installed which tells the -# workers to exit when their work queues are empty and then waits until the -# threads finish. - -_threads_queues = weakref.WeakKeyDictionary() -_shutdown = False - -def _python_exit(): - global _shutdown - _shutdown = True - items = list(_threads_queues.items()) if _threads_queues else () - for t, q in items: - q.put(None) - for t, q in items: - t.join(sys.maxint) - -atexit.register(_python_exit) - -class _WorkItem(object): - def __init__(self, future, fn, args, kwargs): - self.future = future - self.fn = fn - self.args = args - self.kwargs = kwargs - - def run(self): - if not self.future.set_running_or_notify_cancel(): - return - - try: - result = self.fn(*self.args, **self.kwargs) - except: - e, tb = sys.exc_info()[1:] - self.future.set_exception_info(e, tb) - else: - self.future.set_result(result) - -def _worker(executor_reference, work_queue): - try: - while True: - work_item = work_queue.get(block=True) - if work_item is not None: - work_item.run() - # Delete references to object. See issue16284 - del work_item - continue - executor = executor_reference() - # Exit if: - # - The interpreter is shutting down OR - # - The executor that owns the worker has been collected OR - # - The executor that owns the worker has been shutdown. - if _shutdown or executor is None or executor._shutdown: - # Notice other workers - work_queue.put(None) - return - del executor - except: - _base.LOGGER.critical('Exception in worker', exc_info=True) - - -class ThreadPoolExecutor(_base.Executor): - - # Used to assign unique thread names when thread_name_prefix is not supplied. - _counter = itertools.count().next - - def __init__(self, max_workers=None, thread_name_prefix=''): - """Initializes a new ThreadPoolExecutor instance. - - Args: - max_workers: The maximum number of threads that can be used to - execute the given calls. - thread_name_prefix: An optional name prefix to give our threads. - """ - if max_workers is None: - # Use this number because ThreadPoolExecutor is often - # used to overlap I/O instead of CPU work. - max_workers = (cpu_count() or 1) * 5 - if max_workers <= 0: - raise ValueError("max_workers must be greater than 0") - - self._max_workers = max_workers - self._work_queue = queue.Queue() - self._threads = set() - self._shutdown = False - self._shutdown_lock = threading.Lock() - self._thread_name_prefix = (thread_name_prefix or - ("ThreadPoolExecutor-%d" % self._counter())) - - def submit(self, fn, *args, **kwargs): - with self._shutdown_lock: - if self._shutdown: - raise RuntimeError('cannot schedule new futures after shutdown') - - f = _base.Future() - w = _WorkItem(f, fn, args, kwargs) - - self._work_queue.put(w) - self._adjust_thread_count() - return f - submit.__doc__ = _base.Executor.submit.__doc__ - - def _adjust_thread_count(self): - # When the executor gets lost, the weakref callback will wake up - # the worker threads. - def weakref_cb(_, q=self._work_queue): - q.put(None) - # TODO(bquinlan): Should avoid creating new threads if there are more - # idle threads than items in the work queue. - num_threads = len(self._threads) - if num_threads < self._max_workers: - thread_name = '%s_%d' % (self._thread_name_prefix or self, - num_threads) - t = threading.Thread(name=thread_name, target=_worker, - args=(weakref.ref(self, weakref_cb), - self._work_queue)) - t.daemon = True - t.start() - self._threads.add(t) - _threads_queues[t] = self._work_queue - - def shutdown(self, wait=True): - with self._shutdown_lock: - self._shutdown = True - self._work_queue.put(None) - if wait: - for t in self._threads: - t.join(sys.maxint) - shutdown.__doc__ = _base.Executor.shutdown.__doc__
--- a/mercurial/transaction.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/transaction.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno @@ -383,7 +382,7 @@ skip_pre = group == GEN_GROUP_POST_FINALIZE skip_post = group == GEN_GROUP_PRE_FINALIZE - for id, entry in sorted(pycompat.iteritems(self._filegenerators)): + for id, entry in sorted(self._filegenerators.items()): any = True order, filenames, genfunc, location, post_finalize = entry
--- a/mercurial/treediscovery.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/treediscovery.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections
--- a/mercurial/txnutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/txnutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno
--- a/mercurial/ui.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/ui.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import collections import contextlib @@ -170,7 +169,7 @@ return pycompat.rapply(pycompat.bytesurl, maybestr) -class httppasswordmgrdbproxy(object): +class httppasswordmgrdbproxy: """Delays loading urllib2 until it's needed.""" def __init__(self): @@ -208,7 +207,7 @@ _reqexithandlers = [] -class ui(object): +class ui: def __init__(self, src=None): """Create a fresh new ui object if no src given @@ -1726,9 +1725,9 @@ if usereadline: self.flush() prompt = encoding.strfromlocal(prompt) - line = encoding.strtolocal(pycompat.rawinput(prompt)) + line = encoding.strtolocal(input(prompt)) # When stdin is in binary mode on Windows, it can cause - # raw_input() to emit an extra trailing carriage return + # input() to emit an extra trailing carriage return if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'): line = line[:-1] else: @@ -2118,9 +2117,7 @@ """ if not self._loggers: return - activeloggers = [ - l for l in pycompat.itervalues(self._loggers) if l.tracked(event) - ] + activeloggers = [l for l in self._loggers.values() if l.tracked(event)] if not activeloggers: return msg = msgfmt % msgargs
--- a/mercurial/unionrepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/unionrepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,7 +11,6 @@ allowing operations like diff and log with revsets. """ -from __future__ import absolute_import from .i18n import _ from .pycompat import getattr @@ -210,7 +209,7 @@ return False -class unionrepository(object): +class unionrepository: """Represents the union of data in 2 repositories. Instances are not usable if constructed directly. Use ``instance()``
--- a/mercurial/upgrade.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/upgrade.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .i18n import _ from . import (
--- a/mercurial/upgrade_utils/actions.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/upgrade_utils/actions.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from ..i18n import _ from .. import ( @@ -46,7 +45,7 @@ OPTIMISATION = b'optimization' -class improvement(object): +class improvement: """Represents an improvement that can be made as part of an upgrade.""" ### The following attributes should be defined for each subclass: @@ -685,7 +684,7 @@ return newactions -class UpgradeOperation(object): +class UpgradeOperation: """represent the work to be done during an upgrade""" def __init__(
--- a/mercurial/upgrade_utils/engine.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/upgrade_utils/engine.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import stat
--- a/mercurial/url.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/url.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,11 +7,9 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import base64 import socket -import sys from .i18n import _ from .pycompat import getattr @@ -52,7 +50,7 @@ return s -class passwordmgr(object): +class passwordmgr: def __init__(self, ui, passwddb): self.ui = ui self.passwddb = passwddb @@ -241,19 +239,15 @@ if x.lower().startswith('proxy-') } self.send(b'CONNECT %s HTTP/1.0\r\n' % self.realhostport) - for header in pycompat.iteritems(proxyheaders): + for header in proxyheaders.items(): self.send(b'%s: %s\r\n' % header) self.send(b'\r\n') # majority of the following code is duplicated from # httplib.HTTPConnection as there are no adequate places to - # override functions to provide the needed functionality - # strict was removed in Python 3.4. - kwargs = {} - if not pycompat.ispy3: - kwargs[b'strict'] = self.strict + # override functions to provide the needed functionality. - res = self.response_class(self.sock, method=self._method, **kwargs) + res = self.response_class(self.sock, method=self._method) while True: version, status, reason = res._read_status() @@ -348,16 +342,6 @@ keepalive.HTTPConnection.__init__(self, *args, **kwargs) self._create_connection = createconn - if sys.version_info < (2, 7, 7): - # copied from 2.7.14, since old implementations directly call - # socket.create_connection() - def connect(self): - self.sock = self._create_connection( - (self.host, self.port), self.timeout, self.source_address - ) - if self._tunnel_host: - self._tunnel() - class logginghttphandler(httphandler): """HTTP handler that logs socket I/O."""
--- a/mercurial/urllibcompat.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/urllibcompat.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,12 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import + +import http.server +import urllib.error +import urllib.parse +import urllib.request +import urllib.response from .pycompat import getattr from . import pycompat @@ -12,7 +17,7 @@ _sysstr = pycompat.sysstr -class _pycompatstub(object): +class _pycompatstub: def __init__(self): self._aliases = {} @@ -40,199 +45,109 @@ urlreq = _pycompatstub() urlerr = _pycompatstub() -if pycompat.ispy3: - import urllib.parse - - urlreq._registeraliases( - urllib.parse, - ( - b"splitattr", - b"splitpasswd", - b"splitport", - b"splituser", - b"urlparse", - b"urlunparse", - ), - ) - urlreq._registeralias(urllib.parse, b"parse_qs", b"parseqs") - urlreq._registeralias(urllib.parse, b"parse_qsl", b"parseqsl") - urlreq._registeralias(urllib.parse, b"unquote_to_bytes", b"unquote") - import urllib.request - - urlreq._registeraliases( - urllib.request, - ( - b"AbstractHTTPHandler", - b"BaseHandler", - b"build_opener", - b"FileHandler", - b"FTPHandler", - b"ftpwrapper", - b"HTTPHandler", - b"HTTPSHandler", - b"install_opener", - b"pathname2url", - b"HTTPBasicAuthHandler", - b"HTTPDigestAuthHandler", - b"HTTPPasswordMgrWithDefaultRealm", - b"ProxyHandler", - b"Request", - b"url2pathname", - b"urlopen", - ), - ) - import urllib.response - - urlreq._registeraliases( - urllib.response, - ( - b"addclosehook", - b"addinfourl", - ), - ) - import urllib.error +urlreq._registeraliases( + urllib.parse, + ( + b"splitattr", + b"splitpasswd", + b"splitport", + b"splituser", + b"urlparse", + b"urlunparse", + ), +) +urlreq._registeralias(urllib.parse, b"parse_qs", b"parseqs") +urlreq._registeralias(urllib.parse, b"parse_qsl", b"parseqsl") +urlreq._registeralias(urllib.parse, b"unquote_to_bytes", b"unquote") - urlerr._registeraliases( - urllib.error, - ( - b"HTTPError", - b"URLError", - ), - ) - import http.server - - httpserver._registeraliases( - http.server, - ( - b"HTTPServer", - b"BaseHTTPRequestHandler", - b"SimpleHTTPRequestHandler", - b"CGIHTTPRequestHandler", - ), - ) - - # urllib.parse.quote() accepts both str and bytes, decodes bytes - # (if necessary), and returns str. This is wonky. We provide a custom - # implementation that only accepts bytes and emits bytes. - def quote(s, safe='/'): - # bytestr has an __iter__ that emits characters. quote_from_bytes() - # does an iteration and expects ints. We coerce to bytes to appease it. - if isinstance(s, pycompat.bytestr): - s = bytes(s) - s = urllib.parse.quote_from_bytes(s, safe=safe) - return s.encode('ascii', 'strict') - - # urllib.parse.urlencode() returns str. We use this function to make - # sure we return bytes. - def urlencode(query, doseq=False): - s = urllib.parse.urlencode(query, doseq=doseq) - return s.encode('ascii') - - urlreq.quote = quote - urlreq.urlencode = urlencode - - def getfullurl(req): - return req.full_url - - def gethost(req): - return req.host - - def getselector(req): - return req.selector - - def getdata(req): - return req.data - - def hasdata(req): - return req.data is not None +urlreq._registeraliases( + urllib.request, + ( + b"AbstractHTTPHandler", + b"BaseHandler", + b"build_opener", + b"FileHandler", + b"FTPHandler", + b"ftpwrapper", + b"HTTPHandler", + b"HTTPSHandler", + b"install_opener", + b"pathname2url", + b"HTTPBasicAuthHandler", + b"HTTPDigestAuthHandler", + b"HTTPPasswordMgrWithDefaultRealm", + b"ProxyHandler", + b"Request", + b"url2pathname", + b"urlopen", + ), +) -else: - # pytype: disable=import-error - import BaseHTTPServer - import CGIHTTPServer - import SimpleHTTPServer - import urllib2 - import urllib - import urlparse +urlreq._registeraliases( + urllib.response, + ( + b"addclosehook", + b"addinfourl", + ), +) - # pytype: enable=import-error +urlerr._registeraliases( + urllib.error, + ( + b"HTTPError", + b"URLError", + ), +) + +httpserver._registeraliases( + http.server, + ( + b"HTTPServer", + b"BaseHTTPRequestHandler", + b"SimpleHTTPRequestHandler", + b"CGIHTTPRequestHandler", + ), +) - urlreq._registeraliases( - urllib, - ( - b"addclosehook", - b"addinfourl", - b"ftpwrapper", - b"pathname2url", - b"quote", - b"splitattr", - b"splitpasswd", - b"splitport", - b"splituser", - b"unquote", - b"url2pathname", - b"urlencode", - ), - ) - urlreq._registeraliases( - urllib2, - ( - b"AbstractHTTPHandler", - b"BaseHandler", - b"build_opener", - b"FileHandler", - b"FTPHandler", - b"HTTPBasicAuthHandler", - b"HTTPDigestAuthHandler", - b"HTTPHandler", - b"HTTPPasswordMgrWithDefaultRealm", - b"HTTPSHandler", - b"install_opener", - b"ProxyHandler", - b"Request", - b"urlopen", - ), - ) - urlreq._registeraliases( - urlparse, - ( - b"urlparse", - b"urlunparse", - ), - ) - urlreq._registeralias(urlparse, b"parse_qs", b"parseqs") - urlreq._registeralias(urlparse, b"parse_qsl", b"parseqsl") - urlerr._registeraliases( - urllib2, - ( - b"HTTPError", - b"URLError", - ), - ) - httpserver._registeraliases( - BaseHTTPServer, - ( - b"HTTPServer", - b"BaseHTTPRequestHandler", - ), - ) - httpserver._registeraliases( - SimpleHTTPServer, (b"SimpleHTTPRequestHandler",) - ) - httpserver._registeraliases(CGIHTTPServer, (b"CGIHTTPRequestHandler",)) +# urllib.parse.quote() accepts both str and bytes, decodes bytes +# (if necessary), and returns str. This is wonky. We provide a custom +# implementation that only accepts bytes and emits bytes. +def quote(s, safe='/'): + # bytestr has an __iter__ that emits characters. quote_from_bytes() + # does an iteration and expects ints. We coerce to bytes to appease it. + if isinstance(s, pycompat.bytestr): + s = bytes(s) + s = urllib.parse.quote_from_bytes(s, safe=safe) + return s.encode('ascii', 'strict') + + +# urllib.parse.urlencode() returns str. We use this function to make +# sure we return bytes. +def urlencode(query, doseq=False): + s = urllib.parse.urlencode(query, doseq=doseq) + return s.encode('ascii') + - def gethost(req): - return req.get_host() +urlreq.quote = quote +urlreq.urlencode = urlencode + - def getselector(req): - return req.get_selector() +def getfullurl(req): + return req.full_url + + +def gethost(req): + return req.host - def getfullurl(req): - return req.get_full_url() + +def getselector(req): + return req.selector + - def getdata(req): - return req.get_data() +def getdata(req): + return req.data - def hasdata(req): - return req.has_data() + +def hasdata(req): + return req.data is not None
--- a/mercurial/util.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/util.py Tue Apr 05 11:09:03 2022 +0200 @@ -13,7 +13,6 @@ hide platform-specific details from the core. """ -from __future__ import absolute_import, print_function import abc import collections @@ -21,11 +20,12 @@ import errno import gc import hashlib +import io import itertools import locale import mmap import os -import platform as pyplatform +import pickle # provides util.pickle symbol import re as remod import shutil import stat @@ -42,7 +42,6 @@ open, setattr, ) -from .node import hex from hgdemandimport import tracing from . import ( encoding, @@ -76,10 +75,9 @@ cookielib = pycompat.cookielib httplib = pycompat.httplib -pickle = pycompat.pickle safehasattr = pycompat.safehasattr socketserver = pycompat.socketserver -bytesio = pycompat.bytesio +bytesio = io.BytesIO # TODO deprecate stringio name, as it is a lie on Python 3. stringio = bytesio xmlrpclib = pycompat.xmlrpclib @@ -189,7 +187,7 @@ warnings.filterwarnings('default', '', DeprecationWarning, 'mercurial') warnings.filterwarnings('default', '', DeprecationWarning, 'hgext') warnings.filterwarnings('default', '', DeprecationWarning, 'hgext3rd') -if _dowarn and pycompat.ispy3: +if _dowarn: # silence warning emitted by passing user string to re.sub() warnings.filterwarnings( 'ignore', 'bad escape', DeprecationWarning, 'mercurial' @@ -233,7 +231,7 @@ assert k in DIGESTS -class digester(object): +class digester: """helper to compute digests. This helper can be used to compute one or more digests given their name. @@ -281,7 +279,7 @@ return None -class digestchecker(object): +class digestchecker: """file handle wrapper that additionally checks content against a given size and digests. @@ -331,7 +329,7 @@ _chunksize = 4096 -class bufferedinputpipe(object): +class bufferedinputpipe: """a manually buffered input pipe Python will not let us use buffered IO and lazy reading with 'polling' at @@ -459,7 +457,7 @@ raise -class fileobjectproxy(object): +class fileobjectproxy: """A proxy around file objects that tells a watcher when events occur. This type is intended to only be used for testing purposes. Think hard @@ -695,7 +693,7 @@ } -class socketproxy(object): +class socketproxy: """A proxy around a socket that tells a watcher when events occur. This is like ``fileobjectproxy`` except for sockets. @@ -818,7 +816,7 @@ ) -class baseproxyobserver(object): +class baseproxyobserver: def __init__(self, fh, name, logdata, logdataapis): self.fh = fh self.name = name @@ -1258,7 +1256,7 @@ return f -class cow(object): +class cow: """helper class to make copy-on-write easier Call preparewrite before doing any writes. @@ -1302,7 +1300,7 @@ # __setitem__() isn't called as of PyPy 5.8.0 def update(self, src, **f): if isinstance(src, dict): - src = pycompat.iteritems(src) + src = src.items() for k, v in src: self[k] = v for k in f: @@ -1351,7 +1349,7 @@ """ -class transactional(object): # pytype: disable=ignored-metaclass +class transactional: # pytype: disable=ignored-metaclass """Base class for making a transactional type into a context manager.""" __metaclass__ = abc.ABCMeta @@ -1402,7 +1400,7 @@ yield enter_result -class _lrucachenode(object): +class _lrucachenode: """A node in a doubly linked list. Holds a reference to nodes on either side as well as a key-value @@ -1426,7 +1424,7 @@ self.cost = 0 -class lrucachedict(object): +class lrucachedict: """Dict that caches most recent accesses and sets. The dict consists of an actual backing dict - indexed by original @@ -1757,7 +1755,7 @@ return f -class propertycache(object): +class propertycache: def __init__(self, func): self.func = func self.name = func.__name__ @@ -2216,7 +2214,7 @@ _re2 = False -class _re(object): +class _re: def _checkre2(self): global _re2 global _re2_input @@ -2418,7 +2416,7 @@ return temp -class filestat(object): +class filestat: """help to exactly detect change of a file 'stat' attribute is result of 'os.stat()' if specified 'path' @@ -2524,7 +2522,7 @@ return not self == other -class atomictempfile(object): +class atomictempfile: """writable file object that atomically updates a file All writes will go to a temporary copy of the original file. Call @@ -2667,7 +2665,7 @@ fp.write(text) -class chunkbuffer(object): +class chunkbuffer: """Allow arbitrary sized chunks of data to be efficiently read from an iterator over chunks of arbitrary size.""" @@ -2772,7 +2770,7 @@ yield s -class cappedreader(object): +class cappedreader: """A file object proxy that allows reading up to N bytes. Given a source file object, instances of this type allow reading up to @@ -2860,7 +2858,7 @@ ) -class transformingwriter(object): +class transformingwriter: """Writable file wrapper to transform data by function""" def __init__(self, fp, encode): @@ -2906,50 +2904,10 @@ fromnativeeol = pycompat.identity nativeeolwriter = pycompat.identity -if pyplatform.python_implementation() == b'CPython' and sys.version_info < ( - 3, - 0, -): - # There is an issue in CPython that some IO methods do not handle EINTR - # correctly. The following table shows what CPython version (and functions) - # are affected (buggy: has the EINTR bug, okay: otherwise): - # - # | < 2.7.4 | 2.7.4 to 2.7.12 | >= 3.0 - # -------------------------------------------------- - # fp.__iter__ | buggy | buggy | okay - # fp.read* | buggy | okay [1] | okay - # - # [1]: fixed by changeset 67dc99a989cd in the cpython hg repo. - # - # Here we workaround the EINTR issue for fileobj.__iter__. Other methods - # like "read*" work fine, as we do not support Python < 2.7.4. - # - # Although we can workaround the EINTR issue for fp.__iter__, it is slower: - # "for x in fp" is 4x faster than "for x in iter(fp.readline, '')" in - # CPython 2, because CPython 2 maintains an internal readahead buffer for - # fp.__iter__ but not other fp.read* methods. - # - # On modern systems like Linux, the "read" syscall cannot be interrupted - # when reading "fast" files like on-disk files. So the EINTR issue only - # affects things like pipes, sockets, ttys etc. We treat "normal" (S_ISREG) - # files approximately as "fast" files and use the fast (unsafe) code path, - # to minimize the performance impact. - - def iterfile(fp): - fastpath = True - if type(fp) is file: - fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode) - if fastpath: - return fp - else: - # fp.readline deals with EINTR correctly, use it as a workaround. - return iter(fp.readline, b'') - - -else: - # PyPy and CPython 3 do not have the EINTR issue thus no workaround needed. - def iterfile(fp): - return fp + +# TODO delete since workaround variant for Python 2 no longer needed. +def iterfile(fp): + return fp def iterlines(iterator): @@ -3008,7 +2966,7 @@ @attr.s -class timedcmstats(object): +class timedcmstats: """Stats information produced by the timedcm context manager on entering.""" # the starting value of the timer as a float (meaning and resulution is @@ -3109,7 +3067,7 @@ raise error.ParseError(_(b"couldn't parse size: %s") % s) -class hooks(object): +class hooks: """A collection of hook functions that can be used to extend a function's behavior. Hooks are called in lexicographic order, based on the names of their sources."""
--- a/mercurial/utils/cborutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/cborutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,12 +5,9 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import struct -import sys -from .. import pycompat # Very short very of RFC 7049... # @@ -175,9 +172,7 @@ """ yield encodelength(MAJOR_TYPE_MAP, len(d)) - for key, value in sorted( - pycompat.iteritems(d), key=lambda x: _mixedtypesortkey(x[0]) - ): + for key, value in sorted(d.items(), key=lambda x: _mixedtypesortkey(x[0])): for chunk in streamencode(key): yield chunk for chunk in streamencode(value): @@ -210,7 +205,7 @@ STREAM_ENCODERS = { bytes: streamencodebytestring, int: streamencodeint, - pycompat.long: streamencodeint, + int: streamencodeint, list: streamencodearray, tuple: streamencodearray, dict: streamencodemap, @@ -250,16 +245,8 @@ """Represents an error decoding CBOR.""" -if sys.version_info.major >= 3: - - def _elementtointeger(b, i): - return b[i] - - -else: - - def _elementtointeger(b, i): - return ord(b[i]) +def _elementtointeger(b, i): + return b[i] STRUCT_BIG_UBYTE = struct.Struct('>B') @@ -496,7 +483,7 @@ return self -class sansiodecoder(object): +class sansiodecoder: """A CBOR decoder that doesn't perform its own I/O. To use, construct an instance and feed it segments containing @@ -989,7 +976,7 @@ return l -class bufferingdecoder(object): +class bufferingdecoder: """A CBOR decoder that buffers undecoded input. This is a glorified wrapper around ``sansiodecoder`` that adds a buffering
--- a/mercurial/utils/compression.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/compression.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,8 +4,6 @@ # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function - import bz2 import collections import zlib @@ -34,7 +32,7 @@ ) -class propertycache(object): +class propertycache: def __init__(self, func): self.func = func self.name = func.__name__ @@ -49,7 +47,7 @@ obj.__dict__[self.name] = value -class compressormanager(object): +class compressormanager: """Holds registrations of various compression engines. This class essentially abstracts the differences between compression @@ -221,7 +219,7 @@ compengines = compressormanager() -class compressionengine(object): +class compressionengine: """Base class for compression engines. Compression engines must implement the interface defined by this class. @@ -340,7 +338,7 @@ raise NotImplementedError() -class _CompressedStreamReader(object): +class _CompressedStreamReader: def __init__(self, fh): if safehasattr(fh, 'unbufferedread'): self._reader = fh.unbufferedread @@ -484,7 +482,7 @@ def decompressorreader(self, fh): return _GzipCompressedStreamReader(fh) - class zlibrevlogcompressor(object): + class zlibrevlogcompressor: def __init__(self, level=None): self._level = level @@ -628,7 +626,7 @@ def decompressorreader(self, fh): return fh - class nooprevlogcompressor(object): + class nooprevlogcompressor: def compress(self, data): return None @@ -700,7 +698,7 @@ def decompressorreader(self, fh): return _ZstdCompressedStreamReader(fh, self._module) - class zstdrevlogcompressor(object): + class zstdrevlogcompressor: def __init__(self, zstd, level=3): # TODO consider omitting frame magic to save 4 bytes. # This writes content sizes into the frame header. That is @@ -784,7 +782,7 @@ # We need to format the docstring. So use a dummy object/type to hold it # rather than mutating the original. - class docobject(object): + class docobject: pass for name in compengines:
--- a/mercurial/utils/dateutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/dateutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import calendar import datetime
--- a/mercurial/utils/hashutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/hashutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import hashlib try:
--- a/mercurial/utils/procutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/procutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import errno @@ -60,7 +59,7 @@ raise IOError(errno.EBADF, 'Bad file descriptor') -class LineBufferedWrapper(object): +class LineBufferedWrapper: def __init__(self, orig): self.orig = orig @@ -81,7 +80,7 @@ def make_line_buffered(stream): - if pycompat.ispy3 and not isinstance(stream, io.BufferedIOBase): + if not isinstance(stream, io.BufferedIOBase): # On Python 3, buffered streams can be expected to subclass # BufferedIOBase. This is definitively the case for the streams # initialized by the interpreter. For unbuffered streams, we don't need @@ -99,7 +98,7 @@ return stream -class WriteAllWrapper(object): +class WriteAllWrapper: def __init__(self, orig): self.orig = orig @@ -122,7 +121,6 @@ def _make_write_all(stream): - assert pycompat.ispy3 if isinstance(stream, WriteAllWrapper): return stream if isinstance(stream, io.BufferedIOBase): @@ -134,52 +132,32 @@ return WriteAllWrapper(stream) -if pycompat.ispy3: - # Python 3 implements its own I/O streams. Unlike stdio of C library, - # sys.stdin/stdout/stderr may be None if underlying fd is closed. - - # TODO: .buffer might not exist if std streams were replaced; we'll need - # a silly wrapper to make a bytes stream backed by a unicode one. +# Python 3 implements its own I/O streams. Unlike stdio of C library, +# sys.stdin/stdout/stderr may be None if underlying fd is closed. - if sys.stdin is None: - stdin = BadFile() - else: - stdin = sys.stdin.buffer - if sys.stdout is None: - stdout = BadFile() - else: - stdout = _make_write_all(sys.stdout.buffer) - if sys.stderr is None: - stderr = BadFile() - else: - stderr = _make_write_all(sys.stderr.buffer) +# TODO: .buffer might not exist if std streams were replaced; we'll need +# a silly wrapper to make a bytes stream backed by a unicode one. - if pycompat.iswindows: - # Work around Windows bugs. - stdout = platform.winstdout(stdout) # pytype: disable=module-attr - stderr = platform.winstdout(stderr) # pytype: disable=module-attr - if isatty(stdout): - # The standard library doesn't offer line-buffered binary streams. - stdout = make_line_buffered(stdout) +if sys.stdin is None: + stdin = BadFile() +else: + stdin = sys.stdin.buffer +if sys.stdout is None: + stdout = BadFile() else: - # Python 2 uses the I/O streams provided by the C library. - stdin = sys.stdin - stdout = sys.stdout - stderr = sys.stderr - if pycompat.iswindows: - # Work around Windows bugs. - stdout = platform.winstdout(stdout) # pytype: disable=module-attr - stderr = platform.winstdout(stderr) # pytype: disable=module-attr - if isatty(stdout): - if pycompat.iswindows: - # The Windows C runtime library doesn't support line buffering. - stdout = make_line_buffered(stdout) - else: - # glibc determines buffering on first write to stdout - if we - # replace a TTY destined stdout with a pipe destined stdout (e.g. - # pager), we want line buffering. - stdout = os.fdopen(stdout.fileno(), 'wb', 1) + stdout = _make_write_all(sys.stdout.buffer) +if sys.stderr is None: + stderr = BadFile() +else: + stderr = _make_write_all(sys.stderr.buffer) +if pycompat.iswindows: + # Work around Windows bugs. + stdout = platform.winstdout(stdout) # pytype: disable=module-attr + stderr = platform.winstdout(stderr) # pytype: disable=module-attr +if isatty(stdout): + # The standard library doesn't offer line-buffered binary streams. + stdout = make_line_buffered(stdout) findexe = platform.findexe _gethgcmd = platform.gethgcmd @@ -215,7 +193,7 @@ return _(b"killed by signal %d") % -code -class _pfile(object): +class _pfile: """File-like wrapper for a stream opened by subprocess.Popen()""" def __init__(self, proc, fp): @@ -364,7 +342,7 @@ def filter(s, cmd): """filter a string through a command that transforms its input to its output""" - for name, fn in pycompat.iteritems(_filtertable): + for name, fn in _filtertable.items(): if cmd.startswith(name): return fn(s, cmd[len(name) :].lstrip()) return pipefilter(s, cmd) @@ -470,7 +448,7 @@ env = dict(encoding.environ) if environ: - env.update((k, py2shell(v)) for k, v in pycompat.iteritems(environ)) + env.update((k, py2shell(v)) for k, v in environ.items()) env[b'HG'] = hgexecutable() return env @@ -705,7 +683,7 @@ else: - def runbgcommandpy3( + def runbgcommand( cmd, env, shell=False, @@ -788,128 +766,3 @@ returncode = p.wait if record_wait is not None: record_wait(returncode) - - def runbgcommandpy2( - cmd, - env, - shell=False, - stdout=None, - stderr=None, - ensurestart=True, - record_wait=None, - stdin_bytes=None, - ): - """Spawn a command without waiting for it to finish. - - - When `record_wait` is not None, the spawned process will not be fully - detached and the `record_wait` argument will be called with a the - `Subprocess.wait` function for the spawned process. This is mostly - useful for developers that need to make sure the spawned process - finished before a certain point. (eg: writing test)""" - if pycompat.isdarwin: - # avoid crash in CoreFoundation in case another thread - # calls gui() while we're calling fork(). - gui() - - # double-fork to completely detach from the parent process - # based on http://code.activestate.com/recipes/278731 - if record_wait is None: - pid = os.fork() - if pid: - if not ensurestart: - # Even though we're not waiting on the child process, - # we still must call waitpid() on it at some point so - # it's not a zombie/defunct. This is especially relevant for - # chg since the parent process won't die anytime soon. - # We use a thread to make the overhead tiny. - def _do_wait(): - os.waitpid(pid, 0) - - t = threading.Thread(target=_do_wait) - t.daemon = True - t.start() - return - # Parent process - (_pid, status) = os.waitpid(pid, 0) - if os.WIFEXITED(status): - returncode = os.WEXITSTATUS(status) - else: - returncode = -(os.WTERMSIG(status)) - if returncode != 0: - # The child process's return code is 0 on success, an errno - # value on failure, or 255 if we don't have a valid errno - # value. - # - # (It would be slightly nicer to return the full exception info - # over a pipe as the subprocess module does. For now it - # doesn't seem worth adding that complexity here, though.) - if returncode == 255: - returncode = errno.EINVAL - raise OSError( - returncode, - b'error running %r: %s' - % (cmd, os.strerror(returncode)), - ) - return - - returncode = 255 - stdin = None - - try: - if record_wait is None: - # Start a new session - os.setsid() - # connect stdin to devnull to make sure the subprocess can't - # muck up that stream for mercurial. - if stdin_bytes is None: - stdin = open(os.devnull, b'r') - else: - stdin = pycompat.unnamedtempfile() - stdin.write(stdin_bytes) - stdin.flush() - stdin.seek(0) - - if stdout is None: - stdout = open(os.devnull, b'w') - if stderr is None: - stderr = open(os.devnull, b'w') - - p = subprocess.Popen( - cmd, - shell=shell, - env=env, - close_fds=True, - stdin=stdin, - stdout=stdout, - stderr=stderr, - ) - if record_wait is not None: - record_wait(p.wait) - returncode = 0 - except EnvironmentError as ex: - returncode = ex.errno & 0xFF - if returncode == 0: - # This shouldn't happen, but just in case make sure the - # return code is never 0 here. - returncode = 255 - except Exception: - returncode = 255 - finally: - # mission accomplished, this child needs to exit and not - # continue the hg process here. - if stdin is not None: - stdin.close() - if record_wait is None: - os._exit(returncode) - - if pycompat.ispy3: - # This branch is more robust, because it avoids running python - # code (hence gc finalizers, like sshpeer.__del__, which - # blocks). But we can't easily do the equivalent in py2, - # because of the lack of start_new_session=True flag. Given - # that the py2 branch should die soon, the short-lived - # duplication seems acceptable. - runbgcommand = runbgcommandpy3 - else: - runbgcommand = runbgcommandpy2
--- a/mercurial/utils/repoviewutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/repoviewutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import ### Nearest subset relation # Nearest subset of filter X is a filter Y so that:
--- a/mercurial/utils/resourceutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/resourceutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import imp import os
--- a/mercurial/utils/storageutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/storageutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import re import struct
--- a/mercurial/utils/stringutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/stringutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import ast import codecs @@ -497,7 +496,7 @@ @attr.s(hash=True) -class mailmapping(object): +class mailmapping: """Represents a username/email key or value in a mailmap file""" @@ -965,6 +964,4 @@ def evalpythonliteral(s): """Evaluate a string containing a Python literal expression""" # We could backport our tokenizer hack to rewrite '' to u'' if we want - if pycompat.ispy3: - return ast.literal_eval(s.decode('latin1')) - return ast.literal_eval(s) + return ast.literal_eval(s.decode('latin1'))
--- a/mercurial/utils/urlutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/utils/urlutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -54,7 +54,7 @@ ) -class url(object): +class url: r"""Reliable URL parser. This parses URLs and provides attributes for the following @@ -453,7 +453,7 @@ """list all the (name, paths) in the passed ui""" result = [] if target_path is None: - for name, paths in sorted(pycompat.iteritems(ui.paths)): + for name, paths in sorted(ui.paths.items()): for p in paths: result.append((name, p)) @@ -832,7 +832,7 @@ return new_paths -class path(object): +class path: """Represents an individual path and its configuration.""" def __init__( @@ -919,7 +919,7 @@ # Now process the sub-options. If a sub-option is registered, its # attribute will always be present. The value will be None if there # was no valid sub-option. - for suboption, (attr, func) in pycompat.iteritems(_pathsuboptions): + for suboption, (attr, func) in _pathsuboptions.items(): if suboption not in sub_options: setattr(self, attr, None) continue @@ -945,7 +945,7 @@ This is intended to be used for presentation purposes. """ d = {} - for subopt, (attr, _func) in pycompat.iteritems(_pathsuboptions): + for subopt, (attr, _func) in _pathsuboptions.items(): value = getattr(self, attr) if value is not None: d[subopt] = value
--- a/mercurial/verify.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/verify.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import os @@ -55,7 +54,7 @@ ) -class verifier(object): +class verifier: def __init__(self, repo, level=None): self.repo = repo.unfiltered() self.ui = repo.ui @@ -406,11 +405,11 @@ _(b'checking'), unit=_(b'manifests'), total=len(subdirs) ) - for subdir, linkrevs in pycompat.iteritems(subdirnodes): + for subdir, linkrevs in subdirnodes.items(): subdirfilenodes = self._verifymanifest( linkrevs, subdir, storefiles, subdirprogress ) - for f, onefilenodes in pycompat.iteritems(subdirfilenodes): + for f, onefilenodes in subdirfilenodes.items(): filenodes.setdefault(f, {}).update(onefilenodes) if not dir and subdirnodes: @@ -575,7 +574,7 @@ # cross-check if f in filenodes: - fns = [(v, k) for k, v in pycompat.iteritems(filenodes[f])] + fns = [(v, k) for k, v in filenodes[f].items()] for lr, node in sorted(fns): msg = _(b"manifest refers to unknown revision %s") self._err(lr, msg % short(node), f)
--- a/mercurial/vfs.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/vfs.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import errno @@ -47,7 +46,7 @@ checkandavoid() -class abstractvfs(object): +class abstractvfs: """Abstract base class; cannot be instantiated""" # default directory separator for vfs @@ -607,7 +606,7 @@ return self.vfs.join(path, *insidef) -class closewrapbase(object): +class closewrapbase: """Base class of wrapper, which hooks closing Do not instantiate outside of the vfs layer. @@ -653,7 +652,7 @@ self._closer.close(self._origfh) -class backgroundfilecloser(object): +class backgroundfilecloser: """Coordinates background closing of file handles on multiple threads.""" def __init__(self, ui, expectedcount=-1):
--- a/mercurial/win32.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/win32.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import ctypes import ctypes.wintypes as wintypes
--- a/mercurial/windows.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/windows.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import getpass @@ -54,7 +53,7 @@ umask = 0o022 -class mixedfilemodewrapper(object): +class mixedfilemodewrapper: """Wraps a file handle when it is opened in read/write mode. fopen() and fdopen() on Windows have a specific-to-Windows requirement @@ -131,7 +130,7 @@ return self._fp.readlines(*args, **kwargs) -class fdproxy(object): +class fdproxy: """Wraps osutil.posixfile() to override the name attribute to reflect the underlying file name. """ @@ -163,8 +162,7 @@ # PyFile_FromFd() ignores the name, and seems to report fp.name as the # underlying file descriptor. - if pycompat.ispy3: - fp = fdproxy(name, fp) + fp = fdproxy(name, fp) # The position when opening in append mode is implementation defined, so # make it consistent with other platforms, which position at EOF. @@ -216,7 +214,7 @@ return encoding.unitolocal(pw) -class winstdout(object): +class winstdout: """Some files on Windows misbehave. When writing to a broken pipe, EINVAL instead of EPIPE may be raised. @@ -227,7 +225,6 @@ def __init__(self, fp): self.fp = fp - self.throttle = not pycompat.ispy3 and _isatty(fp) def __getattr__(self, key): return getattr(self.fp, key) @@ -240,17 +237,7 @@ def write(self, s): try: - if not self.throttle: - return self.fp.write(s) - # This is workaround for "Not enough space" error on - # writing large size of data to console. - limit = 16000 - l = len(s) - start = 0 - while start < l: - end = start + limit - self.fp.write(s[start:end]) - start = end + return self.fp.write(s) except IOError as inst: if inst.errno != 0 and not win32.lasterrorwaspipeerror(inst): raise @@ -671,7 +658,7 @@ return False -class cachestat(object): +class cachestat: def __init__(self, path): pass @@ -689,14 +676,21 @@ LOCAL_MACHINE). """ if scope is None: + # pytype: disable=module-attr scope = (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE) + # pytype: enable=module-attr elif not isinstance(scope, (list, tuple)): scope = (scope,) for s in scope: try: + # pytype: disable=module-attr with winreg.OpenKey(s, encoding.strfromlocal(key)) as hkey: + # pytype: enable=module-attr name = valname and encoding.strfromlocal(valname) or valname + # pytype: disable=module-attr val = winreg.QueryValueEx(hkey, name)[0] + # pytype: enable=module-attr + # never let a Unicode string escape into the wild return encoding.unitolocal(val) except EnvironmentError:
--- a/mercurial/wireprotoframing.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/wireprotoframing.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,7 +9,6 @@ # protocol. For details about the protocol, see # `hg help internals.wireprotocol`. -from __future__ import absolute_import import collections import struct @@ -123,7 +122,7 @@ def humanflags(mapping, value): """Convert a numeric flags value to a human value, using a mapping table.""" - namemap = {v: k for k, v in pycompat.iteritems(mapping)} + namemap = {v: k for k, v in mapping.items()} flags = [] val = 1 while value >= val: @@ -135,7 +134,7 @@ @attr.s(slots=True) -class frameheader(object): +class frameheader: """Represents the data in a frame header.""" length = attr.ib() @@ -147,7 +146,7 @@ @attr.s(slots=True, repr=False) -class frame(object): +class frame: """Represents a parsed frame.""" requestid = attr.ib() @@ -160,7 +159,7 @@ @encoding.strmethod def __repr__(self): typename = b'<unknown 0x%02x>' % self.typeid - for name, value in pycompat.iteritems(FRAME_TYPES): + for name, value in FRAME_TYPES.items(): if value == self.typeid: typename = name break @@ -590,7 +589,7 @@ ) -class bufferingcommandresponseemitter(object): +class bufferingcommandresponseemitter: """Helper object to emit command response frames intelligently. Raw command response data is likely emitted in chunks much smaller @@ -700,7 +699,7 @@ # mechanism. -class identityencoder(object): +class identityencoder: """Encoder for the "identity" stream encoding profile.""" def __init__(self, ui): @@ -716,7 +715,7 @@ return b'' -class identitydecoder(object): +class identitydecoder: """Decoder for the "identity" stream encoding profile.""" def __init__(self, ui, extraobjs): @@ -729,7 +728,7 @@ return data -class zlibencoder(object): +class zlibencoder: def __init__(self, ui): import zlib @@ -750,7 +749,7 @@ return res -class zlibdecoder(object): +class zlibdecoder: def __init__(self, ui, extraobjs): import zlib @@ -762,15 +761,10 @@ self._decompressor = zlib.decompressobj() def decode(self, data): - # Python 2's zlib module doesn't use the buffer protocol and can't - # handle all bytes-like types. - if not pycompat.ispy3 and isinstance(data, bytearray): - data = bytes(data) - return self._decompressor.decompress(data) -class zstdbaseencoder(object): +class zstdbaseencoder: def __init__(self, level): from . import zstd @@ -798,7 +792,7 @@ super(zstd8mbencoder, self).__init__(3) -class zstdbasedecoder(object): +class zstdbasedecoder: def __init__(self, maxwindowsize): from . import zstd @@ -848,7 +842,7 @@ STREAM_ENCODERS_ORDER.append(b'identity') -class stream(object): +class stream: """Represents a logical unidirectional series of frames.""" def __init__(self, streamid, active=False): @@ -1001,7 +995,7 @@ } -class serverreactor(object): +class serverreactor: """Holds state of a server handling frame-based protocol requests. This class is the "brain" of the unified frame-based protocol server @@ -1689,7 +1683,7 @@ return self._makeerrorresult(_(b'server already errored')) -class commandrequest(object): +class commandrequest: """Represents a request to run a command.""" def __init__(self, requestid, name, args, datafh=None, redirect=None): @@ -1701,7 +1695,7 @@ self.state = b'pending' -class clientreactor(object): +class clientreactor: """Holds state of a client issuing frame-based protocol requests. This is like ``serverreactor`` but for client-side state.
--- a/mercurial/wireprotoserver.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/wireprotoserver.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import contextlib import struct @@ -57,7 +56,7 @@ @interfaceutil.implementer(wireprototypes.baseprotocolhandler) -class httpv1protocolhandler(object): +class httpv1protocolhandler: def __init__(self, req, ui, checkperm): self._req = req self._ui = ui @@ -375,7 +374,7 @@ @interfaceutil.implementer(wireprototypes.baseprotocolhandler) -class sshv1protocolhandler(object): +class sshv1protocolhandler: """Handler for requests services via version 1 of SSH protocol.""" def __init__(self, ui, fin, fout): @@ -521,7 +520,7 @@ ) -class sshserver(object): +class sshserver: def __init__(self, ui, repo, logfh=None): self._ui = ui self._repo = repo
--- a/mercurial/wireprototypes.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/wireprototypes.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from .node import ( bin, @@ -40,14 +39,14 @@ } -class bytesresponse(object): +class bytesresponse: """A wire protocol response consisting of raw bytes.""" def __init__(self, data): self.data = data -class ooberror(object): +class ooberror: """wireproto reply: failure of a batch of operation Something failed during a batch call. The error message is stored in @@ -58,7 +57,7 @@ self.message = message -class pushres(object): +class pushres: """wireproto reply: success with simple integer return The call was successful and returned an integer contained in `self.res`. @@ -69,7 +68,7 @@ self.output = output -class pusherr(object): +class pusherr: """wireproto reply: failure The call failed. The `self.res` attribute contains the error message. @@ -80,7 +79,7 @@ self.output = output -class streamres(object): +class streamres: """wireproto reply: binary stream The call was successful and the result is a stream. @@ -97,7 +96,7 @@ self.prefer_uncompressed = prefer_uncompressed -class streamreslegacy(object): +class streamreslegacy: """wireproto reply: uncompressed binary stream The call was successful and the result is a stream. @@ -244,7 +243,7 @@ """ -class commandentry(object): +class commandentry: """Represents a declared wire protocol command.""" def __init__( @@ -407,7 +406,7 @@ @attr.s -class encodedresponse(object): +class encodedresponse: """Represents response data that is already content encoded. Wire protocol version 2 only. @@ -421,7 +420,7 @@ @attr.s -class alternatelocationresponse(object): +class alternatelocationresponse: """Represents a response available at an alternate location. Instances are sent in place of actual response objects when the server @@ -440,7 +439,7 @@ @attr.s -class indefinitebytestringresponse(object): +class indefinitebytestringresponse: """Represents an object to be encoded to an indefinite length bytestring. Instances are initialized from an iterable of chunks, with each chunk being
--- a/mercurial/wireprotov1peer.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/wireprotov1peer.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,11 +5,11 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import sys import weakref +from concurrent import futures from .i18n import _ from .node import bin from .pycompat import ( @@ -80,15 +80,14 @@ assert all(escapearg(k) == k for k in argsdict) args = b','.join( - b'%s=%s' % (escapearg(k), escapearg(v)) - for k, v in pycompat.iteritems(argsdict) + b'%s=%s' % (escapearg(k), escapearg(v)) for k, v in argsdict.items() ) cmds.append(b'%s %s' % (op, args)) return b';'.join(cmds) -class unsentfuture(pycompat.futures.Future): +class unsentfuture(futures.Future): """A Future variation to represent an unsent command. Because we buffer commands and don't submit them immediately, calling @@ -99,7 +98,7 @@ def result(self, timeout=None): if self.done(): - return pycompat.futures.Future.result(self, timeout) + return futures.Future.result(self, timeout) self._peerexecutor.sendcommands() @@ -110,7 +109,7 @@ @interfaceutil.implementer(repository.ipeercommandexecutor) -class peerexecutor(object): +class peerexecutor: def __init__(self, peer): self._peer = peer self._sent = False @@ -154,7 +153,7 @@ # a batchable one and refuse to service it. def addcall(): - f = pycompat.futures.Future() + f = futures.Future() self._futures.add(f) self._calls.append((command, args, fn, f)) return f @@ -194,7 +193,7 @@ # cycle between us and futures. for f in self._futures: if isinstance(f, unsentfuture): - f.__class__ = pycompat.futures.Future + f.__class__ = futures.Future f._peerexecutor = None calls = self._calls @@ -258,7 +257,7 @@ # hard and it is easy to encounter race conditions, deadlocks, etc. # concurrent.futures already solves these problems and its thread pool # executor has minimal overhead. So we use it. - self._responseexecutor = pycompat.futures.ThreadPoolExecutor(1) + self._responseexecutor = futures.ThreadPoolExecutor(1) self._responsef = self._responseexecutor.submit( self._readbatchresponse, states, wireresults ) @@ -438,7 +437,7 @@ self.requirecap(b'getbundle', _(b'look up remote changes')) opts = {} bundlecaps = kwargs.get(b'bundlecaps') or set() - for key, value in pycompat.iteritems(kwargs): + for key, value in kwargs.items(): if value is None: continue keytype = wireprototypes.GETBUNDLE_ARGUMENTS.get(key)
--- a/mercurial/wireprotov1server.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/wireprotov1server.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import binascii import os @@ -236,7 +235,7 @@ def branchmap(repo, proto): branchmap = repo.branchmap() heads = [] - for branch, nodes in pycompat.iteritems(branchmap): + for branch, nodes in branchmap.items(): branchname = urlreq.quote(encoding.fromlocal(branch)) branchnodes = wireprototypes.encodelist(nodes) heads.append(b'%s %s' % (branchname, branchnodes)) @@ -433,7 +432,7 @@ opts = options( b'getbundle', wireprototypes.GETBUNDLE_ARGUMENTS.keys(), others ) - for k, v in pycompat.iteritems(opts): + for k, v in opts.items(): keytype = wireprototypes.GETBUNDLE_ARGUMENTS[k] if keytype == b'nodes': opts[k] = wireprototypes.decodelist(v)
--- a/mercurial/worker.py Tue Apr 05 10:55:28 2022 +0200 +++ b/mercurial/worker.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,10 +5,10 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import errno import os +import pickle import signal import sys import threading @@ -27,7 +27,6 @@ error, pycompat, scmutil, - util, ) @@ -65,51 +64,39 @@ return min(max(countcpus(), 4), 32) -if pycompat.ispy3: - - def ismainthread(): - return threading.current_thread() == threading.main_thread() - - class _blockingreader(object): - def __init__(self, wrapped): - self._wrapped = wrapped - - # Do NOT implement readinto() by making it delegate to - # _wrapped.readinto(), since that is unbuffered. The unpickler is fine - # with just read() and readline(), so we don't need to implement it. - - def readline(self): - return self._wrapped.readline() - - # issue multiple reads until size is fulfilled - def read(self, size=-1): - if size < 0: - return self._wrapped.readall() - - buf = bytearray(size) - view = memoryview(buf) - pos = 0 - - while pos < size: - ret = self._wrapped.readinto(view[pos:]) - if not ret: - break - pos += ret - - del view - del buf[pos:] - return bytes(buf) +def ismainthread(): + return threading.current_thread() == threading.main_thread() -else: +class _blockingreader: + def __init__(self, wrapped): + self._wrapped = wrapped + + # Do NOT implement readinto() by making it delegate to + # _wrapped.readinto(), since that is unbuffered. The unpickler is fine + # with just read() and readline(), so we don't need to implement it. + + def readline(self): + return self._wrapped.readline() - def ismainthread(): - # pytype: disable=module-attr - return isinstance(threading.current_thread(), threading._MainThread) - # pytype: enable=module-attr + # issue multiple reads until size is fulfilled + def read(self, size=-1): + if size < 0: + return self._wrapped.readall() + + buf = bytearray(size) + view = memoryview(buf) + pos = 0 - def _blockingreader(wrapped): - return wrapped + while pos < size: + ret = self._wrapped.readinto(view[pos:]) + if not ret: + break + pos += ret + + del view + del buf[pos:] + return bytes(buf) if pycompat.isposix or pycompat.iswindows: @@ -256,7 +243,7 @@ os.close(w) os.close(rfd) for result in func(*(staticargs + (pargs,))): - os.write(wfd, util.pickle.dumps(result)) + os.write(wfd, pickle.dumps(result)) return 0 ret = scmutil.callcatch(ui, workerfunc) @@ -292,7 +279,11 @@ while openpipes > 0: for key, events in selector.select(): try: - res = util.pickle.load(_blockingreader(key.fileobj)) + # The pytype error likely goes away on a modern version of + # pytype having a modern typeshed snapshot. + # pytype: disable=wrong-arg-types + res = pickle.load(_blockingreader(key.fileobj)) + # pytype: enable=wrong-arg-types if hasretval and res[0]: retval.update(res[1]) else:
--- a/rust/Cargo.lock Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/Cargo.lock Tue Apr 05 11:09:03 2022 +0200 @@ -15,10 +15,16 @@ checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] +name = "ahash" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" + +[[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -31,9 +37,9 @@ [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ "winapi", ] @@ -57,9 +63,9 @@ [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitmaps" @@ -80,10 +86,19 @@ ] [[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + +[[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes-cast" @@ -141,9 +156,9 @@ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", @@ -161,6 +176,12 @@ checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" [[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] name = "cpufeatures" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -170,6 +191,15 @@ ] [[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] name = "cpython" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -178,7 +208,6 @@ "libc", "num-traits", "paste", - "python27-sys", "python3-sys", ] @@ -203,9 +232,9 @@ [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils 0.8.1", @@ -259,6 +288,15 @@ ] [[package]] +name = "crypto-common" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06" +dependencies = [ + "generic-array", +] + +[[package]] name = "ctor" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -270,20 +308,22 @@ [[package]] name = "derive_more" -version = "0.99.11" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ + "convert_case", "proc-macro2", "quote", + "rustc_version", "syn", ] [[package]] -name = "difference" -version = "2.0.0" +name = "diff" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" [[package]] name = "digest" @@ -295,6 +335,16 @@ ] [[package]] +name = "digest" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", +] + +[[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -302,9 +352,9 @@ [[package]] name = "env_logger" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime", @@ -314,10 +364,19 @@ ] [[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] name = "flate2" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if 1.0.0", "crc32fast", @@ -385,6 +444,16 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash", + "rayon", +] + +[[package]] name = "hermit-abi" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -411,23 +480,24 @@ "derive_more", "flate2", "format-bytes", + "hashbrown", "home", "im-rc", - "itertools", + "itertools 0.10.3", "lazy_static", "libc", "log", "memmap2", - "micro-timer", + "micro-timer 0.3.1", "ouroboros", "pretty_assertions", - "rand 0.8.4", + "rand 0.8.5", "rand_distr", "rand_pcg", "rayon", "regex", "same-file", - "sha-1", + "sha-1 0.10.0", "tempfile", "twox-hash", "zstd", @@ -438,7 +508,7 @@ version = "0.1.0" dependencies = [ "cpython", - "crossbeam-channel 0.4.4", + "crossbeam-channel 0.5.2", "env_logger", "hg-core", "libc", @@ -458,12 +528,9 @@ [[package]] name = "humantime" -version = "1.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "im-rc" @@ -480,6 +547,15 @@ ] [[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] name = "itertools" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -489,6 +565,15 @@ ] [[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] name = "jobserver" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -505,9 +590,9 @@ [[package]] name = "libc" -version = "0.2.81" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "libm" @@ -528,11 +613,11 @@ [[package]] name = "log" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -543,9 +628,9 @@ [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" @@ -572,7 +657,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2620153e1d903d26b72b89f0e9c48d8c4756cba941c185461dddc234980c298c" dependencies = [ - "micro-timer-macros", + "micro-timer-macros 0.3.1", + "scopeguard", +] + +[[package]] +name = "micro-timer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de32cb59a062672560d6f0842c4aa7714727457b9fe2daf8987d995a176a405" +dependencies = [ + "micro-timer-macros 0.4.0", "scopeguard", ] @@ -589,6 +684,18 @@ ] [[package]] +name = "micro-timer-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee948b94700125b52dfb68dd17c19f6326696c1df57f92c05ee857463c93ba1" +dependencies = [ + "proc-macro2", + "quote", + "scopeguard", + "syn", +] + +[[package]] name = "miniz_oxide" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -687,13 +794,13 @@ [[package]] name = "pretty_assertions" -version = "0.6.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" +checksum = "76d5b548b725018ab5496482b45cb8bef21e9fed1858a6d674e3a8a0f0bb5d50" dependencies = [ "ansi_term", "ctor", - "difference", + "diff", "output_vt100", ] @@ -731,16 +838,6 @@ ] [[package]] -name = "python27-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94670354e264300dde81a5864cbb6bfc9d56ac3dcf3a278c32cb52f816f4dfd1" -dependencies = [ - "libc", - "regex", -] - -[[package]] name = "python3-sys" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -751,12 +848,6 @@ ] [[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -775,19 +866,18 @@ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -830,12 +920,12 @@ [[package]] name = "rand_distr" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964d548f8e7d12e102ef183a0de7e98180c9f8729f555897a857b96e48122d2f" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -848,15 +938,6 @@ ] [[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - -[[package]] name = "rand_pcg" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -876,9 +957,9 @@ [[package]] name = "rayon" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ "autocfg", "crossbeam-deque", @@ -888,11 +969,11 @@ [[package]] name = "rayon-core" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ - "crossbeam-channel 0.5.0", + "crossbeam-channel 0.5.2", "crossbeam-deque", "crossbeam-utils 0.8.1", "lazy_static", @@ -901,27 +982,29 @@ [[package]] name = "redox_syscall" -version = "0.1.57" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" +dependencies = [ + "bitflags", +] [[package]] name = "regex" -version = "1.4.2" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.21" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "remove_dir_all" @@ -946,12 +1029,21 @@ "home", "lazy_static", "log", - "micro-timer", + "micro-timer 0.4.0", "regex", "users", ] [[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -967,19 +1059,36 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] +name = "semver" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" + +[[package]] name = "sha-1" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", - "cpufeatures", - "digest", + "cpufeatures 0.1.4", + "digest 0.9.0", "opaque-debug", ] [[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures 0.2.1", + "digest 0.10.2", +] + +[[package]] name = "sized-chunks" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1020,13 +1129,13 @@ [[package]] name = "tempfile" -version = "3.1.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.7.3", "redox_syscall", "remove_dir_all", "winapi", @@ -1051,15 +1160,6 @@ ] [[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - -[[package]] name = "time" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1072,12 +1172,12 @@ [[package]] name = "twox-hash" -version = "1.6.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" +checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ - "cfg-if 0.1.10", - "rand 0.7.3", + "cfg-if 1.0.0", + "rand 0.8.5", "static_assertions", ] @@ -1089,9 +1189,9 @@ [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" @@ -1123,7 +1223,7 @@ dependencies = [ "hex", "rand 0.7.3", - "sha-1", + "sha-1 0.9.6", ] [[package]] @@ -1183,18 +1283,18 @@ [[package]] name = "zstd" -version = "0.5.3+zstd.1.4.5" +version = "0.5.4+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8" +checksum = "69996ebdb1ba8b1517f61387a883857818a66c8a295f487b1ffd8fd9d2c82910" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "2.0.5+zstd.1.4.5" +version = "2.0.6+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055" +checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e" dependencies = [ "libc", "zstd-sys", @@ -1202,12 +1302,12 @@ [[package]] name = "zstd-sys" -version = "1.4.17+zstd.1.4.5" +version = "1.4.18+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b" +checksum = "a1e6e8778706838f43f771d80d37787cb2fe06dafe89dd3aebaf6721b9eaec81" dependencies = [ "cc", "glob", - "itertools", + "itertools 0.9.0", "libc", ]
--- a/rust/README.rst Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/README.rst Tue Apr 05 11:09:03 2022 +0200 @@ -40,8 +40,8 @@ Special features ================ -You might want to check the `features` section in ``hg-cpython/Cargo.toml``. -It may contain features that might be interesting to try out. +In the future, compile-time opt-ins may be added +to the `features` section in ``hg-cpython/Cargo.toml``. To use features from the Makefile, use the `HG_RUST_FEATURES` environment variable: for instance `HG_RUST_FEATURES="some-feature other-feature"`
--- a/rust/hg-core/Cargo.toml Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-core/Cargo.toml Tue Apr 05 11:09:03 2022 +0200 @@ -9,23 +9,24 @@ name = "hg" [dependencies] -bitflags = "1.2" -bytes-cast = "0.2" -byteorder = "1.3.4" -derive_more = "0.99" -home = "0.5" -im-rc = "15.0.*" -itertools = "0.9" +bitflags = "1.3.2" +bytes-cast = "0.2.0" +byteorder = "1.4.3" +derive_more = "0.99.17" +hashbrown = { version = "0.9.1", features = ["rayon"] } +home = "0.5.3" +im-rc = "15.0.0" +itertools = "0.10.3" lazy_static = "1.4.0" libc = "0.2" ouroboros = "0.15.0" rand = "0.8.4" rand_pcg = "0.3.1" -rand_distr = "0.4.2" -rayon = "1.3.0" -regex = "1.3.9" -sha-1 = "0.9.6" -twox-hash = "1.5.0" +rand_distr = "0.4.3" +rayon = "1.5.1" +regex = "1.5.5" +sha-1 = "0.10.0" +twox-hash = "1.6.2" same-file = "1.0.6" tempfile = "3.1.0" crossbeam-channel = "0.4" @@ -38,10 +39,10 @@ # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until # we have a clearer view of which backend is the fastest. [dependencies.flate2] -version = "1.0.16" +version = "1.0.22" features = ["zlib"] default-features = false [dev-dependencies] -clap = "*" -pretty_assertions = "0.6.1" +clap = "2.34.0" +pretty_assertions = "1.1.0"
--- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs Tue Apr 05 11:09:03 2022 +0200 @@ -22,7 +22,7 @@ use crate::DirstateParents; use crate::DirstateStatus; use crate::EntryState; -use crate::FastHashMap; +use crate::FastHashbrownMap as FastHashMap; use crate::PatternFileWarning; use crate::StatusError; use crate::StatusOptions; @@ -585,13 +585,11 @@ .next() .expect("expected at least one inclusive ancestor"); loop { - // TODO: can we avoid allocating an owned key in cases where the - // map already contains that key, without introducing double - // lookup? - let child_node = child_nodes + let (_, child_node) = child_nodes .make_mut(on_disk, unreachable_bytes)? - .entry(to_cow(ancestor_path)) - .or_default(); + .raw_entry_mut() + .from_key(ancestor_path.base_name()) + .or_insert_with(|| (to_cow(ancestor_path), Node::default())); if let Some(next) = inclusive_ancestor_paths.next() { each_ancestor(child_node); ancestor_path = next;
--- a/rust/hg-core/src/lib.rs Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-core/src/lib.rs Tue Apr 05 11:09:03 2022 +0200 @@ -56,6 +56,11 @@ /// write access to your repository, you have other issues. pub type FastHashMap<K, V> = HashMap<K, V, RandomXxHashBuilder64>; +// TODO: should this be the default `FastHashMap` for all of hg-core, not just +// dirstate_tree? How does XxHash compare with AHash, hashbrown’s default? +pub type FastHashbrownMap<K, V> = + hashbrown::HashMap<K, V, RandomXxHashBuilder64>; + #[derive(Debug, PartialEq)] pub enum DirstateMapError { PathNotFound(HgPathBuf),
--- a/rust/hg-core/src/repo.rs Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-core/src/repo.rs Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ use crate::dirstate_tree::owning::OwningDirstateMap; use crate::errors::HgResultExt; use crate::errors::{HgError, IoResultExt}; -use crate::exit_codes; use crate::lock::{try_with_lock_no_wait, LockError}; use crate::manifest::{Manifest, Manifestlog}; use crate::revlog::filelog::Filelog; @@ -159,31 +158,8 @@ requirements::load(Vfs { base: &shared_path })? .contains(requirements::SHARESAFE_REQUIREMENT); - if share_safe && !source_is_share_safe { - return Err(match config - .get(b"share", b"safe-mismatch.source-not-safe") - { - Some(b"abort") | None => HgError::abort( - "abort: share source does not support share-safe requirement\n\ - (see `hg help config.format.use-share-safe` for more information)", - exit_codes::ABORT, - ), - _ => HgError::unsupported("share-safe downgrade"), - } - .into()); - } else if source_is_share_safe && !share_safe { - return Err( - match config.get(b"share", b"safe-mismatch.source-safe") { - Some(b"abort") | None => HgError::abort( - "abort: version mismatch: source uses share-safe \ - functionality while the current share does not\n\ - (see `hg help config.format.use-share-safe` for more information)", - exit_codes::ABORT, - ), - _ => HgError::unsupported("share-safe upgrade"), - } - .into(), - ); + if share_safe != source_is_share_safe { + return Err(HgError::unsupported("share-safe mismatch").into()); } if share_safe {
--- a/rust/hg-cpython/Cargo.toml Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-cpython/Cargo.toml Tue Apr 05 11:09:03 2022 +0200 @@ -8,25 +8,12 @@ name='rusthg' crate-type = ["cdylib"] -[features] -default = ["python3"] - -# Features to build an extension module: -python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"] -python3 = ["cpython/python3-sys", "cpython/extension-module"] - -# Enable one of these features to build a test executable linked to libpython: -# e.g. cargo test --no-default-features --features python27-bin -python27-bin = ["cpython/python27-sys"] -python3-bin = ["cpython/python3-sys"] - [dependencies] -cpython = { version = "0.7.0", default-features = false } -crossbeam-channel = "0.4" +cpython = { version = "0.7.0", features = ["extension-module"] } +crossbeam-channel = "0.5.2" hg-core = { path = "../hg-core"} -libc = "0.2" -log = "0.4.8" -env_logger = "0.7.1" +libc = "0.2.119" +log = "0.4.14" +env_logger = "0.9.0" stable_deref_trait = "1.2.0" vcsgraph = "0.2.0" -
--- a/rust/hg-cpython/src/cindex.rs Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-cpython/src/cindex.rs Tue Apr 05 11:09:03 2022 +0200 @@ -18,7 +18,7 @@ use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::{c_int, ssize_t}; -const REVLOG_CABI_VERSION: c_int = 2; +const REVLOG_CABI_VERSION: c_int = 3; #[repr(C)] pub struct Revlog_CAPI { @@ -29,6 +29,10 @@ index: *mut revlog_capi::RawPyObject, rev: ssize_t, ) -> *const Node, + fast_rank: unsafe extern "C" fn( + index: *mut revlog_capi::RawPyObject, + rev: ssize_t, + ) -> ssize_t, index_parents: unsafe extern "C" fn( index: *mut revlog_capi::RawPyObject, rev: c_int, @@ -173,6 +177,20 @@ } } +impl vcsgraph::graph::RankedGraph for Index { + fn rank( + &self, + rev: Revision, + ) -> Result<vcsgraph::graph::Rank, vcsgraph::graph::GraphReadError> { + match unsafe { + (self.capi.fast_rank)(self.index.as_ptr(), rev as ssize_t) + } { + -1 => Err(vcsgraph::graph::GraphReadError::InconsistentGraphData), + rank => Ok(rank as usize), + } + } +} + impl RevlogIndex for Index { /// Note C return type is Py_ssize_t (hence signed), but we shall /// force it to unsigned, because it's a length
--- a/rust/hg-cpython/src/dagops.rs Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-cpython/src/dagops.rs Tue Apr 05 11:09:03 2022 +0200 @@ -14,6 +14,8 @@ use hg::dagops; use hg::Revision; use std::collections::HashSet; +use vcsgraph::ancestors::node_rank; +use vcsgraph::graph::{Parents, Rank}; use crate::revlog::pyindex_to_graph; @@ -31,6 +33,18 @@ Ok(as_set) } +/// Computes the rank, i.e. the number of ancestors including itself, +/// of a node represented by its parents. +pub fn rank( + py: Python, + index: PyObject, + p1r: Revision, + p2r: Revision, +) -> PyResult<Rank> { + node_rank(&pyindex_to_graph(py, index)?, &Parents([p1r, p2r])) + .map_err(|e| GraphError::pynew_from_vcsgraph(py, e)) +} + /// Create the module, with `__package__` given from parent pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> { let dotted_name = &format!("{}.dagop", package); @@ -42,6 +56,11 @@ "headrevs", py_fn!(py, headrevs(index: PyObject, revs: PyObject)), )?; + m.add( + py, + "rank", + py_fn!(py, rank(index: PyObject, p1r: Revision, p2r: Revision)), + )?; let sys = PyModule::import(py, "sys")?; let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
--- a/rust/hg-cpython/src/lib.rs Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/hg-cpython/src/lib.rs Tue Apr 05 11:09:03 2022 +0200 @@ -62,7 +62,7 @@ Ok(()) }); -#[cfg(not(any(feature = "python27-bin", feature = "python3-bin")))] +#[cfg(not(feature = "python3-bin"))] #[test] #[ignore] fn libpython_must_be_linked_to_run_tests() {
--- a/rust/rhg/Cargo.toml Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/rhg/Cargo.toml Tue Apr 05 11:09:03 2022 +0200 @@ -8,16 +8,16 @@ edition = "2018" [dependencies] -atty = "0.2" +atty = "0.2.14" hg-core = { path = "../hg-core"} chrono = "0.4.19" -clap = "2.33.1" -derive_more = "0.99" +clap = "2.34.0" +derive_more = "0.99.17" home = "0.5.3" lazy_static = "1.4.0" -log = "0.4.11" -micro-timer = "0.3.1" -regex = "1.3.9" -env_logger = "0.7.1" +log = "0.4.14" +micro-timer = "0.4.0" +regex = "1.5.5" +env_logger = "0.9.0" format-bytes = "0.3.0" users = "0.11.0"
--- a/rust/rhg/src/main.rs Tue Apr 05 10:55:28 2022 +0200 +++ b/rust/rhg/src/main.rs Tue Apr 05 11:09:03 2022 +0200 @@ -643,6 +643,11 @@ &[b"blackbox", b"share", b"sparse", b"narrow", b"*"]; fn check_extensions(config: &Config) -> Result<(), CommandError> { + if let Some(b"*") = config.get(b"rhg", b"ignored-extensions") { + // All extensions are to be ignored, nothing to do here + return Ok(()); + } + let enabled: HashSet<&[u8]> = config .get_section_keys(b"extensions") .into_iter() @@ -669,6 +674,9 @@ if unsupported.is_empty() { Ok(()) } else { + let mut unsupported: Vec<_> = unsupported.into_iter().collect(); + // Sort the extensions to get a stable output + unsupported.sort(); Err(CommandError::UnsupportedFeature { message: format_bytes!( b"extensions: {} (consider adding them to 'rhg.ignored-extensions' config)",
--- a/setup.py Tue Apr 05 10:55:28 2022 +0200 +++ b/setup.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,99 +5,24 @@ # 'python setup.py --help' for more options import os -# Mercurial will never work on Python 3 before 3.5 due to a lack -# of % formatting on bytestrings, and can't work on 3.6.0 or 3.6.1 -# due to a bug in % formatting in bytestrings. -# We cannot support Python 3.5.0, 3.5.1, 3.5.2 because of bug in -# codecs.escape_encode() where it raises SystemError on empty bytestring -# bug link: https://bugs.python.org/issue25270 +# Mercurial can't work on 3.6.0 or 3.6.1 due to a bug in % formatting +# in bytestrings. supportedpy = ','.join( [ - '>=2.7.4', - '!=3.0.*', - '!=3.1.*', - '!=3.2.*', - '!=3.3.*', - '!=3.4.*', - '!=3.5.0', - '!=3.5.1', - '!=3.5.2', - '!=3.6.0', - '!=3.6.1', + '>=3.6.2', ] ) import sys, platform import sysconfig -if sys.version_info[0] >= 3: - printf = eval('print') - libdir_escape = 'unicode_escape' - def sysstr(s): - return s.decode('latin-1') - - -else: - libdir_escape = 'string_escape' - - def printf(*args, **kwargs): - f = kwargs.get('file', sys.stdout) - end = kwargs.get('end', '\n') - f.write(b' '.join(args) + end) - - def sysstr(s): - return s +def sysstr(s): + return s.decode('latin-1') -# Attempt to guide users to a modern pip - this means that 2.6 users -# should have a chance of getting a 4.2 release, and when we ratchet -# the version requirement forward again hopefully everyone will get -# something that works for them. -if sys.version_info < (2, 7, 4, 'final'): - pip_message = ( - 'This may be due to an out of date pip. ' - 'Make sure you have pip >= 9.0.1.' - ) - try: - import pip - - pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]]) - if pip_version < (9, 0, 1): - pip_message = ( - 'Your pip version is out of date, please install ' - 'pip >= 9.0.1. pip {} detected.'.format(pip.__version__) - ) - else: - # pip is new enough - it must be something else - pip_message = '' - except Exception: - pass - error = """ -Mercurial does not support Python older than 2.7.4. -Python {py} detected. -{pip} -""".format( - py=sys.version_info, pip=pip_message - ) - printf(error, file=sys.stderr) - sys.exit(1) - import ssl -try: - ssl.SSLContext -except AttributeError: - error = """ -The `ssl` module does not have the `SSLContext` class. This indicates an old -Python version which does not support modern security features (which were -added to Python 2.7 as part of "PEP 466"). Please make sure you have installed -at least Python 2.7.9 or a Python version with backports of these security -features. -""" - printf(error, file=sys.stderr) - sys.exit(1) - # ssl.HAS_TLSv1* are preferred to check support but they were added in Python # 3.7. Prior to CPython commit 6e8cda91d92da72800d891b2fc2073ecbc134d98 # (backported to the 3.7 branch), ssl.PROTOCOL_TLSv1_1 / ssl.PROTOCOL_TLSv1_2 @@ -117,14 +42,10 @@ version enabling these features (likely this requires the OpenSSL version to be at least 1.0.1). """ - printf(error, file=sys.stderr) + print(error, file=sys.stderr) sys.exit(1) -if sys.version_info[0] >= 3: - DYLIB_SUFFIX = sysconfig.get_config_vars()['EXT_SUFFIX'] -else: - # deprecated in Python 3 - DYLIB_SUFFIX = sysconfig.get_config_vars()['SO'] +DYLIB_SUFFIX = sysconfig.get_config_vars()['EXT_SUFFIX'] # Solaris Python packaging brain damage try: @@ -292,7 +213,7 @@ return p.returncode, out, err -class hgcommand(object): +class hgcommand: def __init__(self, cmd, env): self.cmd = cmd self.env = env @@ -302,8 +223,8 @@ returncode, out, err = runcmd(cmd, self.env) err = filterhgerr(err) if err or returncode != 0: - printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) - printf(err, file=sys.stderr) + print("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) + print(err, file=sys.stderr) return b'' return out @@ -536,7 +457,7 @@ if hgrustext != 'cpython' and hgrustext is not None: if hgrustext: msg = 'unknown HGWITHRUSTEXT value: %s' % hgrustext - printf(msg, file=sys.stderr) + print(msg, file=sys.stderr) hgrustext = None self.rust = hgrustext is not None self.no_rust = not self.rust @@ -810,12 +731,9 @@ # Copy the pythonXY.dll next to the binary so that it runs # without tampering with PATH. - fsdecode = lambda x: x - if sys.version_info[0] >= 3: - fsdecode = os.fsdecode dest = os.path.join( os.path.dirname(self.hgtarget), - fsdecode(dllbasename), + os.fsdecode(dllbasename), ) if not os.path.exists(dest): @@ -823,19 +741,18 @@ # Also overwrite python3.dll so that hgext.git is usable. # TODO: also handle the MSYS flavor - if sys.version_info[0] >= 3: - python_x = os.path.join( - os.path.dirname(fsdecode(buf.value)), - "python3.dll", + python_x = os.path.join( + os.path.dirname(os.fsdecode(buf.value)), + "python3.dll", + ) + + if os.path.exists(python_x): + dest = os.path.join( + os.path.dirname(self.hgtarget), + os.path.basename(python_x), ) - if os.path.exists(python_x): - dest = os.path.join( - os.path.dirname(self.hgtarget), - os.path.basename(python_x), - ) - - shutil.copy(python_x, dest) + shutil.copy(python_x, dest) if not pythonlib: log.warn( @@ -850,14 +767,10 @@ f.write(b'/* this file is autogenerated by setup.py */\n') f.write(b'#define HGPYTHONLIB "%s"\n' % pythonlib) - macros = None - if sys.version_info[0] >= 3: - macros = [('_UNICODE', None), ('UNICODE', None)] - objects = self.compiler.compile( ['mercurial/exewrapper.c'], output_dir=self.build_temp, - macros=macros, + macros=[('_UNICODE', None), ('UNICODE', None)], ) self.compiler.link_executable( objects, self.hgtarget, libraries=[], output_dir=self.build_temp @@ -1069,6 +982,10 @@ ), ] + sub_commands = install.sub_commands + [ + ('install_completion', lambda self: True) + ] + # Also helps setuptools not be sad while we refuse to create eggs. single_version_externally_managed = True @@ -1183,11 +1100,38 @@ ) continue - data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape)) + data = data.replace(b'@LIBDIR@', libdir.encode('unicode_escape')) with open(outfile, 'wb') as fp: fp.write(data) +class hginstallcompletion(Command): + description = 'Install shell completion' + + def initialize_options(self): + self.install_dir = None + + def finalize_options(self): + self.set_undefined_options( + 'install_data', ('install_dir', 'install_dir') + ) + + def run(self): + for src, dir_path, dest in ( + ( + 'bash_completion', + ('share', 'bash-completion', 'completions'), + 'hg', + ), + ('zsh_completion', ('share', 'zsh', 'site-functions'), '_hg'), + ): + dir = os.path.join(self.install_dir, *dir_path) + self.mkpath(dir) + self.copy_file( + os.path.join('contrib', src), os.path.join(dir, dest) + ) + + # virtualenv installs custom distutils/__init__.py and # distutils/distutils.cfg files which essentially proxy back to the # "real" distutils in the main Python install. The presence of this @@ -1278,6 +1222,7 @@ 'build_scripts': hgbuildscripts, 'build_hgextindex': buildhgextindex, 'install': hginstall, + 'install_completion': hginstallcompletion, 'install_lib': hginstalllib, 'install_scripts': hginstallscripts, 'build_hgexe': buildhgexe, @@ -1324,27 +1269,12 @@ 'hgdemandimport', ] -# The pygit2 dependency dropped py2 support with the 1.0 release in Dec 2019. -# Prior releases do not build at all on Windows, because Visual Studio 2008 -# doesn't understand C 11. Older Linux releases are buggy. -if sys.version_info[0] == 2: - packages.remove('hgext.git') - - for name in os.listdir(os.path.join('mercurial', 'templates')): if name != '__pycache__' and os.path.isdir( os.path.join('mercurial', 'templates', name) ): packages.append('mercurial.templates.%s' % name) -if sys.version_info[0] == 2: - packages.extend( - [ - 'mercurial.thirdparty.concurrent', - 'mercurial.thirdparty.concurrent.futures', - ] - ) - if 'HG_PY2EXE_EXTRA_INSTALL_PACKAGES' in os.environ: # py2exe can't cope with namespace packages very well, so we have to # install any hgext3rd.* extensions that we want in the final py2exe @@ -1476,19 +1406,9 @@ cargocmd = ['cargo', 'rustc', '--release'] - feature_flags = [] - - cargocmd.append('--no-default-features') - if sys.version_info[0] == 2: - feature_flags.append('python27') - elif sys.version_info[0] == 3: - feature_flags.append('python3') - rust_features = env.get("HG_RUST_FEATURES") if rust_features: - feature_flags.append(rust_features) - - cargocmd.extend(('--features', " ".join(feature_flags))) + cargocmd.extend(('--features', rust_features)) cargocmd.append('--') if sys.platform == 'darwin': @@ -1640,7 +1560,7 @@ # the cygwinccompiler package is not available on some Python # distributions like the ones from the optware project for Synology # DiskStation boxes - class HackedMingw32CCompiler(object): + class HackedMingw32CCompiler: pass @@ -1763,9 +1683,7 @@ if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'): version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[1].splitlines() if version: - version = version[0] - if sys.version_info[0] == 3: - version = version.decode('utf-8') + version = version[0].decode('utf-8') xcode4 = version.startswith('Xcode') and StrictVersion( version.split()[1] ) >= StrictVersion('4.0')
--- a/tests/artifacts/scripts/generate-churning-bundle.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/artifacts/scripts/generate-churning-bundle.py Tue Apr 05 11:09:03 2022 +0200 @@ -17,7 +17,6 @@ # # Running with `chg` in your path and `CHGHG` set is recommended for speed. -from __future__ import absolute_import, print_function import hashlib import os
--- a/tests/autodiff.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/autodiff.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # Extension dedicated to test patch.diff() upgrade modes -from __future__ import absolute_import from mercurial import ( error,
--- a/tests/basic_test_result.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/basic_test_result.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import sys import unittest
--- a/tests/blackbox-readonly-dispatch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/blackbox-readonly-dispatch.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import os from mercurial import ( dispatch,
--- a/tests/bruterebase.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/bruterebase.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial import ( error,
--- a/tests/check-perf-code.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/check-perf-code.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # # check-perf-code - (historical) portability checker for contrib/perf.py -from __future__ import absolute_import import os import sys
--- a/tests/common-pattern.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/common-pattern.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ # common patterns in test at can safely be replaced -from __future__ import absolute_import import os
--- a/tests/crashgetbundler.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/crashgetbundler.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from mercurial.i18n import _ from mercurial import changegroup, error, extensions
--- a/tests/drawdag.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/drawdag.py Tue Apr 05 11:09:03 2022 +0200 @@ -80,7 +80,6 @@ # split: A -> B, C # 1 to many # prune: A, B, C # many to nothing """ -from __future__ import absolute_import, print_function import collections import itertools @@ -266,7 +265,7 @@ return dict(edges) -class simplefilectx(object): +class simplefilectx: def __init__(self, path, data): self._data = data self._path = path
--- a/tests/dumbhttp.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/dumbhttp.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import """ Small and dumb HTTP server for use in tests. @@ -38,7 +37,7 @@ sys.stderr.flush() -class simplehttpservice(object): +class simplehttpservice: def __init__(self, host, port): self.address = (host, port)
--- a/tests/dummysmtpd.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/dummysmtpd.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ """dummy SMTP server for use in tests""" -from __future__ import absolute_import import asyncore import optparse
--- a/tests/dummyssh Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/dummyssh Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -from __future__ import absolute_import import os import shlex
--- a/tests/f Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/f Tue Apr 05 11:09:03 2022 +0200 @@ -23,7 +23,6 @@ md5sum.py """ -from __future__ import absolute_import import binascii import glob
--- a/tests/failfilemerge.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/failfilemerge.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # extension to emulate interrupting filemerge._filemerge -from __future__ import absolute_import from mercurial import ( error,
--- a/tests/fakedirstatewritetime.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/fakedirstatewritetime.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # - 'workingctx._poststatusfixup()' (= 'repo.status()') # - 'committablectx.markcommitted()' -from __future__ import absolute_import from mercurial import ( context,
--- a/tests/fakemergerecord.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/fakemergerecord.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # # -from __future__ import absolute_import from mercurial import ( mergestate as mergestatemod,
--- a/tests/fakepatchtime.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/fakepatchtime.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ # extension to emulate invoking 'patch.internalpatch()' at the time # specified by '[fakepatchtime] fakenow' -from __future__ import absolute_import from mercurial import ( extensions,
--- a/tests/filterpyflakes.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/filterpyflakes.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # Filter output by pyflakes to control which warnings we check -from __future__ import absolute_import, print_function import re import sys
--- a/tests/filtertraceback.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/filtertraceback.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # Filters traceback lines from stdin. -from __future__ import absolute_import, print_function import io import sys
--- a/tests/flagprocessorext.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/flagprocessorext.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # coding=UTF-8 -from __future__ import absolute_import import base64 import zlib
--- a/tests/fsmonitor-run-tests.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/fsmonitor-run-tests.py Tue Apr 05 11:09:03 2022 +0200 @@ -11,8 +11,6 @@ # Watchman and runs the Mercurial tests against it. This ensures that the global # version of Watchman isn't affected by anything this test does. -from __future__ import absolute_import -from __future__ import print_function import argparse import contextlib
--- a/tests/generate-working-copy-states.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/generate-working-copy-states.py Tue Apr 05 11:09:03 2022 +0200 @@ -29,7 +29,6 @@ # $ hg forget *_*_*-untracked # $ rm *_*_missing-* -from __future__ import absolute_import, print_function import os import sys
--- a/tests/get-with-headers.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/get-with-headers.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ """This does HTTP GET requests given a host:port and path and returns a subset of the headers plus the body of the result.""" -from __future__ import absolute_import import argparse import json
--- a/tests/heredoctest.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/heredoctest.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import sys
--- a/tests/hghave Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/hghave Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ prefixed with "no-", the absence of feature is tested. """ -from __future__ import absolute_import, print_function import hghave import optparse
--- a/tests/hghave.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/hghave.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import distutils.version import os import re
--- a/tests/hgweberror.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/hgweberror.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # A dummy extension that installs an hgweb command that throws an Exception. -from __future__ import absolute_import from mercurial.hgweb import webcommands
--- a/tests/httpserverauth.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/httpserverauth.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import base64 import hashlib @@ -18,7 +16,7 @@ return parsed -class digestauthserver(object): +class digestauthserver: def __init__(self): self._user_hashes = {}
--- a/tests/hypothesishelpers.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/hypothesishelpers.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ # # For details see http://hypothesis.readthedocs.org -from __future__ import absolute_import, print_function import os import sys import traceback
--- a/tests/killdaemons.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/killdaemons.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -from __future__ import absolute_import import errno import os import signal
--- a/tests/list-tree.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/list-tree.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,8 +1,3 @@ -from __future__ import ( - absolute_import, - print_function, -) - import argparse import os
--- a/tests/lockdelay.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/lockdelay.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # # This extension can be used to test race conditions between lock acquisition. -from __future__ import absolute_import import os import time
--- a/tests/logexceptions.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/logexceptions.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import inspect import os
--- a/tests/ls-l.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/ls-l.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # like ls -l, but do not print date, user, or non-common mode bit, to avoid # using globs in tests. -from __future__ import absolute_import, print_function import os import stat
--- a/tests/md5sum.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/md5sum.py Tue Apr 05 11:09:03 2022 +0200 @@ -6,7 +6,6 @@ # of the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2, which is # GPL-compatible. -from __future__ import absolute_import import hashlib import os
--- a/tests/mockblackbox.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/mockblackbox.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import from mercurial.utils import procutil # XXX: we should probably offer a devel option to do this in blackbox directly
--- a/tests/mockmakedate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/mockmakedate.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # mock out util.makedate() to supply testable values -from __future__ import absolute_import import os
--- a/tests/mocktime.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/mocktime.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,10 +1,8 @@ -from __future__ import absolute_import - import os import time -class mocktime(object): +class mocktime: def __init__(self, increment): self.time = 0 self.increment = [float(s) for s in increment.split()]
--- a/tests/printenv.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/printenv.py Tue Apr 05 11:09:03 2022 +0200 @@ -12,7 +12,6 @@ # - [output] is the name of the output file (default: use sys.stdout) # the file will be opened in append mode. # -from __future__ import absolute_import import argparse import os import sys
--- a/tests/printrevset.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/printrevset.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import from mercurial.thirdparty import attr from mercurial import ( cmdutil,
--- a/tests/pullext.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/pullext.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.i18n import _ from mercurial import (
--- a/tests/readlink.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/readlink.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -from __future__ import absolute_import, print_function import errno import os
--- a/tests/remotefilelog-getflogheads.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/remotefilelog-getflogheads.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from mercurial.i18n import _ from mercurial import ( hg,
--- a/tests/revlog-formatv0.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/revlog-formatv0.py Tue Apr 05 11:09:03 2022 +0200 @@ -17,7 +17,6 @@ empty file """ -from __future__ import absolute_import import binascii import os import sys
--- a/tests/revnamesext.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/revnamesext.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # Dummy extension to define a namespace containing revision names -from __future__ import absolute_import from mercurial import namespaces
--- a/tests/run-tests.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/run-tests.py Tue Apr 05 11:09:03 2022 +0200 @@ -43,7 +43,6 @@ # completes fairly quickly, includes both shell and Python scripts, and # includes some scripts that run daemon processes.) -from __future__ import absolute_import, print_function import argparse import collections @@ -51,12 +50,15 @@ import difflib import distutils.version as version import errno +import functools import json import multiprocessing import os import platform +import queue import random import re +import shlex import shutil import signal import socket @@ -70,21 +72,15 @@ import uuid import xml.dom.minidom as minidom +if sys.version_info < (3, 5, 0): + print( + '%s is only supported on Python 3.5+, not %s' + % (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3])) + ) + sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` + WINDOWS = os.name == r'nt' - -try: - import Queue as queue -except ImportError: - import queue - -try: - import shlex - - shellquote = shlex.quote -except (ImportError, AttributeError): - import pipes - - shellquote = pipes.quote +shellquote = shlex.quote processlock = threading.Lock() @@ -155,80 +151,62 @@ origenviron = os.environ.copy() -if sys.version_info > (3, 5, 0): - PYTHON3 = True - xrange = range # we use xrange in one place, and we'd rather not use range - - def _sys2bytes(p): - if p is None: - return p - return p.encode('utf-8') - - def _bytes2sys(p): - if p is None: - return p - return p.decode('utf-8') - - osenvironb = getattr(os, 'environb', None) - if osenvironb is None: - # Windows lacks os.environb, for instance. A proxy over the real thing - # instead of a copy allows the environment to be updated via bytes on - # all platforms. - class environbytes(object): - def __init__(self, strenv): - self.__len__ = strenv.__len__ - self.clear = strenv.clear - self._strenv = strenv - - def __getitem__(self, k): - v = self._strenv.__getitem__(_bytes2sys(k)) - return _sys2bytes(v) - - def __setitem__(self, k, v): - self._strenv.__setitem__(_bytes2sys(k), _bytes2sys(v)) - - def __delitem__(self, k): - self._strenv.__delitem__(_bytes2sys(k)) - - def __contains__(self, k): - return self._strenv.__contains__(_bytes2sys(k)) - - def __iter__(self): - return iter([_sys2bytes(k) for k in iter(self._strenv)]) - - def get(self, k, default=None): - v = self._strenv.get(_bytes2sys(k), _bytes2sys(default)) - return _sys2bytes(v) - - def pop(self, k, default=None): - v = self._strenv.pop(_bytes2sys(k), _bytes2sys(default)) - return _sys2bytes(v) - - osenvironb = environbytes(os.environ) - - getcwdb = getattr(os, 'getcwdb') - if not getcwdb or WINDOWS: - getcwdb = lambda: _sys2bytes(os.getcwd()) - -elif sys.version_info >= (3, 0, 0): - print( - '%s is only supported on Python 3.5+ and 2.7, not %s' - % (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3])) - ) - sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` -else: - PYTHON3 = False - - # In python 2.x, path operations are generally done using - # bytestrings by default, so we don't have to do any extra - # fiddling there. We define the wrapper functions anyway just to - # help keep code consistent between platforms. - def _sys2bytes(p): +xrange = range # we use xrange in one place, and we'd rather not use range + + +def _sys2bytes(p): + if p is None: + return p + return p.encode('utf-8') + + +def _bytes2sys(p): + if p is None: return p - - _bytes2sys = _sys2bytes - osenvironb = os.environ - getcwdb = os.getcwd + return p.decode('utf-8') + + +osenvironb = getattr(os, 'environb', None) +if osenvironb is None: + # Windows lacks os.environb, for instance. A proxy over the real thing + # instead of a copy allows the environment to be updated via bytes on + # all platforms. + class environbytes: + def __init__(self, strenv): + self.__len__ = strenv.__len__ + self.clear = strenv.clear + self._strenv = strenv + + def __getitem__(self, k): + v = self._strenv.__getitem__(_bytes2sys(k)) + return _sys2bytes(v) + + def __setitem__(self, k, v): + self._strenv.__setitem__(_bytes2sys(k), _bytes2sys(v)) + + def __delitem__(self, k): + self._strenv.__delitem__(_bytes2sys(k)) + + def __contains__(self, k): + return self._strenv.__contains__(_bytes2sys(k)) + + def __iter__(self): + return iter([_sys2bytes(k) for k in iter(self._strenv)]) + + def get(self, k, default=None): + v = self._strenv.get(_bytes2sys(k), _bytes2sys(default)) + return _sys2bytes(v) + + def pop(self, k, default=None): + v = self._strenv.pop(_bytes2sys(k), _bytes2sys(default)) + return _sys2bytes(v) + + osenvironb = environbytes(os.environ) + +getcwdb = getattr(os, 'getcwdb') +if not getcwdb or WINDOWS: + getcwdb = lambda: _sys2bytes(os.getcwd()) + if WINDOWS: _getcwdb = getcwdb @@ -260,10 +238,14 @@ s.bind(('localhost', port)) s.close() return True - except socket.error as exc: + except (socket.error, OSError) as exc: if exc.errno == errno.EADDRINUSE: return True - elif exc.errno in (errno.EADDRNOTAVAIL, errno.EPROTONOSUPPORT): + elif exc.errno in ( + errno.EADDRNOTAVAIL, + errno.EPROTONOSUPPORT, + errno.EAFNOSUPPORT, + ): return False else: raise @@ -288,12 +270,11 @@ except socket.error as exc: if WINDOWS and exc.errno == errno.WSAEACCES: return False - elif PYTHON3: - # TODO: make a proper exception handler after dropping py2. This - # works because socket.error is an alias for OSError on py3, - # which is also the baseclass of PermissionError. - if isinstance(exc, PermissionError): - return False + # TODO: make a proper exception handler after dropping py2. This + # works because socket.error is an alias for OSError on py3, + # which is also the baseclass of PermissionError. + elif isinstance(exc, PermissionError): + return False if exc.errno not in ( errno.EADDRINUSE, errno.EADDRNOTAVAIL, @@ -372,18 +353,10 @@ def which(exe): - if PYTHON3: - # shutil.which only accept bytes from 3.8 - cmd = _bytes2sys(exe) - real_exec = shutil.which(cmd) - return _sys2bytes(real_exec) - else: - # let us do the os work - for p in osenvironb[b'PATH'].split(os.pathsep): - f = os.path.join(p, exe) - if os.path.isfile(f): - return f - return None + # shutil.which only accept bytes from 3.8 + cmd = _bytes2sys(exe) + real_exec = shutil.which(cmd) + return _sys2bytes(real_exec) def parselistfiles(files, listtype, warn=True): @@ -898,11 +871,7 @@ pass -_unified_diff = difflib.unified_diff -if PYTHON3: - import functools - - _unified_diff = functools.partial(difflib.diff_bytes, difflib.unified_diff) +_unified_diff = functools.partial(difflib.diff_bytes, difflib.unified_diff) def getdiff(expected, output, ref, err): @@ -1486,7 +1455,7 @@ # This has the same effect as Py_LegacyWindowsStdioFlag in exewrapper.c, # but this is needed for testing python instances like dummyssh, # dummysmtpd.py, and dumbhttp.py. - if PYTHON3 and WINDOWS: + if WINDOWS: env['PYTHONLEGACYWINDOWSSTDIO'] = '1' # Modified HOME in test environment can confuse Rust tools. So set @@ -1677,9 +1646,7 @@ re.compile(br'.*\$LOCALIP.*$'), ] -bchr = chr -if PYTHON3: - bchr = lambda x: bytes([x]) +bchr = lambda x: bytes([x]) WARN_UNDEFINED = 1 WARN_YES = 2 @@ -1818,9 +1785,7 @@ script.append(b'echo %s %d $?\n' % (salt, line)) activetrace = [] - session = str(uuid.uuid4()) - if PYTHON3: - session = session.encode('ascii') + session = str(uuid.uuid4()).encode('ascii') hgcatapult = os.getenv('HGTESTCATAPULTSERVERPIPE') or os.getenv( 'HGCATAPULTSERVERPIPE' ) @@ -1874,11 +1839,8 @@ script.append(b'alias pwd="pwd -W"\n') if hgcatapult and hgcatapult != os.devnull: - if PYTHON3: - hgcatapult = hgcatapult.encode('utf8') - cataname = self.name.encode('utf8') - else: - cataname = self.name + hgcatapult = hgcatapult.encode('utf8') + cataname = self.name.encode('utf8') # Kludge: use a while loop to keep the pipe from getting # closed by our echo commands. The still-running file gets @@ -2183,11 +2145,8 @@ return "retry", False if el.endswith(b" (esc)\n"): - if PYTHON3: - el = el[:-7].decode('unicode_escape') + '\n' - el = el.encode('latin-1') - else: - el = el[:-7].decode('string-escape') + '\n' + el = el[:-7].decode('unicode_escape') + '\n' + el = el.encode('latin-1') if el == l or WINDOWS and el[:-1] + b'\r\n' == l: return True, True if el.endswith(b" (re)\n"): @@ -2235,10 +2194,7 @@ firstlock = threading.RLock() firsterror = False -if PYTHON3: - base_class = unittest.TextTestResult -else: - base_class = unittest._TextTestResult +base_class = unittest.TextTestResult class TestResult(base_class): @@ -2362,13 +2318,9 @@ self.stream.write('\n') for line in lines: line = highlightdiff(line, self.color) - if PYTHON3: - self.stream.flush() - self.stream.buffer.write(line) - self.stream.buffer.flush() - else: - self.stream.write(line) - self.stream.flush() + self.stream.flush() + self.stream.buffer.write(line) + self.stream.buffer.flush() if servefail: raise test.failureException( @@ -3035,7 +2987,7 @@ testdescs.sort(key=sortkey) -class TestRunner(object): +class TestRunner: """Holds context for executing tests. Tests rely on a lot of state. This object holds it for them. @@ -3257,10 +3209,7 @@ fileb = _sys2bytes(__file__) runtestdir = os.path.abspath(os.path.dirname(fileb)) osenvironb[b'RUNTESTDIR'] = runtestdir - if PYTHON3: - sepb = _sys2bytes(os.pathsep) - else: - sepb = os.pathsep + sepb = _sys2bytes(os.pathsep) path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) if os.path.islink(__file__): # test helper will likely be at the end of the symlink @@ -3456,7 +3405,7 @@ failed = False kws = self.options.keywords - if kws is not None and PYTHON3: + if kws is not None: kws = kws.encode('utf-8') suite = TestSuite( @@ -3604,14 +3553,10 @@ def _usecorrectpython(self): """Configure the environment to use the appropriate Python in tests.""" # Tests must use the same interpreter as us or bad things will happen. - if WINDOWS and PYTHON3: + if WINDOWS: pyexe_names = [b'python', b'python3', b'python.exe'] - elif WINDOWS: - pyexe_names = [b'python', b'python.exe'] - elif PYTHON3: + else: pyexe_names = [b'python', b'python3'] - else: - pyexe_names = [b'python', b'python2'] # os.symlink() is a thing with py3 on Windows, but it requires # Administrator rights. @@ -3654,14 +3599,6 @@ f.write(b'%s "$@"\n' % esc_executable) if WINDOWS: - if not PYTHON3: - # lets try to build a valid python3 executable for the - # scrip that requires it. - py3exe_name = os.path.join(self._custom_bin_dir, b'python3') - with open(py3exe_name, 'wb') as f: - f.write(b'#!/bin/sh\n') - f.write(b'py -3 "$@"\n') - # adjust the path to make sur the main python finds it own dll path = os.environ['PATH'].split(os.pathsep) main_exec_dir = os.path.dirname(sysexecutable) @@ -3674,8 +3611,6 @@ if appdata is not None: python_dir = 'Python%d%d' % (vi[0], vi[1]) scripts_path = [appdata, 'Python', python_dir, 'Scripts'] - if not PYTHON3: - scripts_path = [appdata, 'Python', 'Scripts'] scripts_dir = os.path.join(*scripts_path) extra_paths.append(scripts_dir) @@ -3719,12 +3654,9 @@ setup_opts = b"--no-rust" # Run installer in hg root - script = os.path.realpath(sys.argv[0]) - exe = sysexecutable - if PYTHON3: - compiler = _sys2bytes(compiler) - script = _sys2bytes(script) - exe = _sys2bytes(exe) + compiler = _sys2bytes(compiler) + script = _sys2bytes(os.path.realpath(sys.argv[0])) + exe = _sys2bytes(sysexecutable) hgroot = os.path.dirname(os.path.dirname(script)) self._hgroot = hgroot os.chdir(hgroot) @@ -3776,10 +3708,7 @@ else: with open(installerrs, 'rb') as f: for line in f: - if PYTHON3: - sys.stdout.buffer.write(line) - else: - sys.stdout.write(line) + sys.stdout.buffer.write(line) sys.exit(1) os.chdir(self._testdir) @@ -3840,9 +3769,7 @@ return self._hgpath cmd = b'"%s" -c "import mercurial; print (mercurial.__path__[0])"' - cmd = cmd % PYTHON - if PYTHON3: - cmd = _bytes2sys(cmd) + cmd = _bytes2sys(cmd % PYTHON) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) out, err = p.communicate() @@ -3872,10 +3799,7 @@ ) out, _err = proc.communicate() if proc.returncode != 0: - if PYTHON3: - sys.stdout.buffer.write(out) - else: - sys.stdout.write(out) + sys.stdout.buffer.write(out) sys.exit(1) def _installrhg(self): @@ -3899,10 +3823,7 @@ ) out, _err = proc.communicate() if proc.returncode != 0: - if PYTHON3: - sys.stdout.buffer.write(out) - else: - sys.stdout.write(out) + sys.stdout.buffer.write(out) sys.exit(1) def _build_pyoxidized(self): @@ -3930,10 +3851,7 @@ ) out, _err = proc.communicate() if proc.returncode != 0: - if PYTHON3: - sys.stdout.buffer.write(out) - else: - sys.stdout.write(out) + sys.stdout.buffer.write(out) sys.exit(1) def _outputcoverage(self):
--- a/tests/seq.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/seq.py Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ # seq START STOP [START, STOP] stepping by 1 # seq START STEP STOP [START, STOP] stepping by STEP -from __future__ import absolute_import, print_function import os import sys
--- a/tests/silenttestrunner.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/silenttestrunner.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import os import sys import unittest
--- a/tests/simplestorerepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/simplestorerepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -10,7 +10,6 @@ # $ HGREPOFEATURES="simplestore" ./run-tests.py \ # --extra-config-opt extensions.simplestore=`pwd`/simplestorerepo.py -from __future__ import absolute_import import stat @@ -71,7 +70,7 @@ @interfaceutil.implementer(repository.irevisiondelta) @attr.s(slots=True) -class simplestorerevisiondelta(object): +class simplestorerevisiondelta: node = attr.ib() p1node = attr.ib() p2node = attr.ib() @@ -85,14 +84,14 @@ @interfaceutil.implementer(repository.iverifyproblem) @attr.s(frozen=True) -class simplefilestoreproblem(object): +class simplefilestoreproblem: warning = attr.ib(default=None) error = attr.ib(default=None) node = attr.ib(default=None) @interfaceutil.implementer(repository.ifilestorage) -class filestorage(object): +class filestorage: """Implements storage for a tracked path. Data is stored in the VFS in a directory corresponding to the tracked
--- a/tests/sitecustomize.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/sitecustomize.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import os if os.environ.get('COVERAGE_PROCESS_START'):
--- a/tests/sshprotoext.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/sshprotoext.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # This extension replaces the SSH server started via `hg serve --stdio`. # The server behaves differently depending on environment variables. -from __future__ import absolute_import from mercurial import ( error,
--- a/tests/svn-safe-append.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/svn-safe-append.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -from __future__ import absolute_import __doc__ = """Same as `echo a >> b`, but ensures a changed mtime of b. Without this svn will not detect workspace changes."""
--- a/tests/svnurlof.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/svnurlof.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import sys from mercurial import (
--- a/tests/svnxml.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/svnxml.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ # Read the output of a "svn log --xml" command on stdin, parse it and # print a subset of attributes common to all svn versions tested by # hg. -from __future__ import absolute_import import sys import xml.dom.minidom
--- a/tests/test-absorb-filefixupstate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-absorb-filefixupstate.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,11 +1,9 @@ -from __future__ import absolute_import, print_function - import itertools from mercurial import pycompat from hgext import absorb -class simplefctx(object): +class simplefctx: def __init__(self, content): self.content = content
--- a/tests/test-ancestor.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-ancestor.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import binascii import getopt import math @@ -64,7 +62,7 @@ return ancs -class naiveincrementalmissingancestors(object): +class naiveincrementalmissingancestors: def __init__(self, ancs, bases): self.ancs = ancs self.bases = set(bases)
--- a/tests/test-annotate.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-annotate.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,3 @@ -from __future__ import absolute_import -from __future__ import print_function - import unittest from mercurial import (
--- a/tests/test-annotate.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-annotate.t Tue Apr 05 11:09:03 2022 +0200 @@ -478,7 +478,6 @@ and its ancestor by overriding "repo._filecommit". $ cat > ../legacyrepo.py <<EOF - > from __future__ import absolute_import > from mercurial import commit, error, extensions > def _filecommit(orig, repo, fctx, manifest1, manifest2, > linkrev, tr, includecopymeta, ms):
--- a/tests/test-arbitraryfilectx.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-arbitraryfilectx.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ Setup: $ cat > eval.py <<EOF - > from __future__ import absolute_import > import filecmp > from mercurial import commands, context, pycompat, registrar > cmdtable = {}
--- a/tests/test-archive.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-archive.t Tue Apr 05 11:09:03 2022 +0200 @@ -320,7 +320,6 @@ $ TIP=`hg id -v | cut -f1 -d' '` $ QTIP=`hg id -q` $ cat > getarchive.py <<EOF - > from __future__ import absolute_import > import os > import sys > from mercurial import ( @@ -455,7 +454,6 @@ > done $ cat > md5comp.py <<EOF - > from __future__ import absolute_import, print_function > import hashlib > import sys > f1, f2 = sys.argv[1:3] @@ -582,16 +580,11 @@ Strms Blocks Compressed Uncompressed Ratio Check Filename (xz !) $ rm -f ../archive.txz #endif -#if py3 no-lzma +#if no-lzma $ hg archive ../archive.txz abort: lzma module is not available [255] #endif -#if no-py3 - $ hg archive ../archive.txz - abort: xz compression is only available in Python 3 - [255] -#endif show an error when a provided pattern matches no files @@ -617,7 +610,6 @@ $ hg -R repo add repo/a $ hg -R repo commit -m '#0' -d '456789012 21600' $ cat > show_mtime.py <<EOF - > from __future__ import absolute_import, print_function > import os > import sys > print(int(os.stat(sys.argv[1]).st_mtime))
--- a/tests/test-atomictempfile.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-atomictempfile.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import glob import os import shutil
--- a/tests/test-bad-extension.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-bad-extension.t Tue Apr 05 11:09:03 2022 +0200 @@ -54,7 +54,6 @@ $ hg -q help help 2>&1 |grep extension *** failed to import extension "badext" from $TESTTMP/badext.py: bit bucket overflow *** failed to import extension "badext2": No module named 'badext2' (py3 !) - *** failed to import extension "badext2": No module named badext2 (no-py3 !) show traceback @@ -63,9 +62,7 @@ Traceback (most recent call last): Exception: bit bucket overflow *** failed to import extension "badext2": No module named 'badext2' (py3 !) - *** failed to import extension "badext2": No module named badext2 (no-py3 !) Traceback (most recent call last): - ImportError: No module named badext2 (no-py3 !) ImportError: No module named 'hgext.badext2' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext.badext2' (py36 !) Traceback (most recent call last): (py3 !) @@ -114,19 +111,16 @@ YYYY/MM/DD HH:MM:SS (PID)> - loading extension: badext2 YYYY/MM/DD HH:MM:SS (PID)> - could not import hgext.badext2 (No module named *badext2*): trying hgext3rd.badext2 (glob) Traceback (most recent call last): - ImportError: No module named badext2 (no-py3 !) ImportError: No module named 'hgext.badext2' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext.badext2' (py36 !) YYYY/MM/DD HH:MM:SS (PID)> - could not import hgext3rd.badext2 (No module named *badext2*): trying badext2 (glob) Traceback (most recent call last): - ImportError: No module named badext2 (no-py3 !) ImportError: No module named 'hgext.badext2' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext.badext2' (py36 !) Traceback (most recent call last): (py3 !) ImportError: No module named 'hgext3rd.badext2' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext3rd.badext2' (py36 !) *** failed to import extension "badext2": No module named 'badext2' (py3 !) - *** failed to import extension "badext2": No module named badext2 (no-py3 !) Traceback (most recent call last): ImportError: No module named 'hgext.badext2' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext.badext2' (py36 !) @@ -136,7 +130,6 @@ Traceback (most recent call last): (py3 !) ModuleNotFoundError: No module named 'badext2' (py36 !) ImportError: No module named 'badext2' (py3 no-py36 !) - ImportError: No module named badext2 (no-py3 !) YYYY/MM/DD HH:MM:SS (PID)> > loaded 2 extensions, total time * (glob) YYYY/MM/DD HH:MM:SS (PID)> - loading configtable attributes YYYY/MM/DD HH:MM:SS (PID)> - executing uisetup hooks @@ -165,7 +158,6 @@ $ hg help --keyword baddocext *** failed to import extension "badext" from $TESTTMP/badext.py: bit bucket overflow *** failed to import extension "badext2": No module named 'badext2' (py3 !) - *** failed to import extension "badext2": No module named badext2 (no-py3 !) Topics: extensions Using Additional Features
--- a/tests/test-basic.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-basic.t Tue Apr 05 11:09:03 2022 +0200 @@ -240,15 +240,16 @@ Underlying message streams should be updated when ui.fout/ferr are set: $ cat <<'EOF' > capui.py - > from mercurial import pycompat, registrar + > import io + > from mercurial import registrar > cmdtable = {} > command = registrar.command(cmdtable) > @command(b'capui', norepo=True) > def capui(ui): > out = ui.fout - > ui.fout = pycompat.bytesio() + > ui.fout = io.BytesIO() > ui.status(b'status\n') - > ui.ferr = pycompat.bytesio() + > ui.ferr = io.BytesIO() > ui.warn(b'warn\n') > out.write(b'stdout: %s' % ui.fout.getvalue()) > out.write(b'stderr: %s' % ui.ferr.getvalue())
--- a/tests/test-batching.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-batching.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import, print_function import contextlib @@ -21,7 +20,7 @@ # equivalent of repo.repository -class thing(object): +class thing: def hello(self): return b"Ready." @@ -108,7 +107,7 @@ # server side # equivalent of wireproto's global functions -class server(object): +class server: def __init__(self, local): self.local = local
--- a/tests/test-bdiff.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-bdiff.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import collections import struct import unittest
--- a/tests/test-bisect.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-bisect.t Tue Apr 05 11:09:03 2022 +0200 @@ -462,7 +462,6 @@ $ cat > script.py <<EOF > #!$PYTHON - > from __future__ import absolute_import > import sys > from mercurial import hg, ui as uimod > repo = hg.repository(uimod.ui.load(), b'.')
--- a/tests/test-blackbox.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-blackbox.t Tue Apr 05 11:09:03 2022 +0200 @@ -403,7 +403,6 @@ when using chg, blackbox.log should get rotated correctly $ cat > $TESTTMP/noop.py << EOF - > from __future__ import absolute_import > import time > from mercurial import registrar, scmutil > cmdtable = {} @@ -463,7 +462,6 @@ blackbox should work if repo.ui.log is not called (issue5518) $ cat > $TESTTMP/raise.py << EOF - > from __future__ import absolute_import > from mercurial import registrar, scmutil > cmdtable = {} > command = registrar.command(cmdtable)
--- a/tests/test-bookmarks.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-bookmarks.t Tue Apr 05 11:09:03 2022 +0200 @@ -1069,7 +1069,6 @@ $ echo a > a $ cat > $TESTTMP/pausefinalize.py <<EOF - > from __future__ import absolute_import > import os > import time > from mercurial import extensions, localrepo
--- a/tests/test-bugzilla.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-bugzilla.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ mock bugzilla driver for testing template output: $ cat <<EOF > bzmock.py - > from __future__ import absolute_import > from mercurial import extensions > from mercurial import pycompat > from mercurial import registrar
--- a/tests/test-bundle.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-bundle.t Tue Apr 05 11:09:03 2022 +0200 @@ -466,7 +466,6 @@ transaction) $ cat > $TESTTMP/showtip.py <<EOF - > from __future__ import absolute_import > > def showtip(ui, repo, hooktype, **kwargs): > ui.warn(b'%s: %s\n' % (hooktype, repo[b'tip'].hex()[:12]))
--- a/tests/test-bundle2-pushback.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-bundle2-pushback.t Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ > Current bundle2 implementation doesn't provide a way to generate those > parts, so they must be created by extensions. > """ - > from __future__ import absolute_import > from mercurial import bundle2, exchange, pushkey, util > def _newhandlechangegroup(op, inpart): > """This function wraps the changegroup part handler for getbundle.
--- a/tests/test-cappedreader.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-cappedreader.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import io import unittest
--- a/tests/test-cbor.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-cbor.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import os import sys import unittest
--- a/tests/test-check-code.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-check-code.t Tue Apr 05 11:09:03 2022 +0200 @@ -27,7 +27,6 @@ Skipping contrib/packaging/hgpackaging/cli.py it has no-che?k-code (glob) Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob) Skipping contrib/packaging/hgpackaging/inno.py it has no-che?k-code (glob) - Skipping contrib/packaging/hgpackaging/py2exe.py it has no-che?k-code (glob) Skipping contrib/packaging/hgpackaging/pyoxidizer.py it has no-che?k-code (glob) Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob) Skipping contrib/packaging/hgpackaging/wix.py it has no-che?k-code (glob)
--- a/tests/test-check-help.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-check-help.t Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ $ . "$TESTDIR/helpers-testrepo.sh" $ cat <<'EOF' > scanhelptopics.py - > from __future__ import absolute_import, print_function > import re > import sys > if sys.platform == "win32":
--- a/tests/test-check-interfaces.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-check-interfaces.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # Test that certain objects conform to well-defined interfaces. -from __future__ import absolute_import, print_function from mercurial import encoding @@ -81,7 +80,7 @@ # Facilitates testing localpeer. -class dummyrepo(object): +class dummyrepo: def __init__(self): self.ui = uimod.ui() self._wanted_sidedata = set() @@ -93,7 +92,7 @@ pass -class dummyopener(object): +class dummyopener: handlers = [] @@ -109,7 +108,7 @@ pass -class dummypipe(object): +class dummypipe: def close(self): pass
--- a/tests/test-check-py3-compat.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-check-py3-compat.t Tue Apr 05 11:09:03 2022 +0200 @@ -3,35 +3,7 @@ $ . "$TESTDIR/helpers-testrepo.sh" $ cd "$TESTDIR"/.. -#if no-py3 - $ testrepohg files 'set:(**.py)' \ - > -X contrib/automation/ \ - > -X contrib/packaging/hgpackaging/ \ - > -X contrib/packaging/inno/ \ - > -X contrib/packaging/packaging.py \ - > -X contrib/packaging/wix/ \ - > -X hgdemandimport/demandimportpy2.py \ - > -X mercurial/thirdparty/cbor \ - > | sed 's|\\|/|g' | xargs "$PYTHON" contrib/check-py3-compat.py - contrib/python-zstandard/setup.py not using absolute_import - contrib/python-zstandard/setup_zstd.py not using absolute_import - contrib/python-zstandard/tests/common.py not using absolute_import - contrib/python-zstandard/tests/test_buffer_util.py not using absolute_import - contrib/python-zstandard/tests/test_compressor.py not using absolute_import - contrib/python-zstandard/tests/test_compressor_fuzzing.py not using absolute_import - contrib/python-zstandard/tests/test_data_structures.py not using absolute_import - contrib/python-zstandard/tests/test_data_structures_fuzzing.py not using absolute_import - contrib/python-zstandard/tests/test_decompressor.py not using absolute_import - contrib/python-zstandard/tests/test_decompressor_fuzzing.py not using absolute_import - contrib/python-zstandard/tests/test_estimate_sizes.py not using absolute_import - contrib/python-zstandard/tests/test_module_attributes.py not using absolute_import - contrib/python-zstandard/tests/test_train_dictionary.py not using absolute_import - setup.py not using absolute_import -#endif - -#if py3 $ testrepohg files 'set:(**.py) - grep(pygments)' \ - > -X hgdemandimport/demandimportpy2.py \ > -X hgext/fsmonitor/pywatchman \ > -X mercurial/cffi \ > -X mercurial/thirdparty \ @@ -44,9 +16,8 @@ mercurial/windows.py: error importing: <*Error> No module named 'msvcrt' (error at windows.py:*) (glob) (no-windows !) mercurial/posix.py: error importing: <*Error> No module named 'fcntl' (error at posix.py:*) (glob) (windows !) mercurial/scmposix.py: error importing: <*Error> No module named 'fcntl' (error at scmposix.py:*) (glob) (windows !) -#endif -#if py3 pygments +#if pygments $ testrepohg files 'set:(**.py) and grep(pygments)' | sed 's|\\|/|g' \ > | xargs "$PYTHON" contrib/check-py3-compat.py \ > | sed 's/[0-9][0-9]*)$/*)/'
--- a/tests/test-check-pyflakes.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-check-pyflakes.t Tue Apr 05 11:09:03 2022 +0200 @@ -15,13 +15,19 @@ $ testrepohg locate 'set:**.py or grep("^#!.*python")' \ > -X hgext/fsmonitor/pywatchman \ - > -X mercurial/pycompat.py -X contrib/python-zstandard \ + > -X contrib/python-zstandard \ > -X mercurial/thirdparty \ > 2>/dev/null \ > | xargs "$PYTHON" -m pyflakes 2>/dev/null | "$TESTDIR/filterpyflakes.py" contrib/perf.py:*:* undefined name 'xrange' (glob) (?) mercurial/hgweb/server.py:*:* undefined name 'reload' (glob) (?) - mercurial/util.py:*:* undefined name 'file' (glob) (?) - mercurial/encoding.py:*:* undefined name 'localstr' (glob) (?) - tests/run-tests.py:*:* undefined name 'PermissionError' (glob) (?) + mercurial/pycompat.py:*:* 'codecs' imported but unused (glob) + mercurial/pycompat.py:*:* 'concurrent.futures' imported but unused (glob) + mercurial/pycompat.py:*:* 'http.client as httplib' imported but unused (glob) + mercurial/pycompat.py:*:* 'http.cookiejar as cookielib' imported but unused (glob) + mercurial/pycompat.py:*:* 'io' imported but unused (glob) + mercurial/pycompat.py:*:* 'queue' imported but unused (glob) + mercurial/pycompat.py:*:* 'socketserver' imported but unused (glob) + mercurial/pycompat.py:*:* 'xmlrpc.client as xmlrpclib' imported but unused (glob) + mercurial/util.py:*:* 'pickle' imported but unused (glob)
--- a/tests/test-chg.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-chg.t Tue Apr 05 11:09:03 2022 +0200 @@ -132,7 +132,6 @@ > EOF $ cat > $TESTTMP/fakepager.py <<EOF - > from __future__ import absolute_import > import sys > import time > for line in iter(sys.stdin.readline, ''):
--- a/tests/test-commandserver.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-commandserver.t Tue Apr 05 11:09:03 2022 +0200 @@ -23,7 +23,6 @@ $ hg init repo $ cd repo - >>> from __future__ import absolute_import >>> import os >>> import sys >>> from hgclient import bprint, check, readchannel, runcommand
--- a/tests/test-commit-interactive.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-commit-interactive.t Tue Apr 05 11:09:03 2022 +0200 @@ -938,7 +938,6 @@ $ export LANGUAGE $ cat > $TESTTMP/escape.py <<EOF - > from __future__ import absolute_import > from mercurial import ( > pycompat, > )
--- a/tests/test-commit.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-commit.t Tue Apr 05 11:09:03 2022 +0200 @@ -645,7 +645,6 @@ verify pathauditor blocks evil filepaths $ cat > evil-commit.py <<EOF - > from __future__ import absolute_import > from mercurial import context, hg, ui as uimod > notrc = u".h\u200cg".encode('utf-8') + b'/hgrc' > u = uimod.ui.load() @@ -671,7 +670,6 @@ $ hg rollback -f repository tip rolled back to revision 2 (undo commit) $ cat > evil-commit.py <<EOF - > from __future__ import absolute_import > from mercurial import context, hg, ui as uimod > notrc = b"HG~1/hgrc" > u = uimod.ui.load() @@ -691,7 +689,6 @@ $ hg rollback -f repository tip rolled back to revision 2 (undo commit) $ cat > evil-commit.py <<EOF - > from __future__ import absolute_import > from mercurial import context, hg, ui as uimod > notrc = b"HG8B6C~2/hgrc" > u = uimod.ui.load()
--- a/tests/test-config-env.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-config-env.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # Test the config layer generated by environment variables -from __future__ import absolute_import, print_function import os
--- a/tests/test-context-metadata.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-context-metadata.t Tue Apr 05 11:09:03 2022 +0200 @@ -12,7 +12,6 @@ $ hg commit -m 'Remove A' $ cat > metaedit.py <<EOF - > from __future__ import absolute_import > from mercurial import context, pycompat, registrar > cmdtable = {} > command = registrar.command(cmdtable)
--- a/tests/test-context.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-context.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import os import stat import sys
--- a/tests/test-contrib-check-code.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-contrib-check-code.t Tue Apr 05 11:09:03 2022 +0200 @@ -51,12 +51,6 @@ ./quote.py:5: > '"""', 42+1, """and missing whitespace in expression - ./classstyle.py:4: - > class oldstyle_class: - old-style class, use class foo(object) - ./classstyle.py:7: - > class empty(): - class foo() creates old style object, use class foo(object) [1] $ cat > python3-compat.py << NO_CHECK_EOF > foo <> bar
--- a/tests/test-contrib-perf.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-contrib-perf.t Tue Apr 05 11:09:03 2022 +0200 @@ -301,7 +301,6 @@ malformatted run limit entry, missing "-": 500 ! wall * comb * user * sys * (best of 5) (glob) $ hg perfparents --config perf.stub=no --config perf.run-limits='aaa-12, 0.000000001-5' - malformatted run limit entry, could not convert string to float: aaa: aaa-12 (no-py3 !) malformatted run limit entry, could not convert string to float: 'aaa': aaa-12 (py3 !) ! wall * comb * user * sys * (best of 5) (glob) $ hg perfparents --config perf.stub=no --config perf.run-limits='12-aaaaaa, 0.000000001-5'
--- a/tests/test-convert-clonebranches.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-convert-clonebranches.t Tue Apr 05 11:09:03 2022 +0200 @@ -31,7 +31,6 @@ Miss perl... sometimes $ cat > filter.py <<EOF - > from __future__ import absolute_import > import re > import sys >
--- a/tests/test-convert-git.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-convert-git.t Tue Apr 05 11:09:03 2022 +0200 @@ -435,7 +435,7 @@ $ cd git-repo3-hg $ hg up -C 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ "$PYTHON" -c 'from __future__ import print_function; print(len(open("b", "rb").read()))' + $ "$PYTHON" -c 'print(len(open("b", "rb").read()))' 4096 $ cd ..
--- a/tests/test-debugcommands.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-debugcommands.t Tue Apr 05 11:09:03 2022 +0200 @@ -212,7 +212,6 @@ { "chainid": 1, "chainlen": 1, - "chainratio": 1.02325581395, (no-py3 !) "chainratio": 1.0232558139534884, (py3 !) "chainsize": 44, "compsize": 44, @@ -249,7 +248,6 @@ { "chainid": 3, "chainlen": 1, - "chainratio": 1.02325581395, (no-py3 !) "chainratio": 1.0232558139534884, (py3 !) "chainsize": 44, "compsize": 44, @@ -289,7 +287,6 @@ { "chainid": 1, "chainlen": 1, - "chainratio": 1.02325581395, (no-py3 !) "chainratio": 1.0232558139534884, (py3 !) "chainsize": 44, "compsize": 44, @@ -326,7 +323,6 @@ { "chainid": 3, "chainlen": 1, - "chainratio": 1.02325581395, (no-py3 !) "chainratio": 1.0232558139534884, (py3 !) "chainsize": 44, "compsize": 44, @@ -574,7 +570,6 @@ Test internal debugstacktrace command $ cat > debugstacktrace.py << EOF - > from __future__ import absolute_import > from mercurial import ( > util, > ) @@ -593,15 +588,15 @@ > EOF $ "$PYTHON" debugstacktrace.py stacktrace at: - *debugstacktrace.py:16 in * (glob) - *debugstacktrace.py:9 in f (glob) + *debugstacktrace.py:15 in * (glob) + *debugstacktrace.py:8 in f (glob) hello from g at: - *debugstacktrace.py:16 in * (glob) - *debugstacktrace.py:10 in f (glob) + *debugstacktrace.py:15 in * (glob) + *debugstacktrace.py:9 in f (glob) hi ... from h hidden in g at: - *debugstacktrace.py:10 in f (glob) - *debugstacktrace.py:13 in g (glob) + *debugstacktrace.py:9 in f (glob) + *debugstacktrace.py:12 in g (glob) Test debugcapabilities command:
--- a/tests/test-demandimport.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-demandimport.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - from mercurial import demandimport demandimport.enable()
--- a/tests/test-dirs.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-dirs.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import unittest import silenttestrunner
--- a/tests/test-dirstate.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-dirstate.t Tue Apr 05 11:09:03 2022 +0200 @@ -77,7 +77,6 @@ coherent (issue4353) $ cat > ../dirstateexception.py <<EOF - > from __future__ import absolute_import > from mercurial import ( > error, > extensions,
--- a/tests/test-dispatch.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-dispatch.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import os import sys from mercurial import dispatch
--- a/tests/test-doctest.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-doctest.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,5 @@ # this is hack to make sure no escape characters are inserted into the output -from __future__ import absolute_import -from __future__ import print_function import doctest import os
--- a/tests/test-duplicateoptions.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-duplicateoptions.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import os from mercurial import ( commands,
--- a/tests/test-encoding-func.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-encoding-func.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import unittest from mercurial import encoding
--- a/tests/test-eol.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-eol.t Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ Set up helpers $ cat > switch-eol.py <<'EOF' - > from __future__ import absolute_import > import os > import sys > try:
--- a/tests/test-extension.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-extension.t Tue Apr 05 11:09:03 2022 +0200 @@ -150,7 +150,6 @@ Check that extensions are loaded in phases: $ cat > foo.py <<EOF - > from __future__ import print_function > import os > from mercurial import exthelper > from mercurial.utils import procutil @@ -295,7 +294,6 @@ $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py $ cat > $TESTTMP/libroot/mod/ambigabs.py <<NO_CHECK_EOF - > from __future__ import absolute_import, print_function > import ambig # should load "libroot/ambig.py" > s = ambig.s > NO_CHECK_EOF @@ -309,23 +307,6 @@ ambigabs.s=libroot/ambig.py $TESTTMP/a -#if no-py3 - $ cat > $TESTTMP/libroot/mod/ambigrel.py <<NO_CHECK_EOF - > from __future__ import print_function - > import ambig # should load "libroot/mod/ambig.py" - > s = ambig.s - > NO_CHECK_EOF - $ cat > loadrel.py <<NO_CHECK_EOF - > import mod.ambigrel as ambigrel - > def extsetup(ui): - > print('ambigrel.s=%s' % ambigrel.s, flush=True) - > NO_CHECK_EOF - $ "$PYTHON" $TESTTMP/unflush.py loadrel.py - $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root) - ambigrel.s=libroot/mod/ambig.py - $TESTTMP/a -#endif - Check absolute/relative import of extension specific modules $ mkdir $TESTTMP/extroot @@ -340,7 +321,6 @@ > s = b'this is extroot.sub1.baz' > NO_CHECK_EOF $ cat > $TESTTMP/extroot/__init__.py <<NO_CHECK_EOF - > from __future__ import absolute_import > s = b'this is extroot.__init__' > from . import foo > def extsetup(ui): @@ -377,39 +357,6 @@ (extroot) import extroot.bar in func(): this is extroot.bar $TESTTMP/a -#if no-py3 - $ rm "$TESTTMP"/extroot/foo.* - $ rm -Rf "$TESTTMP/extroot/__pycache__" - $ cat > $TESTTMP/extroot/foo.py <<NO_CHECK_EOF - > # test relative import - > buf = [] - > def func(): - > # "not locals" case - > import bar - > buf.append('import bar in func(): %s' % bar.s) - > return '\n(extroot) '.join(buf) - > # "fromlist == ('*',)" case - > from bar import * - > buf.append('from bar import *: %s' % s) - > # "not fromlist" and "if '.' in name" case - > import sub1.baz - > buf.append('import sub1.baz: %s' % sub1.baz.s) - > # "not fromlist" and NOT "if '.' in name" case - > import sub1 - > buf.append('import sub1: %s' % sub1.s) - > # NOT "not fromlist" and NOT "level != -1" case - > from bar import s - > buf.append('from bar import s: %s' % s) - > NO_CHECK_EOF - $ hg --config extensions.extroot=$TESTTMP/extroot root - (extroot) from bar import *: this is extroot.bar - (extroot) import sub1.baz: this is extroot.sub1.baz - (extroot) import sub1: this is extroot.sub1.__init__ - (extroot) from bar import s: this is extroot.bar - (extroot) import bar in func(): this is extroot.bar - $TESTTMP/a -#endif - #if demandimport Examine whether module loading is delayed until actual referring, even @@ -453,7 +400,6 @@ > detail = b"this is extlibroot.recursedown.abs.used" > NO_CHECK_EOF $ cat > $TESTTMP/extlibroot/recursedown/abs/__init__.py <<NO_CHECK_EOF - > from __future__ import absolute_import > from extlibroot.recursedown.abs.used import detail > NO_CHECK_EOF @@ -467,7 +413,6 @@ > NO_CHECK_EOF $ cat > $TESTTMP/extlibroot/recursedown/__init__.py <<NO_CHECK_EOF - > from __future__ import absolute_import > from extlibroot.recursedown.abs import detail as absdetail > from .legacy import detail as legacydetail > NO_CHECK_EOF @@ -481,11 +426,9 @@ > detail = b"this is extlibroot.shadowing.used" > NO_CHECK_EOF $ cat > $TESTTMP/extlibroot/shadowing/proxied.py <<NO_CHECK_EOF - > from __future__ import absolute_import > from extlibroot.shadowing.used import detail > NO_CHECK_EOF $ cat > $TESTTMP/extlibroot/shadowing/__init__.py <<NO_CHECK_EOF - > from __future__ import absolute_import > from .used import detail as used > NO_CHECK_EOF @@ -514,7 +457,6 @@ > detail = b"this is absextroot.relimportee" > NO_CHECK_EOF $ cat > $TESTTMP/absextroot/xsub1/xsub2/relimporter.py <<NO_CHECK_EOF - > from __future__ import absolute_import > from mercurial import pycompat > from ... import relimportee > detail = b"this relimporter imports %r" % ( @@ -525,7 +467,6 @@ runtime. $ cat > $TESTTMP/absextroot/absolute.py << NO_CHECK_EOF - > from __future__ import absolute_import > > # import extension local modules absolutely (level = 0) > from absextroot.xsub1.xsub2 import used, unused @@ -539,7 +480,6 @@ > NO_CHECK_EOF $ cat > $TESTTMP/absextroot/relative.py << NO_CHECK_EOF - > from __future__ import absolute_import > > # import extension local modules relatively (level == 1) > from .xsub1.xsub2 import used, unused @@ -559,7 +499,6 @@ Setup main procedure of extension. $ cat > $TESTTMP/absextroot/__init__.py <<NO_CHECK_EOF - > from __future__ import absolute_import > from mercurial import registrar > cmdtable = {} > command = registrar.command(cmdtable) @@ -1925,7 +1864,6 @@ $ hg init $TESTTMP/opt-unicode-default $ cat > $TESTTMP/test_unicode_default_value.py << EOF - > from __future__ import print_function > from mercurial import registrar > cmdtable = {} > command = registrar.command(cmdtable) @@ -1940,7 +1878,6 @@ > EOF $ hg -R $TESTTMP/opt-unicode-default dummy *** failed to import extension "test_unicode_default_value" from $TESTTMP/test_unicode_default_value.py: unicode 'value' found in cmdtable.dummy (py3 !) - *** failed to import extension "test_unicode_default_value" from $TESTTMP/test_unicode_default_value.py: unicode u'value' found in cmdtable.dummy (no-py3 !) *** (use b'' to make it byte string) hg: unknown command 'dummy' (did you mean summary?)
--- a/tests/test-extensions-wrapfunction.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-extensions-wrapfunction.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - from mercurial import extensions @@ -18,7 +16,7 @@ wrappers = [genwrapper(i) for i in range(5)] -class dummyclass(object): +class dummyclass: def getstack(self): return ['orig'] @@ -69,7 +67,7 @@ print('context manager', dummy.getstack()) # Wrap callable object which has no __name__ -class callableobj(object): +class callableobj: def __call__(self): return ['orig']
--- a/tests/test-fastannotate-hg.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-fastannotate-hg.t Tue Apr 05 11:09:03 2022 +0200 @@ -481,7 +481,6 @@ and its ancestor by overriding "repo._filecommit". $ cat > ../legacyrepo.py <<EOF - > from __future__ import absolute_import > from mercurial import commit, error, extensions > def _filecommit(orig, repo, fctx, manifest1, manifest2, > linkrev, tr, includecopymeta, ms):
--- a/tests/test-fastannotate-revmap.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-fastannotate-revmap.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import os import tempfile @@ -171,7 +169,7 @@ os.unlink(path2) -class fakefctx(object): +class fakefctx: def __init__(self, node, path=None): self._node = node self._path = path
--- a/tests/test-filebranch.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-filebranch.t Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ when we do a merge. $ cat <<EOF > merge - > from __future__ import print_function > import sys, os > print("merging for", os.path.basename(sys.argv[1])) > EOF
--- a/tests/test-filecache.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-filecache.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import os import stat import subprocess @@ -36,11 +35,11 @@ xrange = range -class fakerepo(object): +class fakerepo: def __init__(self): self._filecache = {} - class fakevfs(object): + class fakevfs: def join(self, p): return p
--- a/tests/test-filelog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-filelog.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ """ Tests the behavior of filelog w.r.t. data starting with '\1\n' """ -from __future__ import absolute_import, print_function from mercurial.node import hex from mercurial import (
--- a/tests/test-flagprocessor.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-flagprocessor.t Tue Apr 05 11:09:03 2022 +0200 @@ -214,12 +214,10 @@ File "mercurial.revlogutils.flagutil", line *, in insertflagprocessor (glob) (pyoxidizer !) raise error.Abort(msg) mercurial.error.Abort: cannot register multiple processors on flag '0x8'. (py3 !) - Abort: cannot register multiple processors on flag '0x8'. (no-py3 !) *** failed to set up extension duplicate: cannot register multiple processors on flag '0x8'. $ hg st 2>&1 | egrep 'cannot register multiple processors|flagprocessorext' File "*/tests/flagprocessorext.py", line *, in extsetup (glob) mercurial.error.Abort: cannot register multiple processors on flag '0x8'. (py3 !) - Abort: cannot register multiple processors on flag '0x8'. (no-py3 !) *** failed to set up extension duplicate: cannot register multiple processors on flag '0x8'. File "*/tests/flagprocessorext.py", line *, in b64decode (glob)
--- a/tests/test-fncache.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-fncache.t Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ does not break $ cat > chunksize.py <<EOF - > from __future__ import absolute_import > from mercurial import store > store.fncache_chunksize = 1 > EOF @@ -232,7 +231,6 @@ Aborting lock does not prevent fncache writes $ cat > exceptionext.py <<EOF - > from __future__ import absolute_import > import os > from mercurial import commands, error, extensions > @@ -279,7 +277,6 @@ Aborting transaction prevents fncache change $ cat > ../exceptionext.py <<EOF - > from __future__ import absolute_import > import os > from mercurial import commands, error, extensions, localrepo > @@ -315,7 +312,6 @@ Aborted transactions can be recovered later $ cat > ../exceptionext.py <<EOF - > from __future__ import absolute_import > import os > from mercurial import ( > commands, @@ -483,7 +479,6 @@ changesets that only contain changes to existing files: $ cat > fncacheloadwarn.py << EOF - > from __future__ import absolute_import > from mercurial import extensions, localrepo > > def extsetup(ui):
--- a/tests/test-generaldelta.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-generaldelta.t Tue Apr 05 11:09:03 2022 +0200 @@ -25,7 +25,6 @@ > done $ cd .. - >>> from __future__ import print_function >>> import os >>> regsize = os.stat("repo/.hg/store/00manifest.i").st_size >>> gdsize = os.stat("gdrepo/.hg/store/00manifest.i").st_size
--- a/tests/test-hardlinks.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hardlinks.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ #require hardlink reporevlogstore $ cat > nlinks.py <<EOF - > from __future__ import print_function > import sys > from mercurial import pycompat, util > for f in sorted(sys.stdin.readlines()): @@ -17,7 +16,6 @@ Some implementations of cp can't create hardlinks (replaces 'cp -al' on Linux): $ cat > linkcp.py <<EOF - > from __future__ import absolute_import > import sys > from mercurial import pycompat, util > util.copyfiles(pycompat.fsencode(sys.argv[1]),
--- a/tests/test-hashutil.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hashutil.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # Tests to ensure that sha1dc.sha1 is exactly a drop-in for # hashlib.sha1 for our needs. -from __future__ import absolute_import import hashlib import unittest @@ -13,7 +12,7 @@ sha1dc = None -class hashertestsbase(object): +class hashertestsbase: def test_basic_hash(self): h = self.hasher() h.update(b'foo')
--- a/tests/test-help.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-help.t Tue Apr 05 11:09:03 2022 +0200 @@ -1792,7 +1792,6 @@ > > This paragraph is never omitted, too (for extension) > ''' - > from __future__ import absolute_import > from mercurial import commands, help > testtopic = br"""This paragraph is never omitted (for topic). >
--- a/tests/test-hg-parseurl.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hg-parseurl.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import unittest from mercurial.utils import urlutil
--- a/tests/test-hgrc.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgrc.t Tue Apr 05 11:09:03 2022 +0200 @@ -71,7 +71,7 @@ config error at $TESTTMP/hgrc:2: unexpected leading whitespace: x = y [255] - $ "$PYTHON" -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n')" \ + $ "$PYTHON" -c "print('[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n')" \ > > $HGRC $ hg showconfig foo foo.bar=a\nb\nc\nde\nfg
--- a/tests/test-hgweb-auth.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgweb-auth.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - from mercurial import demandimport demandimport.enable()
--- a/tests/test-hgweb-no-path-info.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgweb-no-path-info.t Tue Apr 05 11:09:03 2022 +0200 @@ -15,7 +15,6 @@ summary: test $ cat > request.py <<EOF - > from __future__ import absolute_import > import os > import sys > from mercurial import (
--- a/tests/test-hgweb-no-request-uri.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgweb-no-request-uri.t Tue Apr 05 11:09:03 2022 +0200 @@ -15,7 +15,6 @@ summary: test $ cat > request.py <<EOF - > from __future__ import absolute_import > import os > import sys > from mercurial import (
--- a/tests/test-hgweb-non-interactive.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgweb-non-interactive.t Tue Apr 05 11:09:03 2022 +0200 @@ -7,7 +7,6 @@ $ hg add bar $ hg commit -m "test" $ cat > request.py <<EOF - > from __future__ import absolute_import > import os > import sys > from mercurial import (
--- a/tests/test-hgweb.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgweb.t Tue Apr 05 11:09:03 2022 +0200 @@ -329,7 +329,7 @@ Test the access/error files are opened in append mode - $ "$PYTHON" -c "from __future__ import print_function; print(len(open('access.log', 'rb').readlines()), 'log lines written')" + $ "$PYTHON" -c "print(len(open('access.log', 'rb').readlines()), 'log lines written')" 14 log lines written static file
--- a/tests/test-hgwebdir-gc.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgwebdir-gc.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import os from mercurial.hgweb import hgwebdir_mod
--- a/tests/test-hgwebdir-paths.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hgwebdir-paths.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import os from mercurial import ( hg,
--- a/tests/test-hook.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hook.t Tue Apr 05 11:09:03 2022 +0200 @@ -831,7 +831,6 @@ $ cd "$TESTTMP/b" $ cat > hooktests.py <<EOF - > from __future__ import print_function > from mercurial import ( > error, > pycompat, @@ -979,7 +978,6 @@ Traceback (most recent call last): (py3 !) SyntaxError: * (glob) (py3 !) Traceback (most recent call last): - ImportError: No module named hgext_syntaxerror (no-py3 !) ImportError: No module named 'hgext_syntaxerror' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext_syntaxerror' (py36 !) Traceback (most recent call last): @@ -988,7 +986,6 @@ ImportError: No module named 'hgext_syntaxerror' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext_syntaxerror' (py36 !) Traceback (most recent call last): (py3 !) - HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed (no-py3 !) raise error.HookLoadError( (py38 !) mercurial.error.HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed (py3 !) abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed @@ -1123,7 +1120,6 @@ $ hg id loading pre-identify.npmd hook failed: - abort: No module named repo (no-py3 !) abort: No module named 'repo' (py3 !) [255] @@ -1144,7 +1140,6 @@ $ hg --traceback commit -ma 2>&1 | egrep '^exception|ImportError|ModuleNotFoundError|Traceback|HookLoadError|abort' exception from first failed import attempt: Traceback (most recent call last): - ImportError: No module named somebogusmodule (no-py3 !) ImportError: No module named 'somebogusmodule' (py3 no-py36 !) ModuleNotFoundError: No module named 'somebogusmodule' (py36 !) exception from second failed import attempt: @@ -1158,11 +1153,9 @@ ImportError: No module named 'somebogusmodule' (py3 no-py36 !) ModuleNotFoundError: No module named 'somebogusmodule' (py36 !) Traceback (most recent call last): - ImportError: No module named hgext_importfail (no-py3 !) ImportError: No module named 'hgext_importfail' (py3 no-py36 !) ModuleNotFoundError: No module named 'hgext_importfail' (py36 !) Traceback (most recent call last): - HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed (no-py3 !) raise error.HookLoadError( (py38 !) mercurial.error.HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed (py3 !) abort: precommit.importfail hook is invalid: import of "importfail" failed
--- a/tests/test-http-bad-server.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-http-bad-server.t Tue Apr 05 11:09:03 2022 +0200 @@ -134,13 +134,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob) readline(*) -> (1?) Accept-Encoding* (glob) read limit reached; closing socket @@ -183,13 +176,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob) readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -209,13 +195,6 @@ sendall(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !) write(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !) write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(20) -> Content-Length: 42\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !) readline(24 from ~) -> (*) GET /?cmd=getbundle HTTP* (glob) read limit reached; closing socket readline(~) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n @@ -253,13 +232,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (27) POST /?cmd=batch HTTP/1.1\r\n (glob) readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (41) content-type: application/mercurial-0.1\r\n (glob) @@ -312,7 +284,6 @@ readline(*) -> (2) \r\n (glob) sendall(1 from 160) -> (0) H (py36 !) write(1 from 160) -> (0) H (py3 no-py36 !) - write(1 from 36) -> (0) H (no-py3 !) write limit reached; closing socket $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=capabilities': (glob) Traceback (most recent call last): @@ -348,13 +319,6 @@ sendall(20 from *) -> (0) batch branchmap bund (glob) (py36 !) write(160) -> (20) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(20 from *) -> (0) batch branchmap bund (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(20 from *) -> (0) batch branchmap bund (glob) (no-py3 !) write limit reached; closing socket $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=capabilities': (glob) Traceback (most recent call last): @@ -394,13 +358,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> (568) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (26) GET /?cmd=batch HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -412,10 +369,6 @@ readline(*) -> (2) \r\n (glob) sendall(118 from 159) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: applicat (py36 !) write(118 from 159) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: applicat (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(22 from 41) -> (0) Content-Type: applicat (no-py3 !) write limit reached; closing socket $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=batch': (glob) Traceback (most recent call last): @@ -455,13 +408,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (26) GET /?cmd=batch HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -475,13 +421,6 @@ sendall(24 from 42) -> (0) 96ee1d7354c4ad7372047672 (py36 !) write(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !) write(24 from 42) -> (0) 96ee1d7354c4ad7372047672 (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(20) -> Content-Length: 42\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(24 from 42) -> (0) 96ee1d7354c4ad7372047672 (no-py3 !) write limit reached; closing socket $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=batch': (glob) Traceback (most recent call last): @@ -522,13 +461,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (26) GET /?cmd=batch HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -542,13 +474,6 @@ sendall(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !) write(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !) write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(20) -> Content-Length: 42\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !) readline(~) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -560,10 +485,6 @@ readline(*) -> (2) \r\n (glob) sendall(129 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercuri (py36 !) write(129 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercuri (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(33 from 41) -> (0) Content-Type: application/mercuri (no-py3 !) write limit reached; closing socket $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob) Traceback (most recent call last): @@ -638,13 +559,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (26) GET /?cmd=batch HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -658,13 +572,6 @@ sendall(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !) write(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !) write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(20) -> Content-Length: 42\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !) readline(~) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -676,12 +583,6 @@ readline(*) -> (2) \r\n (glob) sendall(167 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py36 !) write(167 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.2\r\n (no-py3 !) - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2 from 2) -> (0) \r\n (no-py3 !) write limit reached; closing socket $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob) Traceback (most recent call last): @@ -718,13 +619,6 @@ sendall(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py36 !) write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: *\r\n\r\n (glob) (py3 no-py36 !) write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(21) -> Content-Length: *\r\n (glob) (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(*) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=* unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (glob) (no-py3 !) readline(~) -> (26) GET /?cmd=batch HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -737,13 +631,6 @@ sendall(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py36 !) sendall(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !) write(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !) - write(20) -> Content-Length: 42\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !) readline(~) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n readline(*) -> (27) Accept-Encoding: identity\r\n (glob) readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob) @@ -758,15 +645,6 @@ sendall(9) -> 4\r\nnone\r\n (py36 !) sendall(9 from 9) -> (0) 4\r\nHG20\r\n (py36 !) write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !) - write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !) - write(23) -> Server: badhttpserver\r\n (no-py3 !) - write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !) - write(41) -> Content-Type: application/mercurial-0.2\r\n (no-py3 !) - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) - write(6) -> 1\\r\\n\x04\\r\\n (esc) (no-py3 !) - write(9) -> 4\r\nnone\r\n (no-py3 !) - write(9 from 9) -> (0) 4\r\nHG20\r\n (no-py3 !) write limit reached; closing socket $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob) Traceback (most recent call last): @@ -786,7 +664,6 @@ $ hg clone http://localhost:$HGPORT/ clone requesting all changes abort: HTTP request error (incomplete response) (py3 !) - abort: HTTP request error (incomplete response; expected 4 bytes got 3) (no-py3 !) (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) [255] @@ -808,9 +685,6 @@ $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -11 readline(~) -> (2) \r\n (py3 !) write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !) - write(41) -> Content-Type: application/mercurial-0.2\r\n (no-py3 !) - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) write(6) -> 1\\r\\n\x04\\r\\n (esc) write(9) -> 4\r\nnone\r\n write(6 from 9) -> (0) 4\r\nHG2 @@ -834,7 +708,6 @@ $ hg clone http://localhost:$HGPORT/ clone requesting all changes abort: HTTP request error (incomplete response) (py3 !) - abort: HTTP request error (incomplete response; expected 4 bytes got 3) (no-py3 !) (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) [255] @@ -858,8 +731,6 @@ readline(~) -> (2) \r\n (py3 !) write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !) write(41) -> Content-Type: application/mercurial-0.2\r\n - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) write(6) -> 1\\r\\n\x04\\r\\n (esc) write(9) -> 4\r\nnone\r\n write(9) -> 4\r\nHG20\r\n @@ -907,8 +778,6 @@ readline(~) -> (2) \r\n (py3 !) write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !) write(41) -> Content-Type: application/mercurial-0.2\r\n - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) write(6) -> 1\\r\\n\x04\\r\\n (esc) write(9) -> 4\r\nnone\r\n write(9) -> 4\r\nHG20\r\n @@ -958,8 +827,6 @@ readline(~) -> (2) \r\n (py3 !) write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !) write(41) -> Content-Type: application/mercurial-0.2\r\n - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) write(6) -> 1\\r\\n\x04\\r\\n (esc) write(9) -> 4\r\nnone\r\n write(9) -> 4\r\nHG20\r\n @@ -1013,8 +880,6 @@ readline(~) -> (2) \r\n (py3 !) write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !) write(41) -> Content-Type: application/mercurial-0.2\r\n - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) write(6) -> 1\\r\\n\x04\\r\\n (esc) write(9) -> 4\r\nnone\r\n write(9) -> 4\r\nHG20\r\n @@ -1044,7 +909,6 @@ transaction abort! rollback completed abort: HTTP request error (incomplete response) (py3 !) - abort: HTTP request error (incomplete response; expected 466 bytes got 7) (no-py3 !) (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) [255] @@ -1071,7 +935,6 @@ $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -15 write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !) write(28) -> Transfer-Encoding: chunked\r\n - write(2) -> \r\n (no-py3 !) write(6) -> 1\\r\\n\x04\\r\\n (esc) write(9) -> 4\r\nnone\r\n write(9) -> 4\r\nHG20\r\n @@ -1130,8 +993,6 @@ readline(~) -> (2) \r\n (py3 !) write(167) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !) write(41) -> Content-Type: application/mercurial-0.2\r\n - write(28) -> Transfer-Encoding: chunked\r\n (no-py3 !) - write(2) -> \r\n (no-py3 !) write(6) -> 1\\r\\n\x04\\r\\n (esc) write(9) -> 4\r\nnone\r\n write(9) -> 4\r\nHG20\r\n @@ -1165,7 +1026,6 @@ transaction abort! rollback completed abort: HTTP request error (incomplete response) (py3 !) - abort: HTTP request error (incomplete response; expected 32 bytes got 9) (no-py3 !) (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) [255]
--- a/tests/test-hybridencode.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-hybridencode.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import unittest from mercurial import store
--- a/tests/test-impexp-branch.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-impexp-branch.t Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ $ echo 'strip =' >> $HGRCPATH $ cat >findbranch.py <<EOF - > from __future__ import absolute_import > import re > import sys >
--- a/tests/test-import.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-import.t Tue Apr 05 11:09:03 2022 +0200 @@ -71,7 +71,6 @@ regardless of the commit message in the patch) $ cat > dummypatch.py <<EOF - > from __future__ import print_function > print('patching file a') > open('a', 'wb').write(b'line2\n') > EOF
--- a/tests/test-imports-checker.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-imports-checker.t Tue Apr 05 11:09:03 2022 +0200 @@ -16,74 +16,61 @@ $ touch testpackage/__init__.py $ cat > testpackage/multiple.py << EOF - > from __future__ import absolute_import > import os, sys > EOF $ cat > testpackage/unsorted.py << EOF - > from __future__ import absolute_import > import sys > import os > EOF $ cat > testpackage/stdafterlocal.py << EOF - > from __future__ import absolute_import > from . import unsorted > import os > EOF $ cat > testpackage/requirerelative.py << EOF - > from __future__ import absolute_import > import testpackage.unsorted > EOF $ cat > testpackage/importalias.py << EOF - > from __future__ import absolute_import > import ui > EOF $ cat > testpackage/relativestdlib.py << EOF - > from __future__ import absolute_import > from .. import os > EOF $ cat > testpackage/stdlibfrom.py << EOF - > from __future__ import absolute_import > from collections import abc > EOF $ cat > testpackage/symbolimport.py << EOF - > from __future__ import absolute_import > from .unsorted import foo > EOF $ cat > testpackage/latesymbolimport.py << EOF - > from __future__ import absolute_import > from . import unsorted > from mercurial.node import hex > EOF $ cat > testpackage/multiplegroups.py << EOF - > from __future__ import absolute_import > from . import unsorted > from . import more > EOF $ mkdir testpackage/subpackage $ cat > testpackage/subpackage/levelpriority.py << EOF - > from __future__ import absolute_import > from . import foo > from .. import parent > EOF $ touch testpackage/subpackage/foo.py $ cat > testpackage/subpackage/__init__.py << EOF - > from __future__ import absolute_import > from . import levelpriority # should not cause cycle > EOF $ cat > testpackage/subpackage/localimport.py << EOF - > from __future__ import absolute_import > from . import foo > def bar(): > # should not cause "higher-level import should come first" @@ -94,17 +81,14 @@ > EOF $ cat > testpackage/importmodulefromsub.py << EOF - > from __future__ import absolute_import > from .subpackage import foo # not a "direct symbol import" > EOF $ cat > testpackage/importsymbolfromsub.py << EOF - > from __future__ import absolute_import > from .subpackage import foo, nonmodule > EOF $ cat > testpackage/sortedentries.py << EOF - > from __future__ import absolute_import > from . import ( > foo, > bar, @@ -112,12 +96,10 @@ > EOF $ cat > testpackage/importfromalias.py << EOF - > from __future__ import absolute_import > from . import ui > EOF $ cat > testpackage/importfromrelative.py << EOF - > from __future__ import absolute_import > from testpackage.unsorted import foo > EOF @@ -125,7 +107,6 @@ $ touch testpackage2/__init__.py $ cat > testpackage2/latesymbolimport.py << EOF - > from __future__ import absolute_import > from testpackage import unsorted > from mercurial.node import hex > EOF @@ -137,29 +118,28 @@ $ touch email/__init__.py $ touch email/errors.py $ cat > email/utils.py << EOF - > from __future__ import absolute_import > from . import errors > EOF $ "$PYTHON" "$import_checker" testpackage*/*.py testpackage/subpackage/*.py \ > email/*.py - testpackage/importalias.py:2: ui module must be "as" aliased to uimod - testpackage/importfromalias.py:2: ui from testpackage must be "as" aliased to uimod - testpackage/importfromrelative.py:2: import should be relative: testpackage.unsorted - testpackage/importfromrelative.py:2: direct symbol import foo from testpackage.unsorted - testpackage/importsymbolfromsub.py:2: direct symbol import nonmodule from testpackage.subpackage - testpackage/latesymbolimport.py:3: symbol import follows non-symbol import: mercurial.node - testpackage/multiple.py:2: multiple imported names: os, sys - testpackage/multiplegroups.py:3: multiple "from . import" statements - testpackage/relativestdlib.py:2: relative import of stdlib module - testpackage/requirerelative.py:2: import should be relative: testpackage.unsorted - testpackage/sortedentries.py:2: imports from testpackage not lexically sorted: bar < foo - testpackage/stdafterlocal.py:3: stdlib import "os" follows local import: testpackage - testpackage/stdlibfrom.py:2: direct symbol import abc from collections - testpackage/subpackage/levelpriority.py:3: higher-level import should come first: testpackage - testpackage/subpackage/localimport.py:7: multiple "from .. import" statements - testpackage/subpackage/localimport.py:8: import should be relative: testpackage.subpackage.levelpriority - testpackage/symbolimport.py:2: direct symbol import foo from testpackage.unsorted - testpackage/unsorted.py:3: imports not lexically sorted: os < sys - testpackage2/latesymbolimport.py:3: symbol import follows non-symbol import: mercurial.node + testpackage/importalias.py:1: ui module must be "as" aliased to uimod + testpackage/importfromalias.py:1: ui from testpackage must be "as" aliased to uimod + testpackage/importfromrelative.py:1: import should be relative: testpackage.unsorted + testpackage/importfromrelative.py:1: direct symbol import foo from testpackage.unsorted + testpackage/importsymbolfromsub.py:1: direct symbol import nonmodule from testpackage.subpackage + testpackage/latesymbolimport.py:2: symbol import follows non-symbol import: mercurial.node + testpackage/multiple.py:1: multiple imported names: os, sys + testpackage/multiplegroups.py:2: multiple "from . import" statements + testpackage/relativestdlib.py:1: relative import of stdlib module + testpackage/requirerelative.py:1: import should be relative: testpackage.unsorted + testpackage/sortedentries.py:1: imports from testpackage not lexically sorted: bar < foo + testpackage/stdafterlocal.py:2: stdlib import "os" follows local import: testpackage + testpackage/stdlibfrom.py:1: direct symbol import abc from collections + testpackage/subpackage/levelpriority.py:2: higher-level import should come first: testpackage + testpackage/subpackage/localimport.py:6: multiple "from .. import" statements + testpackage/subpackage/localimport.py:7: import should be relative: testpackage.subpackage.levelpriority + testpackage/symbolimport.py:1: direct symbol import foo from testpackage.unsorted + testpackage/unsorted.py:2: imports not lexically sorted: os < sys + testpackage2/latesymbolimport.py:2: symbol import follows non-symbol import: mercurial.node [1]
--- a/tests/test-inherit-mode.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-inherit-mode.t Tue Apr 05 11:09:03 2022 +0200 @@ -10,7 +10,6 @@ $ cd dir $ cat >printmodes.py <<EOF - > from __future__ import absolute_import, print_function > import os > import sys > @@ -31,7 +30,6 @@ > EOF $ cat >mode.py <<EOF - > from __future__ import absolute_import, print_function > import os > import sys > print('%05o' % os.lstat(sys.argv[1]).st_mode)
--- a/tests/test-install.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-install.t Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ checking encoding (ascii)... checking Python executable (*) (glob) checking Python implementation (*) (glob) - checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !) @@ -67,7 +66,6 @@ checking encoding (ascii)... checking Python executable (*) (glob) checking Python implementation (*) (glob) - checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !) @@ -117,7 +115,6 @@ checking encoding (ascii)... checking Python executable (*) (glob) checking Python implementation (*) (glob) - checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !) @@ -147,7 +144,6 @@ checking encoding (ascii)... checking Python executable (*) (glob) checking Python implementation (*) (glob) - checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !)
--- a/tests/test-keyword.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-keyword.t Tue Apr 05 11:09:03 2022 +0200 @@ -1412,7 +1412,6 @@ $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new $ mv $HGRCPATH.new $HGRCPATH - >>> from __future__ import print_function >>> from hgclient import check, readchannel, runcommand >>> @check ... def check(server):
--- a/tests/test-largefiles-cache.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-largefiles-cache.t Tue Apr 05 11:09:03 2022 +0200 @@ -96,7 +96,6 @@ $ cat > ls-l.py <<EOF > #!$PYTHON - > from __future__ import absolute_import, print_function > import os > import sys > path = sys.argv[1]
--- a/tests/test-largefiles-small-disk.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-largefiles-small-disk.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ Test how largefiles abort in case the disk runs full $ cat > criple.py <<EOF - > from __future__ import absolute_import > import errno > import os > import shutil
--- a/tests/test-lfs-pointer.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-lfs-pointer.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - # Import something from Mercurial, so the module loader gets initialized. from mercurial import pycompat
--- a/tests/test-lfs-serve-access.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-lfs-serve-access.t Tue Apr 05 11:09:03 2022 +0200 @@ -355,7 +355,6 @@ $LOCALIP - - [$ERRDATE$] HG error: super(badstore, self).download(oid, src, contentlength) $LOCALIP - - [$ERRDATE$] HG error: raise LfsCorruptionError( (glob) (py38 !) $LOCALIP - - [$ERRDATE$] HG error: _(b'corrupt remote lfs object: %s') % oid (glob) (no-py38 !) - $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (no-py3 !) $LOCALIP - - [$ERRDATE$] HG error: hgext.lfs.blobstore.LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (py3 !) $LOCALIP - - [$ERRDATE$] HG error: (glob) $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob) @@ -367,7 +366,6 @@ handled = wireprotoserver.handlewsgirequest( (py38 !) return _processbasictransfer( (py38 !) rctx, req, res, self.check_perm (no-py38 !) - return func(*(args + a), **kw) (no-py3 !) rctx.repo, req, res, lambda perm: checkperm(rctx, req, perm) (no-py38 !) res.setbodybytes(localstore.read(oid)) blob = self._read(self.vfs, oid, verify) @@ -381,7 +379,6 @@ $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, b'dummy content') (glob) $LOCALIP - - [$ERRDATE$] HG error: raise LfsCorruptionError( (glob) (py38 !) $LOCALIP - - [$ERRDATE$] HG error: hint=_(b'run hg verify'), (glob) (no-py38 !) - $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (no-py3 !) $LOCALIP - - [$ERRDATE$] HG error: hgext.lfs.blobstore.LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (py3 !) $LOCALIP - - [$ERRDATE$] HG error: (glob)
--- a/tests/test-lfs-serve.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-lfs-serve.t Tue Apr 05 11:09:03 2022 +0200 @@ -107,7 +107,6 @@ $ cd client $ echo 'non-lfs' > nonlfs.txt - >>> from __future__ import absolute_import >>> from hgclient import check, readchannel, runcommand >>> @check ... def diff(server): @@ -240,7 +239,6 @@ $ cd ../cmdserve_client3 - >>> from __future__ import absolute_import >>> from hgclient import check, readchannel, runcommand >>> @check ... def addrequirement(server): @@ -355,7 +353,6 @@ $ mv $HGRCPATH $HGRCPATH.tmp $ cp $HGRCPATH.orig $HGRCPATH - >>> from __future__ import absolute_import >>> from hgclient import bprint, check, readchannel, runcommand, stdout >>> @check ... def checkflags(server): @@ -404,7 +401,6 @@ > lfs = ! > EOF - >>> from __future__ import absolute_import, print_function >>> from hgclient import bprint, check, readchannel, runcommand, stdout >>> @check ... def checkflags2(server):
--- a/tests/test-linelog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-linelog.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import difflib import random import unittest
--- a/tests/test-linerange.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-linerange.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import unittest from mercurial import error, mdiff from mercurial.utils import stringutil
--- a/tests/test-lock.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-lock.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import copy import errno import tempfile @@ -37,7 +35,7 @@ return super(lockwrapper, self)._getpid() + self._pidoffset -class teststate(object): +class teststate: def __init__(self, testcase, dir, pidoffset=0): self._testcase = testcase self._acquirecalled = False
--- a/tests/test-log-exthook.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-log-exthook.t Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ ------------------------------------------- $ cat > $TESTTMP/logexthook.py <<EOF - > from __future__ import absolute_import > import codecs > from mercurial import ( > commands,
--- a/tests/test-log.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-log.t Tue Apr 05 11:09:03 2022 +0200 @@ -2451,7 +2451,6 @@ $ cat > ../names.py <<EOF > """A small extension to test adding arbitrary names to a repo""" - > from __future__ import absolute_import > from mercurial import namespaces > > def reposetup(ui, repo):
--- a/tests/test-logtoprocess.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-logtoprocess.t Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ $ hg init $ cat > $TESTTMP/foocommand.py << EOF - > from __future__ import absolute_import > from mercurial import registrar > cmdtable = {} > command = registrar.command(cmdtable)
--- a/tests/test-lrucachedict.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-lrucachedict.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import unittest import silenttestrunner
--- a/tests/test-mac-packages.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-mac-packages.t Tue Apr 05 11:09:03 2022 +0200 @@ -39,8 +39,8 @@ ./Library/Python/2.7/site-packages/mercurial/pure/bdiff.pyo 100644 0/0 $ grep zsh/site-functions/_hg boms.txt | cut -d ' ' -f 1,2,3 ./usr/local/share/zsh/site-functions/_hg 100644 0/0 - $ grep hg-completion.bash boms.txt | cut -d ' ' -f 1,2,3 - ./usr/local/hg/contrib/hg-completion.bash 100644 0/0 + $ grep bash-completion/completions/hg boms.txt | cut -d ' ' -f 1,2,3 + ./usr/local/share/bash-completion-completions/hg 100644 0/0 $ egrep 'man[15]' boms.txt | cut -d ' ' -f 1,2,3 ./usr/local/share/man/man1 40755 0/0 ./usr/local/share/man/man1/chg.1 100644 0/0
--- a/tests/test-manifest.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-manifest.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import binascii import itertools import silenttestrunner @@ -76,7 +74,7 @@ ) -class basemanifesttests(object): +class basemanifesttests: def parsemanifest(self, text): raise NotImplementedError('parsemanifest not implemented by test case')
--- a/tests/test-match.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-match.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import unittest import silenttestrunner
--- a/tests/test-mdiff.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-mdiff.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,3 @@ -from __future__ import absolute_import -from __future__ import print_function - import unittest from mercurial import mdiff
--- a/tests/test-merge-halt.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-merge-halt.t Tue Apr 05 11:09:03 2022 +0200 @@ -210,6 +210,6 @@ merge halted after failed merge (see hg resolve) [240] $ hg shelve --list - default (* ago) changes to: foo (glob) + default (*s ago) * changes to: foo (glob) $ hg unshelve --abort unshelve of 'default' aborted
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-merge-partial-tool.t Tue Apr 05 11:09:03 2022 +0200 @@ -0,0 +1,241 @@ +Test support for partial-resolution tools + +Create a tool that resolves conflicts after line 5 by simply dropping those +lines (even if there are no conflicts there) + $ cat >> "$TESTTMP/head.sh" <<'EOF' + > #!/bin/sh + > for f in "$@"; do + > head -5 $f > tmp + > mv -f tmp $f + > done + > EOF + $ chmod +x "$TESTTMP/head.sh" +...and another tool that keeps only the last 5 lines instead of the first 5. + $ cat >> "$TESTTMP/tail.sh" <<'EOF' + > #!/bin/sh + > for f in "$@"; do + > tail -5 $f > tmp + > mv -f tmp $f + > done + > EOF + $ chmod +x "$TESTTMP/tail.sh" + +Set up both tools to run on all patterns (the default), and let the `tail` tool +run after the `head` tool, which means it will have no effect (we'll override it +to test order later) + $ cat >> "$HGRCPATH" <<EOF + > [partial-merge-tools] + > head.executable=$TESTTMP/head.sh + > tail.executable=$TESTTMP/tail.sh + > tail.order=1 + > EOF + + $ make_commit() { + > echo "$@" | xargs -n1 > file + > hg add file 2> /dev/null + > hg ci -m "$*" + > } + + +Let a partial-resolution tool resolve some conflicts and leave other conflicts +for the regular merge tool (:merge3 here) + + $ hg init repo + $ cd repo + $ make_commit a b c d e f + $ make_commit a b2 c d e f2 + $ hg up 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ make_commit a b3 c d e f3 + created new head + $ hg merge 1 -t :merge3 + merging file + warning: conflicts while merging file! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] + $ cat file + a + <<<<<<< working copy: e11a49d4b620 - test: a b3 c d e f3 + b3 + ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f + b + ======= + b2 + >>>>>>> merge rev: fbc096a40cc5 - test: a b2 c d e f2 + c + d + e + + +With premerge=keep, the partial-resolution tools runs before and doesn't see +the conflict markers + + $ hg up -C 2 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cat >> .hg/hgrc <<EOF + > [merge-tools] + > my-local.executable = cat + > my-local.args = $local + > my-local.premerge = keep-merge3 + > EOF + $ hg merge 1 -t my-local + merging file + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ cat file + a + <<<<<<< working copy: e11a49d4b620 - test: a b3 c d e f3 + b3 + ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f + b + ======= + b2 + >>>>>>> merge rev: fbc096a40cc5 - test: a b2 c d e f2 + c + d + e + + +When a partial-resolution tool resolves all conflicts, the resolution should +be recorded and the regular merge tool should not be invoked for the file. + + $ hg up -C 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ make_commit a b c d e f2 + created new head + $ hg up 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ make_commit a b c d e f3 + created new head + $ hg merge 3 -t false + merging file + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ cat file + a + b + c + d + e + + +Only tools whose patterns match are run. We make `head` not match here, so +only `tail` should run + + $ hg up -C 4 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 3 -t :merge3 --config partial-merge-tools.head.patterns=other + merging file + warning: conflicts while merging file! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] + $ cat file + b + c + d + e + <<<<<<< working copy: d57edaa6e21a - test: a b c d e f3 + f3 + ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f + f + ======= + f2 + >>>>>>> merge rev: 8c217da987be - test: a b c d e f2 + + +If there are several matching tools, they are run in requested order. We move +`head` after `tail` in order here so it has no effect (the conflict in "f" thus +remains). + + $ hg up -C 4 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 3 -t :merge3 --config partial-merge-tools.head.order=2 + merging file + warning: conflicts while merging file! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] + $ cat file + b + c + d + e + <<<<<<< working copy: d57edaa6e21a - test: a b c d e f3 + f3 + ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f + f + ======= + f2 + >>>>>>> merge rev: 8c217da987be - test: a b c d e f2 + + +When using "nomerge" tools (e.g. `:other`), the partial-resolution tools +should not be run. + + $ hg up -C 4 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 3 -t :other + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ cat file + a + b + c + d + e + f2 + + +If a partial-resolution tool resolved some conflict and simplemerge can +merge the rest, then the regular merge tool should not be used. Here we merge +"a b c d e3 f3" with "a b2 c d e f2". The `head` tool resolves the conflict in +"f" and the internal simplemerge merges the remaining changes in "b" and "e". + + $ hg up -C 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ make_commit a b c d e3 f3 + created new head + $ hg merge 1 -t false + merging file + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ cat file + a + b2 + c + d + e3 + +Test that arguments get passed as expected. + + $ cat >> "$TESTTMP/log-args.sh" <<'EOF' + > #!/bin/sh + > echo "$@" > args.log + > EOF + $ chmod +x "$TESTTMP/log-args.sh" + $ cat >> "$HGRCPATH" <<EOF + > [partial-merge-tools] + > log-args.executable=$TESTTMP/log-args.sh + > EOF + $ hg up -C 2 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 1 + merging file + warning: conflicts while merging file! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] + $ cat args.log + */hgmerge-*/file~local */hgmerge-*/file~base */hgmerge-*/file~other (glob) + $ hg up -C 2 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 1 --config partial-merge-tools.log-args.args='--other $other $base --foo --local $local --also-other $other' + merging file + warning: conflicts while merging file! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] + $ cat args.log + --other */hgmerge-*/file~other */hgmerge-*/file~base --foo --local */hgmerge-*/file~local --also-other */hgmerge-*/file~other (glob)
--- a/tests/test-merge-symlinks.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-merge-symlinks.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ $ cat > echo.py <<EOF > #!$PYTHON - > from __future__ import absolute_import, print_function > import os > import sys > try:
--- a/tests/test-merge1.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-merge1.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ $ cat <<EOF > merge - > from __future__ import print_function > import sys, os > > try: @@ -354,7 +353,6 @@ trigger it. If you see flakyness here, there is a race. $ cat > $TESTTMP/abort.py <<EOF - > from __future__ import absolute_import > # emulate aborting before "recordupdates()". in this case, files > # are changed without updating dirstate > from mercurial import (
--- a/tests/test-minifileset.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-minifileset.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,3 @@ -from __future__ import absolute_import -from __future__ import print_function - from mercurial import minifileset
--- a/tests/test-minirst.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-minirst.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function from mercurial import minirst from mercurial.utils import stringutil
--- a/tests/test-mq-missingfiles.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-mq-missingfiles.t Tue Apr 05 11:09:03 2022 +0200 @@ -5,10 +5,7 @@ $ cat > writelines.py <<EOF > import sys - > if sys.version_info[0] >= 3: - > encode = lambda x: x.encode('utf-8').decode('unicode_escape').encode('utf-8') - > else: - > encode = lambda x: x.decode('string_escape') + > encode = lambda x: x.encode('utf-8').decode('unicode_escape').encode('utf-8') > path = sys.argv[1] > args = sys.argv[2:] > assert (len(args) % 2) == 0
--- a/tests/test-mq-qimport.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-mq-qimport.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,9 +1,6 @@ $ cat > writelines.py <<EOF > import sys - > if sys.version_info[0] >= 3: - > encode = lambda x: x.encode('utf-8').decode('unicode_escape').encode('utf-8') - > else: - > encode = lambda x: x.decode('string_escape') + > encode = lambda x: x.encode('utf-8').decode('unicode_escape').encode('utf-8') > path = sys.argv[1] > args = sys.argv[2:] > assert (len(args) % 2) == 0
--- a/tests/test-narrow-clone-non-narrow-server.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-narrow-clone-non-narrow-server.t Tue Apr 05 11:09:03 2022 +0200 @@ -20,7 +20,6 @@ Verify that narrow is advertised in the bundle2 capabilities: $ cat >> unquote.py <<EOF - > from __future__ import print_function > import sys > if sys.version[0] == '3': > import urllib.parse as up
--- a/tests/test-notify-changegroup.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-notify-changegroup.t Tue Apr 05 11:09:03 2022 +0200 @@ -40,7 +40,7 @@ $ hg --traceback --cwd b push ../a 2>&1 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ - > "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' + > "$PYTHON" -c 'import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' pushing to ../a searching for changes adding changesets @@ -95,7 +95,7 @@ $ hg --config notify.sources=unbundle --cwd a unbundle ../test.hg 2>&1 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ - > "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' + > "$PYTHON" -c 'import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' adding changesets adding manifests adding file changes @@ -172,7 +172,7 @@ $ hg --traceback --cwd b --config notify.fromauthor=True push ../a 2>&1 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ - > "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' + > "$PYTHON" -c 'import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' pushing to ../a searching for changes adding changesets
--- a/tests/test-notify.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-notify.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,16 +1,14 @@ $ cat > $TESTTMP/filter.py <<EOF - > from __future__ import absolute_import, print_function > import io > import re > import sys - > if sys.version_info[0] >= 3: - > sys.stdout = io.TextIOWrapper( - > sys.stdout.buffer, - > sys.stdout.encoding, - > sys.stdout.errors, - > newline="\n", - > line_buffering=sys.stdout.line_buffering, - > ) + > sys.stdout = io.TextIOWrapper( + > sys.stdout.buffer, + > sys.stdout.encoding, + > sys.stdout.errors, + > newline="\n", + > line_buffering=sys.stdout.line_buffering, + > ) > print(re.sub("\n[ \t]", " ", sys.stdin.read()), end="") > EOF @@ -469,7 +467,6 @@ Content-Transfer-Encoding: 8bit X-Test: foo Date: * (glob) - Subject: \xc3\xa0... (esc) (no-py3 !) Subject: =?utf-8?b?w6AuLi4=?= (py3 !) From: test@test.com X-Hg-Notification: changeset 0f25f9c22b4c
--- a/tests/test-obsolete.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-obsolete.t Tue Apr 05 11:09:03 2022 +0200 @@ -1465,7 +1465,6 @@ Test heads computation on pending index changes with obsolescence markers $ cd .. $ cat >$TESTTMP/test_extension.py << EOF - > from __future__ import absolute_import > from mercurial.i18n import _ > from mercurial import cmdutil, pycompat, registrar > from mercurial.utils import stringutil @@ -1499,7 +1498,6 @@ bookmarks change $ cd .. $ cat >$TESTTMP/test_extension.py << EOF - > from __future__ import absolute_import, print_function > import weakref > from mercurial import ( > bookmarks,
--- a/tests/test-pager.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-pager.t Tue Apr 05 11:09:03 2022 +0200 @@ -411,7 +411,6 @@ Environment variables like LESS and LV are set automatically: $ cat > $TESTTMP/printlesslv.py <<EOF - > from __future__ import absolute_import > import os > import sys > sys.stdin.read()
--- a/tests/test-parseindex.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-parseindex.t Tue Apr 05 11:09:03 2022 +0200 @@ -26,7 +26,6 @@ summary: change foo $ cat >> test.py << EOF - > from __future__ import print_function > from mercurial import changelog, node, pycompat, vfs > > class singlebyteread(object): @@ -75,7 +74,6 @@ $ cd a $ "$PYTHON" <<EOF - > from __future__ import print_function > from mercurial import changelog, vfs > cl = changelog.changelog(vfs.vfs(b'.hg/store')) > print('good heads:') @@ -177,7 +175,6 @@ 1 2 1 -1 base 66 65 66 1.01538 66 0 0.00000 $ cat <<EOF > test.py - > from __future__ import print_function > import sys > from mercurial import changelog, pycompat, vfs > cl = changelog.changelog(vfs.vfs(pycompat.fsencode(sys.argv[1])))
--- a/tests/test-parseindex2.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-parseindex2.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ It also checks certain aspects of the parsers module as a whole. """ -from __future__ import absolute_import, print_function import os import struct
--- a/tests/test-patch.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-patch.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ $ cat > patchtool.py <<EOF - > from __future__ import absolute_import, print_function > import sys > print('Using custom patch') > if '--binary' in sys.argv:
--- a/tests/test-patchbomb.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-patchbomb.t Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ --===+[0-9]+=+$ -> --===*= (glob) $ cat > prune-blank-after-boundary.py <<EOF - > from __future__ import absolute_import, print_function > import sys > skipblank = False > trim = lambda x: x.strip(' \r\n') @@ -514,7 +513,6 @@ X-Mercurial-Series-Id: <f81ef97829467e868fc4.240@test-hostname> User-Agent: Mercurial-patchbomb/* (glob) Date: Thu, 01 Jan 1970 00:04:00 +0000 - From: Q <quux> (no-py3 !) From: =?iso-8859-1?q?Q?= <quux> (py3 !) To: foo Cc: bar @@ -2400,9 +2398,6 @@ User-Agent: Mercurial-patchbomb/* (glob) Date: Tue, 01 Jan 1980 00:01:00 +0000 From: quux - To: spam <spam>, eggs, toast (no-py3 !) - Cc: foo, bar@example.com, "A, B <>" <a@example.com> (no-py3 !) - Bcc: "Quux, A." <quux> (no-py3 !) To: =?iso-8859-1?q?spam?= <spam>, eggs, toast (py3 !) Cc: foo, bar@example.com, =?iso-8859-1?q?A=2C_B_=3C=3E?= <a@example.com> (py3 !) Bcc: =?iso-8859-1?q?Quux=2C_A=2E?= <quux> (py3 !) @@ -2722,7 +2717,6 @@ MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable - Subject: [PATCH 2 of 6] \xe7a (esc) (no-py3 !) Subject: =?utf-8?b?W1BBVENIIDIgb2YgNl0gw6dh?= (py3 !) X-Mercurial-Node: f81ef97829467e868fc405fccbcfa66217e4d3e6 X-Mercurial-Series-Index: 2
--- a/tests/test-pathencode.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-pathencode.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # that have proven likely to expose bugs and divergent behavior in # different encoding implementations. -from __future__ import absolute_import, print_function import binascii import collections @@ -67,7 +66,7 @@ counts[c] += 1 for c in '\r/\n': counts.pop(c, None) - t = sum(pycompat.itervalues(counts)) / 100.0 + t = sum(counts.values()) / 100.0 fp.write('probtable = (') for i, (k, v) in enumerate( sorted(counts.items(), key=lambda x: x[1], reverse=True)
--- a/tests/test-profile.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-profile.t Tue Apr 05 11:09:03 2022 +0200 @@ -132,7 +132,6 @@ profiler extension could be loaded before other extensions $ cat > fooprof.py <<EOF - > from __future__ import absolute_import > import contextlib > import sys > @contextlib.contextmanager @@ -147,7 +146,6 @@ > EOF $ cat > otherextension.py <<EOF - > from __future__ import absolute_import > def extsetup(ui): > ui.write(b'otherextension: loaded\n') > EOF
--- a/tests/test-progress.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-progress.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ $ cat > loop.py <<EOF - > from __future__ import absolute_import > import time > from mercurial import commands, registrar >
--- a/tests/test-propertycache.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-propertycache.py Tue Apr 05 11:09:03 2022 +0200 @@ -4,7 +4,6 @@ property cache of both localrepo and repoview to prevent regression.""" -from __future__ import absolute_import, print_function import os import subprocess
--- a/tests/test-pull-network.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-pull-network.t Tue Apr 05 11:09:03 2022 +0200 @@ -90,12 +90,12 @@ It's tricky to make file:// URLs working on every platform with regular shell commands. - $ URL=`"$PYTHON" -c "from __future__ import print_function; import os; print('file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"` + $ URL=`"$PYTHON" -c "import os; print('file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"` $ hg pull -q "$URL" abort: file:// URLs can only refer to localhost [255] - $ URL=`"$PYTHON" -c "from __future__ import print_function; import os; print('file://localhost' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"` + $ URL=`"$PYTHON" -c "import os; print('file://localhost' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"` $ hg pull -q "$URL" SEC: check for unsafe ssh url
--- a/tests/test-rebase-dest.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-rebase-dest.t Tue Apr 05 11:09:03 2022 +0200 @@ -81,7 +81,6 @@ $ cd $TESTTMP $ cat >> $TESTTMP/maprevset.py <<EOF - > from __future__ import absolute_import > from mercurial import registrar, revset, revsetlang, smartset > revsetpredicate = registrar.revsetpredicate() > cache = {}
--- a/tests/test-rebase-scenario-global.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-rebase-scenario-global.t Tue Apr 05 11:09:03 2022 +0200 @@ -949,7 +949,6 @@ $ hg init tr-state $ cd tr-state $ cat > $TESTTMP/wraprebase.py <<EOF - > from __future__ import absolute_import > from mercurial import extensions > def _rebase(orig, ui, repo, *args, **kwargs): > with repo.wlock():
--- a/tests/test-relink.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-relink.t Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ > } $ cat > arelinked.py <<EOF - > from __future__ import absolute_import, print_function > import os > import sys > from mercurial import (
--- a/tests/test-remotefilelog-corrupt-cache.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-remotefilelog-corrupt-cache.t Tue Apr 05 11:09:03 2022 +0200 @@ -38,7 +38,6 @@ $ chmod u+w $CACHEDIR/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/1406e74118627694268417491f018a4a883152f0 $ echo x > $CACHEDIR/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/1406e74118627694268417491f018a4a883152f0 $ hg up tip 2>&1 | egrep "^[^ ].*unexpected remotefilelog" - abort: unexpected remotefilelog header: illegal format (no-py3 !) hgext.remotefilelog.shallowutil.BadRemotefilelogHeader: unexpected remotefilelog header: illegal format (py3 !) Verify detection and remediation when remotefilelog.validatecachelog is set
--- a/tests/test-remotefilelog-datapack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-remotefilelog-datapack.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import absolute_import, print_function import hashlib import os @@ -36,7 +35,7 @@ ) -class datapacktestsbase(object): +class datapacktestsbase: def __init__(self, datapackreader, paramsavailable): self.datapackreader = datapackreader self.paramsavailable = paramsavailable
--- a/tests/test-remotefilelog-histpack.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-remotefilelog-histpack.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import absolute_import import hashlib import os
--- a/tests/test-rename.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-rename.t Tue Apr 05 11:09:03 2022 +0200 @@ -682,7 +682,6 @@ "hg cp" does not preserve the mtime, so it should be newer than the 2009 timestamp. $ hg cp -q mtime mtime_cp - >>> from __future__ import print_function >>> import os >>> filename = "mtime_cp/f" >>> print(os.stat(filename).st_mtime < 1234567999) @@ -691,7 +690,6 @@ (modulo some fudge factor due to not every system supporting 1s-level precision). $ hg mv -q mtime mtime_mv - >>> from __future__ import print_function >>> import os >>> filename = "mtime_mv/f" >>> print(os.stat(filename).st_mtime < 1234567999)
--- a/tests/test-requires.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-requires.t Tue Apr 05 11:09:03 2022 +0200 @@ -32,7 +32,6 @@ $ echo 'featuresetup-test' >> supported/.hg/requires $ cat > $TESTTMP/supported-locally/supportlocally.py <<EOF - > from __future__ import absolute_import > from mercurial import extensions, localrepo > def featuresetup(ui, supported): > for name, module in extensions.extensions(ui):
--- a/tests/test-revert.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-revert.t Tue Apr 05 11:09:03 2022 +0200 @@ -550,7 +550,6 @@ $ cat << EOF >> dircontent.py > # generate a simple text view of the directory for easy comparison - > from __future__ import print_function > import os > files = os.listdir('.') > files.sort()
--- a/tests/test-revlog-ancestry.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-revlog-ancestry.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function import os from mercurial import ( hg,
--- a/tests/test-revlog-mmapindex.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-revlog-mmapindex.t Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ $ cat << EOF > verbosemmap.py > # extension to make util.mmapread verbose > - > from __future__ import absolute_import > > from mercurial import ( > extensions,
--- a/tests/test-revlog-raw.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-revlog-raw.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # test revlog interaction about raw data (flagprocessor) -from __future__ import absolute_import, print_function import collections import hashlib @@ -20,7 +19,7 @@ ) -class _NoTransaction(object): +class _NoTransaction: """transaction like object to update the nodemap outside a transaction""" def __init__(self): @@ -151,7 +150,7 @@ code path, which is not covered by "appendrev" alone. """ - class dummychangegroup(object): + class dummychangegroup: @staticmethod def deltachunk(pnode): pnode = pnode or rlog.nullid
--- a/tests/test-revset.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-revset.t Tue Apr 05 11:09:03 2022 +0200 @@ -36,7 +36,6 @@ these predicates use '\0' as a separator: $ cat <<EOF > debugrevlistspec.py - > from __future__ import absolute_import > from mercurial import ( > node as nodemod, > registrar,
--- a/tests/test-rhg.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-rhg.t Tue Apr 05 11:09:03 2022 +0200 @@ -391,3 +391,17 @@ $ echo "*:required = yes" >> $HGRCPATH $ rhg files a + +We can ignore all extensions at once + + $ echo "[extensions]" >> $HGRCPATH + $ echo "thisextensionbetternotexist=" >> $HGRCPATH + $ echo "thisextensionbetternotexisteither=" >> $HGRCPATH + $ $NO_FALLBACK rhg files + unsupported feature: extensions: thisextensionbetternotexist, thisextensionbetternotexisteither (consider adding them to 'rhg.ignored-extensions' config) + [252] + + $ echo "[rhg]" >> $HGRCPATH + $ echo "ignored-extensions=*" >> $HGRCPATH + $ $NO_FALLBACK rhg files + a
--- a/tests/test-run-tests.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-run-tests.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ run-test.t only checks positive matches and can not see warnings (both by design) """ -from __future__ import absolute_import, print_function import doctest import os
--- a/tests/test-run-tests.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-run-tests.t Tue Apr 05 11:09:03 2022 +0200 @@ -2086,5 +2086,4 @@ $ ./test-py3.py 3.* (glob) $ ./test-py.py - 2.* (glob) (no-py3 !) 3.* (glob) (py3 !)
--- a/tests/test-rust-ancestor.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-rust-ancestor.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import sys import unittest
--- a/tests/test-rust-discovery.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-rust-discovery.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import unittest from mercurial import policy @@ -32,12 +31,12 @@ ) -class fakechangelog(object): +class fakechangelog: def __init__(self, idx): self.index = idx -class fakerepo(object): +class fakerepo: def __init__(self, idx): """Just make so that self.changelog.index is the given idx.""" self.changelog = fakechangelog(idx)
--- a/tests/test-rust-revlog.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-rust-revlog.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import import unittest try:
--- a/tests/test-share-bookmarks.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-share-bookmarks.t Tue Apr 05 11:09:03 2022 +0200 @@ -222,7 +222,6 @@ $ cat > failpullbookmarks.py << EOF > """A small extension that makes bookmark pulls fail, for testing""" - > from __future__ import absolute_import > from mercurial import ( > error, > exchange,
--- a/tests/test-shelve.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-shelve.t Tue Apr 05 11:09:03 2022 +0200 @@ -976,7 +976,7 @@ Test shelve --delete $ hg shelve --list - default (*s ago) changes to: create conflict (glob) + default (*s ago) * changes to: create conflict (glob) $ hg shelve --delete doesnotexist abort: shelved change 'doesnotexist' not found [10] @@ -1209,7 +1209,7 @@ $ hg add e $ hg ci -m e $ hg shelve --patch - default (*s ago) changes to: b (glob) + default (*s ago) * changes to: b (glob) diff --git a/c b/c new file mode 100644 @@ -1258,7 +1258,7 @@ e -- shelve should not contain `c` now $ hg shelve --patch - default (*s ago) changes to: b (glob) + default (*s ago) * changes to: b (glob) diff --git a/d b/d new file mode 100644 @@ -1357,7 +1357,7 @@ A B $ hg shelve --patch - default (*s ago) changes to: add B to foo (glob) + default (*s ago) * changes to: add B to foo (glob) diff --git a/foo b/foo --- a/foo
--- a/tests/test-simplekeyvaluefile.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-simplekeyvaluefile.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import unittest import silenttestrunner @@ -9,7 +7,7 @@ ) -class mockfile(object): +class mockfile: def __init__(self, name, fs): self.name = name self.fs = fs @@ -27,7 +25,7 @@ return self.fs.contents[self.name] -class mockvfs(object): +class mockvfs: def __init__(self): self.contents = {}
--- a/tests/test-simplemerge.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-simplemerge.py Tue Apr 05 11:09:03 2022 +0200 @@ -13,7 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. -from __future__ import absolute_import import unittest from mercurial import (
--- a/tests/test-ssh-proto-unbundle.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-ssh-proto-unbundle.t Tue Apr 05 11:09:03 2022 +0200 @@ -99,7 +99,6 @@ Test pushing to a server that has a pretxnchangegroup Python hook that fails $ cat > $TESTTMP/failhook << EOF - > from __future__ import print_function > import sys > def hook1line(ui, repo, **kwargs): > ui.write(b'ui.write 1 line\n')
--- a/tests/test-ssh.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-ssh.t Tue Apr 05 11:09:03 2022 +0200 @@ -326,7 +326,6 @@ remote: added 1 changesets with 1 changes to 1 files (py3 !) remote: KABOOM remote: KABOOM IN PROCESS - remote: added 1 changesets with 1 changes to 1 files (no-py3 !) #endif
--- a/tests/test-sshserver.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-sshserver.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import io import unittest @@ -40,12 +38,12 @@ return wireprotoserver.sshserver(ui, repo) -class mockrepo(object): +class mockrepo: def __init__(self, ui): self.ui = ui -class mockui(object): +class mockui: def __init__(self, inbytes): self.fin = io.BytesIO(inbytes) self.fout = io.BytesIO()
--- a/tests/test-status-inprocess.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-status-inprocess.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import absolute_import, print_function import sys
--- a/tests/test-status.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-status.t Tue Apr 05 11:09:03 2022 +0200 @@ -315,9 +315,8 @@ ] $ hg status -A -Tpickle > pickle - >>> from __future__ import print_function + >>> import pickle >>> from mercurial import util - >>> pickle = util.pickle >>> data = sorted((x[b'status'].decode(), x[b'path'].decode()) for x in pickle.load(open("pickle", r"rb"))) >>> for s, p in data: print("%s %s" % (s, p)) ! deleted
--- a/tests/test-stdio.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-stdio.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,11 +2,11 @@ """ Tests the buffering behavior of stdio streams in `mercurial.utils.procutil`. """ -from __future__ import absolute_import import contextlib import errno import os +import pickle import signal import subprocess import sys @@ -336,7 +336,7 @@ proc.stdin.close() def post_child_check(): - err = util.pickle.load(err_f) + err = pickle.load(err_f) self.assertEqual(err.errno, errno.EPIPE) self.assertEqual(err.strerror, "Broken pipe")
--- a/tests/test-storage.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-storage.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,6 +1,5 @@ # This test verifies the conformance of various classes to various # storage interfaces. -from __future__ import absolute_import import silenttestrunner
--- a/tests/test-strip.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-strip.t Tue Apr 05 11:09:03 2022 +0200 @@ -1290,7 +1290,6 @@ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo 3 >> I $ cat > $TESTTMP/delayedstrip.py <<EOF - > from __future__ import absolute_import > from mercurial import commands, registrar, repair > cmdtable = {} > command = registrar.command(cmdtable)
--- a/tests/test-subrepo-git.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-subrepo-git.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,20 +1,5 @@ #require git -# XXX-CHG When running with python2 + chg this test tend to get stuck and end up -# as a time-out error. My effort to reproduce this outside of the CI failed. The -# test itself seems to pass fine, but never "complete". Debugging it is slow and -# tedious. This as a bad impact on the development process as most CI run end up -# wasting abotu 1h until that one fails. -# -# Pierre-Yves David, Augie Fackler and Raphaël Gomès all agreed to disable this -# case in that specific case until we figure this out (or we drop python2 o:-) ) - -#if no-py3 chg - $ echo 'skipped: this test get stuck on the CI with python2 + chg. investigation needed' - $ exit 80 -#endif - - make git commits repeatable $ cat >> $HGRCPATH <<EOF
--- a/tests/test-subrepo-svn.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-subrepo-svn.t Tue Apr 05 11:09:03 2022 +0200 @@ -249,7 +249,7 @@ verify subrepo is contained within the repo directory - $ "$PYTHON" -c "from __future__ import print_function; import os.path; print(os.path.exists('s'))" + $ "$PYTHON" -c "import os.path; print(os.path.exists('s'))" True update to nullrev (must delete the subrepo)
--- a/tests/test-symlink-os-yes-fs-no.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-symlink-os-yes-fs-no.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import os import sys import time
--- a/tests/test-template-functions.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-template-functions.t Tue Apr 05 11:09:03 2022 +0200 @@ -192,7 +192,6 @@ $ cd unstable-hash $ hg log --template '{date|age}\n' > /dev/null || exit 1 - >>> from __future__ import absolute_import >>> import datetime >>> fp = open('a', 'wb') >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7) @@ -1572,7 +1571,6 @@ Test cbor filter: $ cat <<'EOF' > "$TESTTMP/decodecbor.py" - > from __future__ import absolute_import > from mercurial import ( > dispatch, > )
--- a/tests/test-template-map.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-template-map.t Tue Apr 05 11:09:03 2022 +0200 @@ -722,7 +722,6 @@ test CBOR style: $ cat <<'EOF' > "$TESTTMP/decodecborarray.py" - > from __future__ import absolute_import > from mercurial import ( > dispatch, > )
--- a/tests/test-trusted.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-trusted.py Tue Apr 05 11:09:03 2022 +0200 @@ -2,7 +2,6 @@ # with files from different users/groups, we cheat a bit by # monkey-patching some functions in the util module -from __future__ import absolute_import, print_function import os import sys
--- a/tests/test-ui-color.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-ui-color.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import os from mercurial import ( dispatch,
--- a/tests/test-ui-config.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-ui-config.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,4 +1,3 @@ -from __future__ import absolute_import, print_function from mercurial import ( dispatch, error,
--- a/tests/test-ui-verbosity.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-ui-verbosity.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import os from mercurial import ( pycompat,
--- a/tests/test-unified-test.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-unified-test.t Tue Apr 05 11:09:03 2022 +0200 @@ -26,7 +26,6 @@ Doctest commands: - >>> from __future__ import print_function >>> print('foo') foo $ echo interleaved
--- a/tests/test-update-atomic.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-update-atomic.t Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ Checking that experimental.atomic-file works. $ cat > $TESTTMP/show_mode.py <<EOF - > from __future__ import print_function > import os > import stat > import sys @@ -20,7 +19,6 @@ $ cd repo $ cat > .hg/showwrites.py <<EOF - > from __future__ import print_function > from mercurial import pycompat > from mercurial.utils import stringutil > def uisetup(ui):
--- a/tests/test-upgrade-repo.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-upgrade-repo.t Tue Apr 05 11:09:03 2022 +0200 @@ -734,7 +734,6 @@ $ touch FooBarDirectory.d/f1 $ hg -q commit -A -m 'add f1' $ hg -q up -r 0 - >>> from __future__ import absolute_import, print_function >>> import random >>> random.seed(0) # have a reproducible content >>> with open("f2", "wb") as f: @@ -958,7 +957,6 @@ Check that the repo still works fine $ hg log -G --stat - @ changeset: 2:76d4395f5413 (no-py3 !) @ changeset: 2:fca376863211 (py3 !) | tag: tip | parent: 0:ba592bf28da2
--- a/tests/test-url.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-url.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ # coding=utf-8 -from __future__ import absolute_import, print_function import doctest import os
--- a/tests/test-util.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-util.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,7 @@ # unit tests for mercuril.util utilities -from __future__ import absolute_import import contextlib +import io import itertools import unittest @@ -55,7 +55,7 @@ @contextlib.contextmanager def capturestderr(): - """Replace utils.procutil.stderr with a pycompat.bytesio instance + """Replace utils.procutil.stderr with an io.BytesIO instance The instance is made available as the return value of __enter__. @@ -63,7 +63,7 @@ """ orig = utils.procutil.stderr - utils.procutil.stderr = pycompat.bytesio() + utils.procutil.stderr = io.BytesIO() try: yield utils.procutil.stderr finally:
--- a/tests/test-verify-repo-operations.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-verify-repo-operations.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import print_function, absolute_import - """Fuzz testing for operations against a Mercurial repository This uses Hypothesis's stateful testing to generate random repository
--- a/tests/test-verify.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-verify.t Tue Apr 05 11:09:03 2022 +0200 @@ -338,7 +338,6 @@ checked 1 changesets with 1 changes to 1 files $ cat >> $TESTTMP/break-base64.py <<EOF - > from __future__ import absolute_import > import base64 > base64.b64decode=lambda x: x > EOF
--- a/tests/test-walk.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-walk.t Tue Apr 05 11:09:03 2022 +0200 @@ -640,7 +640,6 @@ $ cd t $ echo fennel > overflow.list $ cat >> printnum.py <<EOF - > from __future__ import print_function > for i in range(20000 // 100): > print('x' * 100) > EOF
--- a/tests/test-walkrepo.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-walkrepo.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import os from mercurial import (
--- a/tests/test-wireproto-clientreactor.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-wireproto-clientreactor.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import sys import unittest import zlib
--- a/tests/test-wireproto-framing.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-wireproto-framing.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import unittest from mercurial import (
--- a/tests/test-wireproto-serverreactor.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-wireproto-serverreactor.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import unittest from mercurial import (
--- a/tests/test-wireproto.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-wireproto.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import sys from mercurial import ( @@ -16,7 +14,7 @@ stringio = util.stringio -class proto(object): +class proto: def __init__(self, args): self.args = args self.name = 'dummyproto' @@ -78,7 +76,7 @@ return {b'name': mangle(name)}, unmangle -class serverrepo(object): +class serverrepo: def __init__(self, ui): self.ui = ui
--- a/tests/test-worker.t Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-worker.t Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,6 @@ Test UI worker interaction $ cat > t.py <<EOF - > from __future__ import absolute_import, print_function > import sys > import time > from mercurial import ( @@ -88,9 +87,7 @@ > test 100000.0 abort --traceback 2>&1 | egrep '(WorkerError|Abort)' raise error.Abort(b'known exception') mercurial.error.Abort: known exception (py3 !) - Abort: known exception (no-py3 !) raise error.WorkerError(status) - WorkerError: 255 (no-py3 !) mercurial.error.WorkerError: 255 (py3 !) Traceback must be printed for unknown exceptions @@ -102,7 +99,6 @@ Workers should not do cleanups in all cases $ cat > $TESTTMP/detectcleanup.py <<EOF - > from __future__ import absolute_import > import atexit > import os > import sys @@ -136,7 +132,6 @@ Do not crash on partially read result $ cat > $TESTTMP/detecttruncated.py <<EOF - > from __future__ import absolute_import > import os > import sys > import time
--- a/tests/test-wsgirequest.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/test-wsgirequest.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import unittest from mercurial.hgweb import request as requestmod
--- a/tests/testlib/badserverext.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/badserverext.py Tue Apr 05 11:09:03 2022 +0200 @@ -44,7 +44,6 @@ request) """ -from __future__ import absolute_import import re import socket @@ -91,7 +90,7 @@ ) -class ConditionTracker(object): +class ConditionTracker: def __init__( self, close_after_recv_bytes, @@ -257,7 +256,7 @@ # We can't adjust __class__ on a socket instance. So we define a proxy type. -class socketproxy(object): +class socketproxy: __slots__ = ('_orig', '_logfp', '_cond') def __init__(self, obj, logfp, condition_tracked): @@ -301,7 +300,7 @@ # We can't adjust __class__ on socket._fileobject, so define a proxy. -class fileobjectproxy(object): +class fileobjectproxy: __slots__ = ('_orig', '_logfp', '_cond') def __init__(self, obj, logfp, condition_tracked):
--- a/tests/testlib/crash_transaction_late.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/crash_transaction_late.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial import ( error,
--- a/tests/testlib/ext-phase-report.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/ext-phase-report.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,7 +1,5 @@ # tiny extension to report phase changes during transaction -from __future__ import absolute_import - def reposetup(ui, repo): def reportphasemove(tr):
--- a/tests/testlib/ext-sidedata-2.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/ext-sidedata-2.py Tue Apr 05 11:09:03 2022 +0200 @@ -8,7 +8,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import hashlib import struct
--- a/tests/testlib/ext-sidedata-3.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/ext-sidedata-3.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,7 +9,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import hashlib import struct
--- a/tests/testlib/ext-sidedata-4.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/ext-sidedata-4.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,7 +9,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import from mercurial.revlogutils import sidedata
--- a/tests/testlib/ext-sidedata-5.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/ext-sidedata-5.py Tue Apr 05 11:09:03 2022 +0200 @@ -9,7 +9,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import hashlib import struct
--- a/tests/testlib/ext-sidedata.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/ext-sidedata.py Tue Apr 05 11:09:03 2022 +0200 @@ -5,7 +5,6 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from __future__ import absolute_import import hashlib import struct
--- a/tests/testlib/ext-stream-clone-steps.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/ext-stream-clone-steps.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from mercurial import ( encoding, extensions,
--- a/tests/testlib/persistent-nodemap-race-ext.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/persistent-nodemap-race-ext.py Tue Apr 05 11:09:03 2022 +0200 @@ -35,7 +35,6 @@ /!\ valid. """ -from __future__ import print_function import os
--- a/tests/testlib/sigpipe-remote.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/sigpipe-remote.py Tue Apr 05 11:09:03 2022 +0200 @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from __future__ import print_function import io import os @@ -7,14 +6,6 @@ import sys import time -# we cannot use mercurial.testing as long as python2 is not dropped as the test -# will only install the mercurial module for python2 in python2 run -if sys.version_info[0] < 3: - ver = '.'.join(str(x) for x in sys.version_info) - exe = sys.executable - print('SIGPIPE-HELPER: script should run with Python 3', file=sys.stderr) - print('SIGPIPE-HELPER: %s is running %s' % (exe, ver), file=sys.stderr) - sys.exit(255) if isinstance(sys.stdout.buffer, io.BufferedWriter): print('SIGPIPE-HELPER: script need unbuffered output', file=sys.stderr)
--- a/tests/testlib/sigpipe-worker.py Tue Apr 05 10:55:28 2022 +0200 +++ b/tests/testlib/sigpipe-worker.py Tue Apr 05 11:09:03 2022 +0200 @@ -3,7 +3,6 @@ # This is literally `cat` but in python, one char at a time. # # see sigpipe-remote.py for details. -from __future__ import print_function import io import os