We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Tests/Python 3: update unittest syntax
Hi,

In order to test this, one must be using threshold_py3_staging branch.

### Steps to reproduce:
1. Checkout latest threshold_py3_staging work.
2. Perform scons tests.

### Actual behavior:
Errors related to syntax in unittest test cases are thrown.

### Expected behavior:
No errors

### System configuration
#### NVDA installed/portable/running from source:
Source

#### NVDA version:
Python 3 source

#### Windows version:
Windows 10 Version 1903 (build 18362)

#### Name and version of other software in use when reproducing the issue:
None

#### Other information about your system:
None

### Other questions
#### Does the issue still occur after restarting your PC?
Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
Yes - no errors in Python 2 version.

### Additional notes:
Scons tests revealed numerous source code errors, including removal of itertools.izip and others. I'll take care of izip issue as part of another pull request.

Thanks.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `source/extensionPoints/util.py`
Content:
```
1 #util.py
2 #A part of NonVisual Desktop Access (NVDA)
3 #Copyright (C) 2017 NV Access Limited
4 #This file is covered by the GNU General Public License.
5 #See the file COPYING for more details.
6 
7 """Utilities used withing the extension points framework. Generally it is expected that the class in __init__.py are
8 used, however for more advanced requirements these utilities can be used directly.
9 """
10 import weakref
11 import collections
12 import inspect
13 
14 
15 class AnnotatableWeakref(weakref.ref):
16 	"""A weakref.ref which allows annotation with custom attributes.
17 	"""
18 
19 
20 class BoundMethodWeakref(object):
21 	"""Weakly references a bound instance method.
22 	Instance methods are bound dynamically each time they are fetched.
23 	weakref.ref on a bound instance method doesn't work because
24 	as soon as you drop the reference, the method object dies.
25 	Instead, this class holds weak references to both the instance and the function,
26 	which can then be used to bind an instance method.
27 	To get the actual method, you call an instance as you would a weakref.ref.
28 	"""
29 
30 	def __init__(self, target, onDelete):
31 		def onRefDelete(weak):
32 			"""Calls onDelete for our BoundMethodWeakref when one of the individual weakrefs (instance or function) dies.
33 			"""
34 			onDelete(self)
35 		inst = target.__self__
36 		func = target.__func__
37 		self.weakInst = weakref.ref(inst, onRefDelete)
38 		self.weakFunc = weakref.ref(func, onRefDelete)
39 
40 	def __call__(self):
41 		inst = self.weakInst()
42 		if not inst:
43 			return
44 		func = self.weakFunc()
45 		assert func, "inst is alive but func is dead"
46 		# Get an instancemethod by binding func to inst.
47 		return func.__get__(inst)
48 
49 def _getHandlerKey(handler):
50 	"""Get a key which identifies a handler function.
51 	This is needed because we store weak references, not the actual functions.
52 	We store the key on the weak reference.
53 	When the handler dies, we can use the key on the weak reference to remove the handler.
54 	"""
55 	inst = getattr(handler, "__self__", None)
56 	if inst:
57 		return (id(inst), id(handler.__func__))
58 	return id(handler)
59 
60 
61 class HandlerRegistrar(object):
62 	"""Base class to Facilitate registration and unregistration of handler functions.
63 	The handlers are stored using weak references and are automatically unregistered
64 	if the handler dies.
65 	Both normal functions, instance methods and lambdas are supported. Ensure to keep lambdas alive by maintaining a
66 	reference to them.
67 	The handlers are maintained in the order they were registered
68 	so that they can be called in a deterministic order across runs.
69 	This class doesn't provide any functionality to actually call the handlers.
70 	If you want to implement an extension point,
71 	you probably want the L{Action} or L{Filter} subclasses instead.
72 	"""
73 
74 	def __init__(self):
75 		#: Registered handler functions.
76 		#: This is an OrderedDict where the keys are unique identifiers (as returned by _getHandlerKey)
77 		#: and the values are weak references.
78 		self._handlers = collections.OrderedDict()
79 
80 	def register(self, handler):
81 		"""You can register functions, bound instance methods, class methods, static methods or lambdas.
82 		However, the callable must be kept alive by your code otherwise it will be de-registered. This is due to the use
83 		of weak references. This is especially relevant when using lambdas.
84 		"""
85 		if hasattr(handler, "__self__"):
86 			if not handler.__self__:
87 				raise TypeError("Registering unbound instance methods not supported.")
88 			weak = BoundMethodWeakref(handler, self.unregister)
89 		else:
90 			weak = AnnotatableWeakref(handler, self.unregister)
91 		key = _getHandlerKey(handler)
92 		# Store the key on the weakref so we can remove the handler when it dies.
93 		weak.handlerKey = key
94 		self._handlers[key] = weak
95 
96 	def unregister(self, handler):
97 		if isinstance(handler, (AnnotatableWeakref, BoundMethodWeakref)):
98 			key = handler.handlerKey
99 		else:
100 			key = _getHandlerKey(handler)
101 		try:
102 			del self._handlers[key]
103 		except KeyError:
104 			return False
105 		return True
106 
107 	@property
108 	def handlers(self):
109 		"""Generator of registered handler functions.
110 		This should be used when you want to call the handlers.
111 		"""
112 		# #9067 (py3 review required): handlers is an ordered dictionary.
113 		# Therefore wrap this inside a list call.
114 		for weak in list(self._handlers.values()):
115 			handler = weak()
116 			if not handler:
117 				continue # Died.
118 			yield handler
119 
120 
121 def callWithSupportedKwargs(func, *args, **kwargs):
122 	"""Call a function with only the keyword arguments it supports.
123 	For example, if myFunc is defined as:
124 	C{def myFunc(a=None, b=None):}
125 	and you call:
126 	C{callWithSupportedKwargs(myFunc, a=1, b=2, c=3)}
127 	Instead of raising a TypeError, myFunc will simply be called like this:
128 	C{myFunc(a=1, b=2)}
129 
130 	While C{callWithSupportedKwargs} does support positional arguments (C{*args}), usage is strongly discouraged due to the
131 	risk of parameter order differences causing bugs.
132 
133 	@param func: can be any callable that is not an unbound method. EG:
134 		- Bound instance methods
135 		- class methods
136 		- static methods
137 		- functions
138 		- lambdas
139 
140 		The arguments for the supplied callable, C{func}, do not need to have default values, and can take C{**kwargs} to
141 		capture all arguments.
142 		See C{tests/unit/test_extensionPoints.py:TestCallWithSupportedKwargs} for examples.
143 
144 		An exception is raised if:
145 			- the number of positional arguments given can not be received by C{func}.
146 			- parameters required (parameters declared with no default value) by C{func} are not supplied.
147 	"""
148 	spec = inspect.getargspec(func)
149 
150 	# some handlers are instance/class methods, discard "self"/"cls" because it is typically passed implicitly.
151 	if inspect.ismethod(func):
152 		spec.args.pop(0)  # remove "self"/"cls" for instance methods
153 		if not hasattr(func, "__self__"):
154 			raise TypeError("Unbound instance methods are not handled.")
155 
156 	# Ensure that the positional args provided by the caller of `callWithSupportedKwargs` actually have a place to go.
157 	# Unfortunately, positional args can not be matched on name (keyword) to the names of the params in the handler,
158 	# and so calling `callWithSupportedKwargs` is at risk of causing bugs if parameter order differs.
159 	numExpectedArgs = len(spec.args)
160 	numGivenPositionalArgs = len(args)
161 	if numGivenPositionalArgs > numExpectedArgs:
162 		raise TypeError("Expected to be able to pass {} positional arguments.".format(numGivenPositionalArgs))
163 
164 	# Ensure that all arguments without defaults which are expected by the handler were provided.
165 	# `defaults` is a tuple of default argument values or None if there are no default arguments;
166 	# if this tuple has N elements, they correspond to the last N elements listed in args.
167 	numExpectedArgsWithDefaults = len(spec.defaults) if spec.defaults else 0
168 	if not spec.defaults or numExpectedArgsWithDefaults != numExpectedArgs:
169 		# get the names of the args without defaults, skipping the N positional args given to `callWithSupportedKwargs`
170 		# positionals are required for the Filter extension point.
171 		# #9067 (Py3 review required): Set construction will work with iterators, too.
172 		givenKwargsKeys = set(kwargs.keys())
173 		firstArgWithDefault = numExpectedArgs - numExpectedArgsWithDefaults
174 		specArgs = set(spec.args[numGivenPositionalArgs:firstArgWithDefault])
175 		for arg in specArgs:
176 			# and ensure they are in the kwargs list
177 			if arg not in givenKwargsKeys:
178 				raise TypeError("Parameter required for handler not provided: {}".format(arg))
179 
180 	if spec.keywords:
181 		# func has a catch-all for kwargs (**kwargs) so we do not need to filter to just the supported args.
182 		return func(*args, **kwargs)
183 
184 	supportedKwargs = set(spec.args)
185 	# #9067 (Py3 review required): originally called dict.keys.
186 	# Therefore wrap this inside a list call.
187 	for kwarg in list(kwargs.keys()):
188 		if kwarg not in supportedKwargs:
189 			del kwargs[kwarg]
190 	return func(*args, **kwargs)
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/source/extensionPoints/util.py b/source/extensionPoints/util.py
--- a/source/extensionPoints/util.py
+++ b/source/extensionPoints/util.py
@@ -82,6 +82,7 @@
 		However, the callable must be kept alive by your code otherwise it will be de-registered. This is due to the use
 		of weak references. This is especially relevant when using lambdas.
 		"""
+		# #9720 (Py3 review required): this method causes unittest to fail in Python 3.
 		if hasattr(handler, "__self__"):
 			if not handler.__self__:
 				raise TypeError("Registering unbound instance methods not supported.")

{"golden_diff": "diff --git a/source/extensionPoints/util.py b/source/extensionPoints/util.py\n--- a/source/extensionPoints/util.py\n+++ b/source/extensionPoints/util.py\n@@ -82,6 +82,7 @@\n \t\tHowever, the callable must be kept alive by your code otherwise it will be de-registered. This is due to the use\r\n \t\tof weak references. This is especially relevant when using lambdas.\r\n \t\t\"\"\"\r\n+\t\t# #9720 (Py3 review required): this method causes unittest to fail in Python 3.\r\n \t\tif hasattr(handler, \"__self__\"):\r\n \t\t\tif not handler.__self__:\r\n \t\t\t\traise TypeError(\"Registering unbound instance methods not supported.\")\n", "issue": "Tests/Python 3: update unittest syntax\nHi,\r\n\r\nIn order to test this, one must be using threshold_py3_staging branch.\r\n\r\n### Steps to reproduce:\r\n1. Checkout latest threshold_py3_staging work.\r\n2. Perform scons tests.\r\n\r\n### Actual behavior:\r\nErrors related to syntax in unittest test cases are thrown.\r\n\r\n### Expected behavior:\r\nNo errors\r\n\r\n### System configuration\r\n#### NVDA installed/portable/running from source:\r\nSource\r\n\r\n#### NVDA version:\r\nPython 3 source\r\n\r\n#### Windows version:\r\nWindows 10 Version 1903 (build 18362)\r\n\r\n#### Name and version of other software in use when reproducing the issue:\r\nNone\r\n\r\n#### Other information about your system:\r\nNone\r\n\r\n### Other questions\r\n#### Does the issue still occur after restarting your PC?\r\nYes\r\n\r\n#### Have you tried any other versions of NVDA? If so, please report their behaviors.\r\nYes - no errors in Python 2 version.\r\n\r\n### Additional notes:\r\nScons tests revealed numerous source code errors, including removal of itertools.izip and others. I'll take care of izip issue as part of another pull request.\r\n\r\nThanks.\n", "before_files": [{"content": "#util.py\r\n#A part of NonVisual Desktop Access (NVDA)\r\n#Copyright (C) 2017 NV Access Limited\r\n#This file is covered by the GNU General Public License.\r\n#See the file COPYING for more details.\r\n\r\n\"\"\"Utilities used withing the extension points framework. Generally it is expected that the class in __init__.py are\r\nused, however for more advanced requirements these utilities can be used directly.\r\n\"\"\"\r\nimport weakref\r\nimport collections\r\nimport inspect\r\n\r\n\r\nclass AnnotatableWeakref(weakref.ref):\r\n\t\"\"\"A weakref.ref which allows annotation with custom attributes.\r\n\t\"\"\"\r\n\r\n\r\nclass BoundMethodWeakref(object):\r\n\t\"\"\"Weakly references a bound instance method.\r\n\tInstance methods are bound dynamically each time they are fetched.\r\n\tweakref.ref on a bound instance method doesn't work because\r\n\tas soon as you drop the reference, the method object dies.\r\n\tInstead, this class holds weak references to both the instance and the function,\r\n\twhich can then be used to bind an instance method.\r\n\tTo get the actual method, you call an instance as you would a weakref.ref.\r\n\t\"\"\"\r\n\r\n\tdef __init__(self, target, onDelete):\r\n\t\tdef onRefDelete(weak):\r\n\t\t\t\"\"\"Calls onDelete for our BoundMethodWeakref when one of the individual weakrefs (instance or function) dies.\r\n\t\t\t\"\"\"\r\n\t\t\tonDelete(self)\r\n\t\tinst = target.__self__\r\n\t\tfunc = target.__func__\r\n\t\tself.weakInst = weakref.ref(inst, onRefDelete)\r\n\t\tself.weakFunc = weakref.ref(func, onRefDelete)\r\n\r\n\tdef __call__(self):\r\n\t\tinst = self.weakInst()\r\n\t\tif not inst:\r\n\t\t\treturn\r\n\t\tfunc = self.weakFunc()\r\n\t\tassert func, \"inst is alive but func is dead\"\r\n\t\t# Get an instancemethod by binding func to inst.\r\n\t\treturn func.__get__(inst)\r\n\r\ndef _getHandlerKey(handler):\r\n\t\"\"\"Get a key which identifies a handler function.\r\n\tThis is needed because we store weak references, not the actual functions.\r\n\tWe store the key on the weak reference.\r\n\tWhen the handler dies, we can use the key on the weak reference to remove the handler.\r\n\t\"\"\"\r\n\tinst = getattr(handler, \"__self__\", None)\r\n\tif inst:\r\n\t\treturn (id(inst), id(handler.__func__))\r\n\treturn id(handler)\r\n\r\n\r\nclass HandlerRegistrar(object):\r\n\t\"\"\"Base class to Facilitate registration and unregistration of handler functions.\r\n\tThe handlers are stored using weak references and are automatically unregistered\r\n\tif the handler dies.\r\n\tBoth normal functions, instance methods and lambdas are supported. Ensure to keep lambdas alive by maintaining a\r\n\treference to them.\r\n\tThe handlers are maintained in the order they were registered\r\n\tso that they can be called in a deterministic order across runs.\r\n\tThis class doesn't provide any functionality to actually call the handlers.\r\n\tIf you want to implement an extension point,\r\n\tyou probably want the L{Action} or L{Filter} subclasses instead.\r\n\t\"\"\"\r\n\r\n\tdef __init__(self):\r\n\t\t#: Registered handler functions.\r\n\t\t#: This is an OrderedDict where the keys are unique identifiers (as returned by _getHandlerKey)\r\n\t\t#: and the values are weak references.\r\n\t\tself._handlers = collections.OrderedDict()\r\n\r\n\tdef register(self, handler):\r\n\t\t\"\"\"You can register functions, bound instance methods, class methods, static methods or lambdas.\r\n\t\tHowever, the callable must be kept alive by your code otherwise it will be de-registered. This is due to the use\r\n\t\tof weak references. This is especially relevant when using lambdas.\r\n\t\t\"\"\"\r\n\t\tif hasattr(handler, \"__self__\"):\r\n\t\t\tif not handler.__self__:\r\n\t\t\t\traise TypeError(\"Registering unbound instance methods not supported.\")\r\n\t\t\tweak = BoundMethodWeakref(handler, self.unregister)\r\n\t\telse:\r\n\t\t\tweak = AnnotatableWeakref(handler, self.unregister)\r\n\t\tkey = _getHandlerKey(handler)\r\n\t\t# Store the key on the weakref so we can remove the handler when it dies.\r\n\t\tweak.handlerKey = key\r\n\t\tself._handlers[key] = weak\r\n\r\n\tdef unregister(self, handler):\r\n\t\tif isinstance(handler, (AnnotatableWeakref, BoundMethodWeakref)):\r\n\t\t\tkey = handler.handlerKey\r\n\t\telse:\r\n\t\t\tkey = _getHandlerKey(handler)\r\n\t\ttry:\r\n\t\t\tdel self._handlers[key]\r\n\t\texcept KeyError:\r\n\t\t\treturn False\r\n\t\treturn True\r\n\r\n\t@property\r\n\tdef handlers(self):\r\n\t\t\"\"\"Generator of registered handler functions.\r\n\t\tThis should be used when you want to call the handlers.\r\n\t\t\"\"\"\r\n\t\t# #9067 (py3 review required): handlers is an ordered dictionary.\r\n\t\t# Therefore wrap this inside a list call.\r\n\t\tfor weak in list(self._handlers.values()):\r\n\t\t\thandler = weak()\r\n\t\t\tif not handler:\r\n\t\t\t\tcontinue # Died.\r\n\t\t\tyield handler\r\n\r\n\r\ndef callWithSupportedKwargs(func, *args, **kwargs):\r\n\t\"\"\"Call a function with only the keyword arguments it supports.\r\n\tFor example, if myFunc is defined as:\r\n\tC{def myFunc(a=None, b=None):}\r\n\tand you call:\r\n\tC{callWithSupportedKwargs(myFunc, a=1, b=2, c=3)}\r\n\tInstead of raising a TypeError, myFunc will simply be called like this:\r\n\tC{myFunc(a=1, b=2)}\r\n\r\n\tWhile C{callWithSupportedKwargs} does support positional arguments (C{*args}), usage is strongly discouraged due to the\r\n\trisk of parameter order differences causing bugs.\r\n\r\n\t@param func: can be any callable that is not an unbound method. EG:\r\n\t\t- Bound instance methods\r\n\t\t- class methods\r\n\t\t- static methods\r\n\t\t- functions\r\n\t\t- lambdas\r\n\r\n\t\tThe arguments for the supplied callable, C{func}, do not need to have default values, and can take C{**kwargs} to\r\n\t\tcapture all arguments.\r\n\t\tSee C{tests/unit/test_extensionPoints.py:TestCallWithSupportedKwargs} for examples.\r\n\r\n\t\tAn exception is raised if:\r\n\t\t\t- the number of positional arguments given can not be received by C{func}.\r\n\t\t\t- parameters required (parameters declared with no default value) by C{func} are not supplied.\r\n\t\"\"\"\r\n\tspec = inspect.getargspec(func)\r\n\r\n\t# some handlers are instance/class methods, discard \"self\"/\"cls\" because it is typically passed implicitly.\r\n\tif inspect.ismethod(func):\r\n\t\tspec.args.pop(0)  # remove \"self\"/\"cls\" for instance methods\r\n\t\tif not hasattr(func, \"__self__\"):\r\n\t\t\traise TypeError(\"Unbound instance methods are not handled.\")\r\n\r\n\t# Ensure that the positional args provided by the caller of `callWithSupportedKwargs` actually have a place to go.\r\n\t# Unfortunately, positional args can not be matched on name (keyword) to the names of the params in the handler,\r\n\t# and so calling `callWithSupportedKwargs` is at risk of causing bugs if parameter order differs.\r\n\tnumExpectedArgs = len(spec.args)\r\n\tnumGivenPositionalArgs = len(args)\r\n\tif numGivenPositionalArgs > numExpectedArgs:\r\n\t\traise TypeError(\"Expected to be able to pass {} positional arguments.\".format(numGivenPositionalArgs))\r\n\r\n\t# Ensure that all arguments without defaults which are expected by the handler were provided.\r\n\t# `defaults` is a tuple of default argument values or None if there are no default arguments;\r\n\t# if this tuple has N elements, they correspond to the last N elements listed in args.\r\n\tnumExpectedArgsWithDefaults = len(spec.defaults) if spec.defaults else 0\r\n\tif not spec.defaults or numExpectedArgsWithDefaults != numExpectedArgs:\r\n\t\t# get the names of the args without defaults, skipping the N positional args given to `callWithSupportedKwargs`\r\n\t\t# positionals are required for the Filter extension point.\r\n\t\t# #9067 (Py3 review required): Set construction will work with iterators, too.\r\n\t\tgivenKwargsKeys = set(kwargs.keys())\r\n\t\tfirstArgWithDefault = numExpectedArgs - numExpectedArgsWithDefaults\r\n\t\tspecArgs = set(spec.args[numGivenPositionalArgs:firstArgWithDefault])\r\n\t\tfor arg in specArgs:\r\n\t\t\t# and ensure they are in the kwargs list\r\n\t\t\tif arg not in givenKwargsKeys:\r\n\t\t\t\traise TypeError(\"Parameter required for handler not provided: {}\".format(arg))\r\n\r\n\tif spec.keywords:\r\n\t\t# func has a catch-all for kwargs (**kwargs) so we do not need to filter to just the supported args.\r\n\t\treturn func(*args, **kwargs)\r\n\r\n\tsupportedKwargs = set(spec.args)\r\n\t# #9067 (Py3 review required): originally called dict.keys.\r\n\t# Therefore wrap this inside a list call.\r\n\tfor kwarg in list(kwargs.keys()):\r\n\t\tif kwarg not in supportedKwargs:\r\n\t\t\tdel kwargs[kwarg]\r\n\treturn func(*args, **kwargs)", "path": "source/extensionPoints/util.py"}], "after_files": [{"content": "#util.py\r\n#A part of NonVisual Desktop Access (NVDA)\r\n#Copyright (C) 2017 NV Access Limited\r\n#This file is covered by the GNU General Public License.\r\n#See the file COPYING for more details.\r\n\r\n\"\"\"Utilities used withing the extension points framework. Generally it is expected that the class in __init__.py are\r\nused, however for more advanced requirements these utilities can be used directly.\r\n\"\"\"\r\nimport weakref\r\nimport collections\r\nimport inspect\r\n\r\n\r\nclass AnnotatableWeakref(weakref.ref):\r\n\t\"\"\"A weakref.ref which allows annotation with custom attributes.\r\n\t\"\"\"\r\n\r\n\r\nclass BoundMethodWeakref(object):\r\n\t\"\"\"Weakly references a bound instance method.\r\n\tInstance methods are bound dynamically each time they are fetched.\r\n\tweakref.ref on a bound instance method doesn't work because\r\n\tas soon as you drop the reference, the method object dies.\r\n\tInstead, this class holds weak references to both the instance and the function,\r\n\twhich can then be used to bind an instance method.\r\n\tTo get the actual method, you call an instance as you would a weakref.ref.\r\n\t\"\"\"\r\n\r\n\tdef __init__(self, target, onDelete):\r\n\t\tdef onRefDelete(weak):\r\n\t\t\t\"\"\"Calls onDelete for our BoundMethodWeakref when one of the individual weakrefs (instance or function) dies.\r\n\t\t\t\"\"\"\r\n\t\t\tonDelete(self)\r\n\t\tinst = target.__self__\r\n\t\tfunc = target.__func__\r\n\t\tself.weakInst = weakref.ref(inst, onRefDelete)\r\n\t\tself.weakFunc = weakref.ref(func, onRefDelete)\r\n\r\n\tdef __call__(self):\r\n\t\tinst = self.weakInst()\r\n\t\tif not inst:\r\n\t\t\treturn\r\n\t\tfunc = self.weakFunc()\r\n\t\tassert func, \"inst is alive but func is dead\"\r\n\t\t# Get an instancemethod by binding func to inst.\r\n\t\treturn func.__get__(inst)\r\n\r\ndef _getHandlerKey(handler):\r\n\t\"\"\"Get a key which identifies a handler function.\r\n\tThis is needed because we store weak references, not the actual functions.\r\n\tWe store the key on the weak reference.\r\n\tWhen the handler dies, we can use the key on the weak reference to remove the handler.\r\n\t\"\"\"\r\n\tinst = getattr(handler, \"__self__\", None)\r\n\tif inst:\r\n\t\treturn (id(inst), id(handler.__func__))\r\n\treturn id(handler)\r\n\r\n\r\nclass HandlerRegistrar(object):\r\n\t\"\"\"Base class to Facilitate registration and unregistration of handler functions.\r\n\tThe handlers are stored using weak references and are automatically unregistered\r\n\tif the handler dies.\r\n\tBoth normal functions, instance methods and lambdas are supported. Ensure to keep lambdas alive by maintaining a\r\n\treference to them.\r\n\tThe handlers are maintained in the order they were registered\r\n\tso that they can be called in a deterministic order across runs.\r\n\tThis class doesn't provide any functionality to actually call the handlers.\r\n\tIf you want to implement an extension point,\r\n\tyou probably want the L{Action} or L{Filter} subclasses instead.\r\n\t\"\"\"\r\n\r\n\tdef __init__(self):\r\n\t\t#: Registered handler functions.\r\n\t\t#: This is an OrderedDict where the keys are unique identifiers (as returned by _getHandlerKey)\r\n\t\t#: and the values are weak references.\r\n\t\tself._handlers = collections.OrderedDict()\r\n\r\n\tdef register(self, handler):\r\n\t\t\"\"\"You can register functions, bound instance methods, class methods, static methods or lambdas.\r\n\t\tHowever, the callable must be kept alive by your code otherwise it will be de-registered. This is due to the use\r\n\t\tof weak references. This is especially relevant when using lambdas.\r\n\t\t\"\"\"\r\n\t\t# #9720 (Py3 review required): this method causes unittest to fail in Python 3.\r\n\t\tif hasattr(handler, \"__self__\"):\r\n\t\t\tif not handler.__self__:\r\n\t\t\t\traise TypeError(\"Registering unbound instance methods not supported.\")\r\n\t\t\tweak = BoundMethodWeakref(handler, self.unregister)\r\n\t\telse:\r\n\t\t\tweak = AnnotatableWeakref(handler, self.unregister)\r\n\t\tkey = _getHandlerKey(handler)\r\n\t\t# Store the key on the weakref so we can remove the handler when it dies.\r\n\t\tweak.handlerKey = key\r\n\t\tself._handlers[key] = weak\r\n\r\n\tdef unregister(self, handler):\r\n\t\tif isinstance(handler, (AnnotatableWeakref, BoundMethodWeakref)):\r\n\t\t\tkey = handler.handlerKey\r\n\t\telse:\r\n\t\t\tkey = _getHandlerKey(handler)\r\n\t\ttry:\r\n\t\t\tdel self._handlers[key]\r\n\t\texcept KeyError:\r\n\t\t\treturn False\r\n\t\treturn True\r\n\r\n\t@property\r\n\tdef handlers(self):\r\n\t\t\"\"\"Generator of registered handler functions.\r\n\t\tThis should be used when you want to call the handlers.\r\n\t\t\"\"\"\r\n\t\t# #9067 (py3 review required): handlers is an ordered dictionary.\r\n\t\t# Therefore wrap this inside a list call.\r\n\t\tfor weak in list(self._handlers.values()):\r\n\t\t\thandler = weak()\r\n\t\t\tif not handler:\r\n\t\t\t\tcontinue # Died.\r\n\t\t\tyield handler\r\n\r\n\r\ndef callWithSupportedKwargs(func, *args, **kwargs):\r\n\t\"\"\"Call a function with only the keyword arguments it supports.\r\n\tFor example, if myFunc is defined as:\r\n\tC{def myFunc(a=None, b=None):}\r\n\tand you call:\r\n\tC{callWithSupportedKwargs(myFunc, a=1, b=2, c=3)}\r\n\tInstead of raising a TypeError, myFunc will simply be called like this:\r\n\tC{myFunc(a=1, b=2)}\r\n\r\n\tWhile C{callWithSupportedKwargs} does support positional arguments (C{*args}), usage is strongly discouraged due to the\r\n\trisk of parameter order differences causing bugs.\r\n\r\n\t@param func: can be any callable that is not an unbound method. EG:\r\n\t\t- Bound instance methods\r\n\t\t- class methods\r\n\t\t- static methods\r\n\t\t- functions\r\n\t\t- lambdas\r\n\r\n\t\tThe arguments for the supplied callable, C{func}, do not need to have default values, and can take C{**kwargs} to\r\n\t\tcapture all arguments.\r\n\t\tSee C{tests/unit/test_extensionPoints.py:TestCallWithSupportedKwargs} for examples.\r\n\r\n\t\tAn exception is raised if:\r\n\t\t\t- the number of positional arguments given can not be received by C{func}.\r\n\t\t\t- parameters required (parameters declared with no default value) by C{func} are not supplied.\r\n\t\"\"\"\r\n\tspec = inspect.getargspec(func)\r\n\r\n\t# some handlers are instance/class methods, discard \"self\"/\"cls\" because it is typically passed implicitly.\r\n\tif inspect.ismethod(func):\r\n\t\tspec.args.pop(0)  # remove \"self\"/\"cls\" for instance methods\r\n\t\tif not hasattr(func, \"__self__\"):\r\n\t\t\traise TypeError(\"Unbound instance methods are not handled.\")\r\n\r\n\t# Ensure that the positional args provided by the caller of `callWithSupportedKwargs` actually have a place to go.\r\n\t# Unfortunately, positional args can not be matched on name (keyword) to the names of the params in the handler,\r\n\t# and so calling `callWithSupportedKwargs` is at risk of causing bugs if parameter order differs.\r\n\tnumExpectedArgs = len(spec.args)\r\n\tnumGivenPositionalArgs = len(args)\r\n\tif numGivenPositionalArgs > numExpectedArgs:\r\n\t\traise TypeError(\"Expected to be able to pass {} positional arguments.\".format(numGivenPositionalArgs))\r\n\r\n\t# Ensure that all arguments without defaults which are expected by the handler were provided.\r\n\t# `defaults` is a tuple of default argument values or None if there are no default arguments;\r\n\t# if this tuple has N elements, they correspond to the last N elements listed in args.\r\n\tnumExpectedArgsWithDefaults = len(spec.defaults) if spec.defaults else 0\r\n\tif not spec.defaults or numExpectedArgsWithDefaults != numExpectedArgs:\r\n\t\t# get the names of the args without defaults, skipping the N positional args given to `callWithSupportedKwargs`\r\n\t\t# positionals are required for the Filter extension point.\r\n\t\t# #9067 (Py3 review required): Set construction will work with iterators, too.\r\n\t\tgivenKwargsKeys = set(kwargs.keys())\r\n\t\tfirstArgWithDefault = numExpectedArgs - numExpectedArgsWithDefaults\r\n\t\tspecArgs = set(spec.args[numGivenPositionalArgs:firstArgWithDefault])\r\n\t\tfor arg in specArgs:\r\n\t\t\t# and ensure they are in the kwargs list\r\n\t\t\tif arg not in givenKwargsKeys:\r\n\t\t\t\traise TypeError(\"Parameter required for handler not provided: {}\".format(arg))\r\n\r\n\tif spec.keywords:\r\n\t\t# func has a catch-all for kwargs (**kwargs) so we do not need to filter to just the supported args.\r\n\t\treturn func(*args, **kwargs)\r\n\r\n\tsupportedKwargs = set(spec.args)\r\n\t# #9067 (Py3 review required): originally called dict.keys.\r\n\t# Therefore wrap this inside a list call.\r\n\tfor kwarg in list(kwargs.keys()):\r\n\t\tif kwarg not in supportedKwargs:\r\n\t\t\tdel kwargs[kwarg]\r\n\treturn func(*args, **kwargs)", "path": "source/extensionPoints/util.py"}]}