Blob Blame History Raw
From 6238d9e8b78f5327f60bd1d2606a37f951a3cd9c Mon Sep 17 00:00:00 2001
Message-Id: <6238d9e8b78f5327f60bd1d2606a37f951a3cd9c.1655928893.git.github@sicherha.de>
From: Christoph Erhardt <github@sicherha.de>
Date: Wed, 22 Jun 2022 21:42:53 +0200
Subject: [PATCH] Ensure compatibility with Python 3.11

* Replace deprecated `getargspec()` with `getfullargspec()`
* Replace deprecated `formatargspec()` with custom implementation

Fixes #2209.
---
 docs/source/powerline_autodoc.py |  6 ++----
 powerline/lint/inspect.py        | 34 +++++++++++++++++++++++++++++---
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/docs/source/powerline_autodoc.py b/docs/source/powerline_autodoc.py
index eba42edb..83996aea 100644
--- a/docs/source/powerline_autodoc.py
+++ b/docs/source/powerline_autodoc.py
@@ -3,11 +3,9 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
 
 import os
 
-from inspect import formatargspec
-
 from sphinx.ext import autodoc
 
-from powerline.lint.inspect import getconfigargspec
+from powerline.lint.inspect import formatconfigargspec, getconfigargspec
 from powerline.segments import Segment
 from powerline.lib.unicode import unicode
 
@@ -28,7 +26,7 @@ class ThreadedDocumenter(autodoc.FunctionDocumenter):
 
 	def format_args(self):
 		argspec = getconfigargspec(self.object)
-		return formatargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\')
+		return formatconfigargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\')
 
 
 class Repr(object):
diff --git a/powerline/lint/inspect.py b/powerline/lint/inspect.py
index 15bb6103..7ab720f8 100644
--- a/powerline/lint/inspect.py
+++ b/powerline/lint/inspect.py
@@ -1,7 +1,8 @@
 # vim:fileencoding=utf-8:noet
 from __future__ import (unicode_literals, division, absolute_import, print_function)
 
-from inspect import ArgSpec, getargspec
+from inspect import FullArgSpec, getfullargspec
+from itertools import zip_longest
 
 from powerline.segments import Segment
 
@@ -33,7 +34,7 @@ def getconfigargspec(obj):
 	requires_filesystem_watcher = hasattr(obj, 'powerline_requires_filesystem_watcher')
 
 	for name, method in argspecobjs:
-		argspec = getargspec(method)
+		argspec = getfullargspec(method)
 		omitted_args = get_omitted_args(name, method)
 		largs = len(argspec.args)
 		for i, arg in enumerate(reversed(argspec.args)):
@@ -60,4 +61,31 @@ def getconfigargspec(obj):
 				if arg not in args:
 					args.insert(0, arg)
 
-	return ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
+	return FullArgSpec(args=args, varargs=None, varkw=None, defaults=tuple(defaults), kwonlyargs=(), kwonlydefaults={}, annotations={})
+
+
+def formatconfigargspec(args, varargs=None, varkw=None, defaults=None,
+                        kwonlyargs=(), kwonlydefaults={}, annotations={},
+                        formatvalue=lambda value: '=' + repr(value)):
+	'''Format an argument spec from the values returned by getconfigargspec.
+
+	This is a specialized replacement for inspect.formatargspec, which has been
+	deprecated since Python 3.5 and was removed in Python 3.11. It supports
+	valid values for args, defaults and formatvalue; all other parameters are
+	expected to be either empty or None.
+	'''
+	assert varargs is None
+	assert varkw is None
+	assert not kwonlyargs
+	assert not kwonlydefaults
+	assert not annotations
+
+	specs = []
+	if defaults:
+		firstdefault = len(args) - len(defaults)
+	for i, arg in enumerate(args):
+		spec = arg
+		if defaults and i >= firstdefault:
+			spec += formatvalue(defaults[i - firstdefault])
+		specs.append(spec)
+	return '(' + ', '.join(specs) + ')'
-- 
2.36.1