eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: I'm having a hard time using the subprocess.run function with a command that contains accentuated characters (like "é" for example). Consider this simple example : # -*- coding: utf-8 -*- import subprocess cmd = "echo é" result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE) print("Output of subprocess.run : {}".format(result.stdout.hex())) print("é char encoded manually : {}".format("é".encode("utf-8").hex()))  It gives the following output : Output of subprocess.run : 820d0a é char encoded manually : c3a9  I don't understand the value returned by subprocess.run, shouldn't it also be c3a9 ? I understand the 0d0a is CR+LF, but why 82 ? Because of this, when I try to run this line : output = result.stdout.decode("utf-8")  I get a UnicodeDecodeError Exception with the following message : 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte I tried explicitly specifying the encoding format like this : result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding="utf-8")  But this raises the same exception ('utf-8' codec can't decode byte 0x82 in position 0: invalid start byte) when subprocess.run is called. I'm running this on Windows 10 with Python3.8.5. I hope someone can help me with this, any hint ?

Answer: As a fix try cp437 decoding: print("Output of subprocess.run : {}".format(result.stdout.decode('cp437'))) # or result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, text=True, encoding="cp437") print(f"Output of subprocess.run : {result.stdout}")   From other stackoverlow answers it seems that Windows terminal code issue is old and probably should be fixed by now, but it seems it still is present. https://stackoverflow.com/a/37260867/11815313 Anyway I have no deeper understanding in Windows 10 terminal encoding, but cp437 worked for my Win10 system. However the Python 3.9.13 documentation 3. Using Python on Windows 3.7. UTF-8 mode states an option to temporarily or permanent (note the caveat mentioned in the documentation) change the encoding.
Question: I'm trying to get a queryset from the cache, but am unsure if this even has a point. I have the following method (simplified) inside a custom queryset:  def queryset_from_cache(self, key: str=None, timeout: int=60): # Generate a key based on the query. if key is None: key = self.__generate_key # () # If the cache has the key, return the cached object. cached_object = cache.get(key, None) # If the cache doesn't have the key, set the cache, # and then return self (from DB) as cached_object if cached_object is None: cached_object = self cache.set(key, cached_object , timeout=timeout) return cached_object  The usage is basically to append it to a django QuerySet method, for example: queryset = MyModel.objects.filter(id__range=[0,99]).queryset_from_cache()   My question: Would usage like this work? Or would it call MyModel.objects.filter(id__range=[0,99]) from the database no matter what?  Since normally caching would be done like this: cached_object = cache.get(key, None) if cached_object is None: cached_object = MyModel.objects.filter(id__range=[0,99]) #Only now call the query cache.set(key, cached_object , timeout=timeout)  And thus the queryset filter() method only gets called when the key is not present in the cache, as opposed to always calling it, and then trying to get it from the cache with the queryset_from_cache method.

Answer: This is a really cool idea, but I'm not sure if you can Cache full-on Objects.. I think it's only attributes Now this having a point. Grom what I'm seeing from the limited code I've seen idk if it does have a point, unless filtering for Jane and John (and only them) is very common. Very narrow. Maybe just try caching ALL the users or just individual Users, and only the attributes you need  Update Yes! you are completetly correct, you can cache full on objects- how cool! I don't think your example method of queryset = MyModel.objects.filter(id__range=[0,99]).queryset_from_cache() would work. but you can do something similar by using Model Managers and do something like: queryset = MyModel.objects.queryset_from_cache(filterdict) Models  Natually you can return just the qs, this is just for the example to show it actually is from the cache  from django.db import models class MyModelManager(models.Manager): def queryset_from_cache(self, filterdict): from django.core.cache import cache cachekey = 'MyModelCache' qs = cache.get(cachekey) if qs: d = { 'in_cache': True, 'qs': qs } else: qs = MyModel.objects.filter(**filterdict) cache.set(cachekey, qs, 300) # 5 min cache d = { 'in_cache': False, 'qs': qs } return d class MyModel(models.Model): name = models.CharField(max_length=200) # # other attributes # objects = MyModelManager()  Example Use from app.models import MyModel filterdict = {'pk__range':[0,99]} r = MyModel.objects.queryset_from_cache(filterdict) print(r['qs'])  While it's not exactly what you wanted, it might be close enough
Question: I am using this code to put all Excel files and sheets into one Excel file, and it works flawlessly. But on some occasions, I want to put them all into a single excel file, but to keep the sheets separate. I know there is "Copy sheet" in Excel, but I want to do it to multiple documents. I am sure pandas has such a function, so I do not have to do this manually. I also want to keep all the data as it was, with no added columns or rows, and keep the name of the sheet as well. If you have an idea, please help. Example:  Workbook1: Sheet1, Sheet2, Sheet3 Workbook2: Sheet11, Sheet22  Apply code...  FinalWorkbook: Sheet1, Sheet2, Sheet3, Sheet11, Sheet22,  This code puts all the data into a single sheet. import os import pandas as pd print("Combine xls and xlsx") cwd = os.path.abspath('') files = os.listdir(cwd) ## get all sheets of a given file df_total = pd.DataFrame() for file in files: # loop through Excel files if file.endswith('.xls') or file.endswith('.xlsx'): excel_file = pd.ExcelFile(file) sheets = excel_file.sheet_names for sheet in sheets: # loop through sheets inside an Excel file print (file, sheet) df = excel_file.parse(sheet_name = sheet) df_total = df_total.append(df) print("Loaded, ENTER to combine:") dali=input() df_total.to_excel('Combined/combined_file.xlsx') print("Done") dali=input() 

Answer: Here is the answer. I hope someone finds this useful. Combines all sheets from all excel files XLS od XLSX to a single excel file with all sheets. import pandas as pd import openpyxl print("Copying sheets from multiple files to one file") cwd = os.path.abspath('') files = os.listdir(cwd) df_total = pd.DataFrame() df_total.to_excel('Combined/combined_file.xlsx') #create a new file workbook=openpyxl.load_workbook('Combined/combined_file.xlsx') ss_sheet = workbook['Sheet1'] ss_sheet.title = 'TempExcelSheetForDeleting' workbook.save('Combined/combined_file.xlsx') for file in files: # loop through Excel files if file.endswith('.xls') or file.endswith('.xlsx'): excel_file = pd.ExcelFile(file) sheets = excel_file.sheet_names for sheet in sheets: # loop through sheets inside an Excel file print (file, sheet) df = excel_file.parse(sheet_name = sheet) with pd.ExcelWriter("Combined/combined_file.xlsx",mode='a') as writer: df.to_excel(writer, sheet_name=f"{sheet}", index=False) #df.to_excel("Combined/combined_file.xlsx", sheet_name=f"{sheet}") workbook=openpyxl.load_workbook('Combined/combined_file.xlsx') std=workbook["TempExcelSheetForDeleting"] workbook.remove(std) workbook.save('Combined/combined_file.xlsx') print("Loaded, press ENTER to end") dali=input() #df_total.to_excel('Combined/combined_file.xlsx') print("Done") dali=input()
Question: I have a numpy array of integers a and an integer x. For each element in a I want to check whether it starts with x (so the elements of a usually have more digits than x, but that's not guaranteed for every element). I was thinking of converting the integers to strings and then checking it with pandas import pandas as pd import numpy as np a = np.array([4141, 4265, 4285, 4, 41656]) x = 42 pd.Series(a).astype(str).str.startswith(str(x)).values # .values returns numpy array instead of pd.Series [False True True False False]  This works and is also quite performant, but for educational purpose I was wondering if there is also an elegant solution doing it numerically in numpy only.

Answer: You can get the number of digits using the log10, then divide as integer: # number of digits of x n = int(np.ceil(np.log10(x+1))) # number of digits in array n2 = np.ceil(np.log10(a+1)).astype(int) # get first n digits of numbers in array out = a//10**np.clip((n2-n), 0, np.inf) == x  output: array([False, True, True, False, False])
Question: The VSCode autocomplete option doesn't work for tensorflow and keras libraries; However i've installed python and pylance extension on it; is there any solution to make it work or not, without install new extension or something like as AI autocomplete; Kite and tabinine? For instance, here i'm trying to use layers or preprocessing from keras API but it doesn't show anything at all   Also notice here the tensorflow version and python version 

Answer: A potentially useful fix:  try adding this to the bottom of your tensorflow/__init__.py # Explicitly import lazy-loaded modules to support autocompletion. # pylint: disable=g-import-not-at-top if _typing.TYPE_CHECKING: from tensorflow_estimator.python.estimator.api._v2 import estimator as estimator from keras.api._v2 import keras from keras.api._v2.keras import losses from keras.api._v2.keras import metrics from keras.api._v2.keras import optimizers from keras.api._v2.keras import initializers # pylint: enable=g-import-not-at-top    Find the location of the tensorflow package and open the __init__.py file in the tensorflow folder   Add the above codes at the bottom of the file   It should be noted that it will be useful to import in the following way import tensorflow as tf tf.keras     Importing in the previous way still can't get intellisense
Question: I would like to specify a custom lookup field on the action (different from the viewset default "pk"), i.e. @action( methods=["GET"], detail=True, url_name="something", url_path="something", lookup_field="uuid", # this does not work unfortunately ) def get_something(self, request, uuid=None): pass  But the router does not generate the correct urls: router = DefaultRouter() router.register(r"test", TestViewSet) router.urls  yields url: '^test/(?P<pk>[^/.]+)/something/$'  instead of '^test/(?P<uuid>[^/.]+)/something/$'  I do not want to change the lookup field for the whole viewset though and have been unsuccessful in finding a way to do this for the action itself after debugging through the router url generation. I did notice that model viewsets have this method: get_extra_action_url_map(self)  but am unsure how to get it to be called to generate custom urls or if it is even relevant. Any help would be great thanks!

Answer: I think it will create much confusion for your API consumers if you have 2 different resource identification on the same resource. You can name that action query_by_uuid or just allow them to use list_view to filter by uuid if you only want to represent the object tho. (so consumers can use /test/?uuid= to retrieve data) But if you really want to do it, you can simply override get_object method to filter for your custom action tho: def get_object(self): if self.action == 'do_something': return get_object_or_404(self.get_queryset(), uuid=self.kwargs['pk']) return super().get_object()  Here is a bit hacky solution for generate uuid in router with detail=False. @action(detail=False, url_path=r'(?P<uuid>[^/.]+)/do_something') def do_something(self, request, uuid=None): pass
Question: I have sales data for different customers on different dates. But the dates are not continuous and I would like to resample the data to daily frequency. How can I do this? MWE import numpy as np import pandas as pd df = pd.DataFrame({'id': list('aababcbc'), 'date': pd.date_range('2022-01-01',periods=8), 'value':range(8)}).sort_values('id') df id date value 0 a 2022-01-01 0 1 a 2022-01-02 1 3 a 2022-01-04 3 2 b 2022-01-03 2 4 b 2022-01-05 4 6 b 2022-01-07 6 5 c 2022-01-06 5 7 c 2022-01-08 7  The required output is following id date value a 2022-01-01 0 a 2022-01-02 1 a 2022-01-03 0 ** there is no data for a in this day a 2022-01-04 3 b 2022-01-03 2 b 2022-01-04 0 ** there is no data for b in this day b 2022-01-05 4 b 2022-01-06 0 ** there is no data for b in this day b 2022-01-07 6 c 2022-01-06 5 c 2022-01-07 0 ** there is no data for c in this day c 2022-01-08 7  My attempt df.groupby(['id']).resample('D',on='date')['value'].sum().reset_index() 

Answer: df["date"] = pd.to_datetime(df["date"]) df.set_index("date").groupby("id").resample("1d").sum()
Question: I have a date 2020-05-31 and the following dataframe, where the column names are statuses:  rejected revocation decision rfe interview premium received rfe_response biometrics withdrawal appeal 196 None None 2020-01-28 None None None 2020-01-16 None None None None 203 None None 2020-06-20 2020-04-01 None None 2020-01-03 2020-08-08 None None None 209 None None 2020-12-03 2020-06-03 None None 2020-01-03 None None None None 213 None None 2020-06-23 None None None 2020-01-27 None 2020-02-19 None None 1449 None None 2020-05-12 None None None 2020-01-06 None None None None 1660 None None 2021-09-23 2021-05-27 None None 2020-01-21 2021-08-17 None None None  I want to get the latest step each row is in, such that the latest steap is on or before the date mentioed above 2020-05-31 So the output for this woud be: 196: decision 203: rfe 209: received 213: biometrics 1449: decision 1660: received  or even a count works: { rejected = 0, revocation = 0, decision = 2, rfe = 1, interview = 0, premium = 0, received = 2, rfe_response = 0, biometrics 0 0, withdrawal = 0, appeal = 0 }  Currently i am looping through each row, where i create a dict of {status: date}, then i sort by date, and take the key of the last value (which is a status) This is very slow and takes forever Is there a simpler or cleaner way of doing it? NOTE: Each row will have atleast one date, in decision column

Answer: you can mask where the date is bigger than the chosen date, then use idxmax along the columns. dt_max = '2020-05-31' res = df.where(df.le(dt_max)).astype('datetime64[ns]')\ .dropna(how='all', axis=0).idxmax(axis=1) print(res) # 196 decision # 203 rfe # 209 received # 213 biometrics # 1449 decision # 1660 received # dtype: object  And for the count, per status, then you can do with value_counts like dict_res = res.value_counts().reindex(df.columns, fill_value=0).to_dict() print(dict_res) #{'rejected': 0, 'revocation': 0, 'decision': 2, 'rfe': 1, 'interview': 0, 'premium': 0, # 'received': 2, 'rfe_response': 0, 'biometrics': 1, 'withdrawal': 0, 'appeal': 0}  EDIT thanks to a comment from @mozway, I added dropna to create res to prevent the method to fail if none of the dates are under the threshold on a row
Question: My requirement is very simple, but I just could not figure out how to reach it. This is the original string ACCCTNGGATGTGGGGGGATGTCCCCCATGTGCTCG, I want to find out all the sub-strings that only consist of [ACGT], end with ATGT, and have a length of at least 8. And what I expect is: GGATGTGGGGGGATGT GGATGTGGGGGGATGTCCCCCATGT  With following code: import re seq = 'ACCCTNGGATGTGGGGGGATGTCCCCCATGTGCTCG' matches = re.findall("[ACGT]{4,}ATGT", seq) if matches: for match in matches: print(match)  I got only GGATGTGGGGGGATGTCCCCCATGT  The shorter one is missing. Then I realized that re.findall doesn't allow overlapping. I found this solution from How to use regex to find all overlapping matches, then I modified the code as: matches = re.findall("(?=([ACGT]{4,}ATGT))", seq)  Then I got: GGATGTGGGGGGATGTCCCCCATGT GATGTGGGGGGATGTCCCCCATGT ATGTGGGGGGATGTCCCCCATGT TGTGGGGGGATGTCCCCCATGT GTGGGGGGATGTCCCCCATGT TGGGGGGATGTCCCCCATGT GGGGGGATGTCCCCCATGT GGGGGATGTCCCCCATGT GGGGATGTCCCCCATGT GGGATGTCCCCCATGT GGATGTCCCCCATGT GATGTCCCCCATGT ATGTCCCCCATGT TGTCCCCCATGT GTCCCCCATGT TCCCCCATGT CCCCCATGT CCCCATGT  Then I realized that this searching starts from right to left. So how can I ask re.findall to search from left to right and also allow for overlapping?

Answer: You can use PyPi's regex module, utilizing reversed and overlapped matching using only a small addition to your initial pattern: (?r)[ACGT]{4,}ATGT  For example: import regex as re seq = 'ACCCTNGGATGTGGGGGGATGTCCCCCATGTGCTCG' matches = re.findall(r'(?r)[ACGT]{4,}ATGT', seq, overlapped=True) print(matches)  Prints: ['GGATGTGGGGGGATGTCCCCCATGT', 'GGATGTGGGGGGATGT']
Question: I've a df like this as shown below. What I'm doing is I'm trying to loop through the df column(s) with paths & printing the image as sub plots one column with image paths at axis0 and other column paths parallely on axis1 as follows.  identity VGG-Face_cosine img comment 0 ./clip_v4/3.png 1.110223e-16 .\clip_v3\0.png .\clip_v3\0.png is matched with ./clip_v4/3.png 0 ./clip_v4/2.png 2.220446e-16 .\clip_v3\1.png .\clip_v3\1.png is matched with ./clip_v4/2.png 1 ./clip_v4/4.png 2.220446e-16 .\clip_v3\1.png .\clip_v3\1.png is matched with ./clip_v4/4.png 2 ./clip_v4/5.png 2.220446e-16 .\clip_v3\1.png .\clip_v3\1.png is matched with ./clip_v4/5.png 0 ./clip_v4/2.png 2.220446e-16 .\clip_v3\2.png .\clip_v3\2.png is matched with  I'm looping through these 2 columns identity and img columns & plotting as follows import pandas as pd import matplotlib.pyplot as plt import matplotlib.image as mpimg from matplotlib import rcParams df = df.iloc[1:] #merged_img = [] for index, row in df.iterrows(): # figure size in inches optional rcParams['figure.figsize'] = 11 ,8 # read images img_A = mpimg.imread(row['identity']) img_B = mpimg.imread(row['img']) # display images fig, ax = plt.subplots(1,2) ax[0].imshow(img_A) ax[1].imshow(img_B)  sample output I got. ###Console output  Upto now it's fine. My next idea is to save these images as it is with sublots on PDF. I don't want to change the structure the way it prints. Like I just want 2 images side by side in PDF too. I've went through many available solutions. But, I can't relate my part of code with the logic avaiable in documentation. Is there is any way to achieve my goal?. Any references would be helpful!!. Thanks in advance.

Answer: Use PdfPages from matplotlib.backends.backend_pdf to save figures one by one on separate pages of the same pdf-file: import pandas as pd import matplotlib.pyplot as plt import matplotlib.image as mpimg from matplotlib import rcParams from matplotlib.backends.backend_pdf import PdfPages df = df.iloc[1:] rcParams['figure.figsize'] = 11 ,8 pdf_file_name = 'my_images.pdf' with PdfPages(pdf_file_name) as pdf: for index, row in df.iterrows(): img_A = mpimg.imread(row['identity']) img_B = mpimg.imread(row['img']) fig, ax = plt.subplots(1,2) ax[0].imshow(img_A) ax[1].imshow(img_B) # save the current figure at a new page in pdf_file_name pdf.savefig()  See also https://matplotlib.org/stable/api/backend_pdf_api.html
Question: I have a dictionary which I want to convert to multilevel column dataframe and the index will be the most outer keys of the dictionary. my_dict = {'key1': {'sub-key1': {'sub-sub-key1':'a','sub-sub-key2':'b'}, 'sub-key2': {'sub-sub-key1':'aa','sub-sub-key2':'bb'}}, 'key2': {'sub-key1': {'sub-sub-key1':'c','sub-sub-key2':'d'}, 'sub-key2': {'sub-sub-key1':'cc','sub-sub-key2':'dd'}}}  My desired output should look like:  sub-key1 sub-key2 sub-sub-key1 sub-sub-key2 sub-sub-key1 sub-sub-key2 key1 a b aa bb key2 c d cc dd  I tried to use concat with pd.concat({k: pd.DataFrame.from_dict(my_dict, orient='index') for k, v in d.items()}, axis=1) but the result is not as expected. I also tried to reform the dictionary. reformed_dict = {} for outerKey, innerDict in my_dict.items(): for innerKey, values in innerDict.items(): reformed_dict[(outerKey, innerKey)] = values pd.DataFrame(reformed_dict)  Again the result was not ok. The highest level column and index are interchanged. Is there any other way to do this?

Answer: You were pretty close with concat, need to unstack after so like res = pd.concat({k: pd.DataFrame.from_dict(v, orient='columns') for k, v in my_dict.items()} ).unstack() print(res) # sub-key1 sub-key2 # sub-sub-key1 sub-sub-key2 sub-sub-key1 sub-sub-key2 # key1 a b aa bb # key2 c d cc dd
Question: I have a table like this:     id name doggo floofer puppo pupper     1 rowa NaN NaN NaN NaN   2 ray NaN NaN NaN NaN   3 emma NaN NaN NaN pupper   4 sophy doggo NaN NaN NaN   5 jack NaN NaN NaN NaN   6 jimmy NaN NaN puppo NaN   7 bingo NaN NaN NaN NaN   8 billy NaN NaN NaN pupper   9 tiger NaN floofer NaN NaN   10 lucy NaN NaN NaN NaN     I want the (doggo, floofer, puppo, pupper) columns to be in a single category column (dog_type). Note: The NaN should also be NaN in the column since not all the dogs were categorized. But after using: df1 = df.melt(id_vars = ['id', 'name'], value_vars = ['doggo', 'floofer', 'pupper', 'puppo'], var_name = 'dog_types', ignore_index = True)  The melted df is now duplicated to 40 rows:  id name dog_types value 0 1 rowa doggo NaN 1 2 ray doggo NaN 2 3 emma doggo NaN 3 4 sophy doggo doggo 4 5 jack doggo NaN 5 6 jimmy doggo NaN 6 7 bingo doggo NaN 7 8 billy doggo NaN 8 9 tiger doggo NaN 9 10 lucy doggo NaN 10 1 rowa floofer NaN 11 2 ray floofer NaN 12 3 emma floofer NaN 13 4 sophy floofer NaN 14 5 jack floofer NaN 15 6 jimmy floofer NaN 16 7 bingo floofer NaN 17 8 billy floofer NaN 18 9 tiger floofer floofer 19 10 lucy floofer NaN 20 1 rowa pupper NaN 21 2 ray pupper NaN 22 3 emma pupper pupper 23 4 sophy pupper NaN 24 5 jack pupper NaN 25 6 jimmy pupper NaN 26 7 bingo pupper NaN 27 8 billy pupper pupper 28 9 tiger pupper NaN 29 10 lucy pupper NaN 30 1 rowa puppo NaN 31 2 ray puppo NaN 32 3 emma puppo NaN 33 4 sophy puppo NaN 34 5 jack puppo NaN 35 6 jimmy puppo puppo 36 7 bingo puppo NaN 37 8 billy puppo NaN 38 9 tiger puppo NaN 39 10 lucy puppo NaN  How I do get the correct results without duplicates?

Answer: df['dog_types'] = (df['doggo'].fillna(df['floofer']) .fillna(df['puppo']) .fillna(df['pupper']))   id name doggo floofer puppo pupper dog_types 0 1 rowa NaN NaN NaN NaN NaN 1 2 ray NaN NaN NaN NaN NaN 2 3 emma NaN NaN NaN pupper pupper 3 4 sophy doggo NaN NaN NaN doggo 4 5 jack NaN NaN NaN NaN NaN 5 6 jimmy NaN NaN puppo NaN puppo 6 7 bingo NaN NaN NaN NaN NaN 7 8 billy NaN NaN NaN pupper pupper 8 9 tiger NaN floofer NaN NaN floofer 9 10 lucy NaN NaN NaN NaN NaN  Afterwards you can drop redundant columns: df.drop(columns=['doggo', 'floofer', 'puppo', 'pupper'], inplace=True)   id name dog_types 0 1 rowa NaN 1 2 ray NaN 2 3 emma pupper 3 4 sophy doggo 4 5 jack NaN 5 6 jimmy puppo 6 7 bingo NaN 7 8 billy pupper 8 9 tiger floofer 9 10 lucy NaN
Question: python's TypeVar inference broken when using lru_cache decorator. For example, after applying mypy the following example, only function with lru_cache causes error like: main.py:14: error: Incompatible types in assignment (expression has type "T", variable has type "int") Found 1 error in 1 file (checked 1 source file)  and pyright's editor support also warn the same thing. Is this lru_cache's own limitation or is there some good workaround? from functools import lru_cache from typing import TypeVar T = TypeVar("T") def working(foo: T) -> T: return foo @lru_cache(maxsize=None) def not_working(foo: T) -> T: return foo a: int = working(1) b: int = not_working(1) 

Answer: Here's the relevant parts of the lru_cache type hints _T = TypeVar("_T") class _lru_cache_wrapper(Generic[_T]): __wrapped__: Callable[..., _T] def __call__(self, *args: Hashable, **kwargs: Hashable) -> _T: ... def lru_cache( maxsize: int | None = ..., typed: bool = ... ) -> Callable[[Callable[..., _T]], _lru_cache_wrapper[_T]]: ...  so it appears that, in its attempts to allow for any argument set, it loses any connection between the input and output types and so is unable to refine T to int. You may have to wrap lru_cache locally to fix this. You may be able to use ParamSpec, but you might find difficulties with that, see the note below. If you only need it for a small set of function types (unary, binary, ternary), you could wrap it for those. Apparently they did actually fix this with ParamSpec but from a cursory reading it appears to break other things so they reverted it. This issue also discusses it.