diff tests/hghave.py @ 52572:384d71e3dd65

pyproject: defer the `hghave` version check of `black` to the project file This demonstrates the alternate way of testing for the proper version that was mentioned in the last commit. Needing to manually evaluate from the project root when run in the test suite is a bit unfortunate. Arguably it is limiting for 3rd party users, but they were already locked into a specific version before too, if using this sentinel. This lock-in is only for the version check though, and then they can `cd /path/to/repo` to run their `test-*.t` with their config. On the plus side, we're allowing any minor variant of the required major version, we're not assuming the version string format that the tool produces, and there's one source of truth for the version. If running under `RUNTESTDIR` is omitted, then `hghave` will allow any version as long as the tool exists on `PATH`, but `test-check-format.t` will fail with the message in the previous commit. I'd argue that's preferrable to suddenly quietly skipping the test when the requirement changes, but this was the previous behavior too, so that's maintained here.
author Matt Harbison <matt_harbison@yahoo.com>
date Tue, 17 Dec 2024 22:54:36 -0500
parents 323e3626929a
children 918ef1fca39e
line wrap: on
line diff
--- a/tests/hghave.py	Tue Dec 17 22:32:12 2024 -0500
+++ b/tests/hghave.py	Tue Dec 17 22:54:36 2024 -0500
@@ -130,11 +130,7 @@
         sys.exit(1)
 
 
-def matchoutput(cmd, regexp, ignorestatus=False):
-    """Return the match object if cmd executes successfully and its output
-    is matched by the supplied regular expression.
-    """
-
+def environ():
     # Tests on Windows have to fake USERPROFILE to point to the test area so
     # that `~` is properly expanded on py3.8+.  However, some tools like black
     # make calls that need the real USERPROFILE in order to run `foo --version`.
@@ -142,6 +138,14 @@
     if os.name == 'nt':
         env = os.environ.copy()
         env['USERPROFILE'] = env['REALUSERPROFILE']
+    return env
+
+
+def matchoutput(cmd, regexp, ignorestatus=False):
+    """Return the match object if cmd executes successfully and its output
+    is matched by the supplied regular expression.
+    """
+    env = environ()
 
     r = re.compile(regexp)
     p = subprocess.Popen(
@@ -1125,14 +1129,27 @@
     return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
 
 
-@check('black', 'the black formatter for python >=23.3.0')
+@check(
+    'black', 'the black formatter for python (version set in pyproject.toml)'
+)
 def has_black():
-    blackcmd = 'black --version'
-    version_regex = b'black, (?:version )?([0-9a-b.]+)'
-    version = matchoutput(blackcmd, version_regex)
-    if not version:
-        return False
-    return Version(_bytes2sys(version.group(1))) >= Version('23.3.0')
+    env = environ()
+
+    # The top level #require statements are evaluated from $TESTTMP, and won't
+    # see the project level pyproject.toml unless executing from the project
+    # directory.
+    cwd = os.getcwd()
+    if 'RUNTESTDIR' in env:
+        cwd = os.path.realpath(f"{env['RUNTESTDIR']}/..")
+
+    p = subprocess.Popen(
+        ['black', '--check', '-'],
+        stdin=subprocess.PIPE,
+        cwd=cwd,
+        env=env,
+    )
+    p.communicate(b'# test\n')
+    return p.returncode == 0
 
 
 @check('pytype', 'the pytype type checker')