Совет по использованию патч-файла в django для установленной библиотеки

Я использую rest_framework_simple_api_key в своем производственном приложении на python версии 3.9. При выполнении команды

python generate_fernet_keymanage.py как указано в doc(djangorestframework-simple-apikey) я получаю

File "C:\Users\DELL\anaconda3\lib\site-packages\rest_framework_simple_api_key\models.py", line 15, in <module>
class AbstractAPIKeyManager(models.Manager):
File "C:\Users\DELL\anaconda3\lib\site-packages\rest_framework_simple_api_key\models.py", line 16, in AbstractAPIKeyManager
def get_api_key(self, pk: int | str):
TypeError: unsupported operand type(s) for |: 'type' and 'type'

При поиске я получил ошибку, которая заключается в том, что Ошибка TypeError: неподдерживаемый тип(ы) операнда(ов) для |: 'type' и 'type' вызвана использованием синтаксиса int | str для подсказки типа, который поддерживается только в Python 3.10 и более поздних версиях. Я не могу изменить версию Python, так как он находится в производстве, поэтому я наткнулся на решение monkey patching, а затем получил эту статью https://medium.com/lemon-code/monkey-patch-f1de778d61d3. мой файл monkey_patch.py:

def patch_get_api_key():
    print("*********************************EXE****************************************")
    """
    Monkey patch for AbstractAPIKeyManager.get_api_key method to replace the type hint.
    """
    from typing import Union
    def patched_get_api_key(self, pk: Union[int, str]):
        try:
            print("Patched get_api_key method")
            return self.get(pk=pk)
        except self.model.DoesNotExist:
            return None
    print("Before import")
    import rest_framework_simple_api_key.models as models
    print("After import")    
models.AbstractAPIKeyManager.get_api_key = patched_get_api_key

Я добавил код в свой файл apps.py:

# myapp/apps.py

from django.apps import AppConfig

class MyCustomAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'roomroot'

    def ready(self):
        """ Load monkey patching. """
        try:
            from .monkey_patch import patch_get_api_key
            patch_get_api_key()
        except ImportError:
            pass

и вызвал его в файле manage.py:

def main():
    """Run administrative tasks."""
    
    settings_module = "roomroot.deployment" if "WEBSITEHOSTNAME" in os.environ else  "roomroot.settings"

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_module)
    from roomroot.monkey_patch import patch_get_api_key
    patch_get_api_key()

при выполнении команды generate_fernet_key я получаю ошибку:

python manage.py generate_fernet_key
*********************************EXE****************************************
Before import
Traceback (most recent call last):
File "F:\Abha\Room_Reveal\Backend\roomroot\manage.py", line 27, in <module>
main()
File "F:\Abha\Room_Reveal\Backend\roomroot\manage.py", line 14, in main
patch_get_api_key()
File "F:\Abha\Room_Reveal\Backend\roomroot\roomroot\monkey_patch.py", line 18, in patch_get_api_key
from rest_framework_simple_api_key.models import AbstractAPIKeyManager
File "C:\Users\DELL\anaconda3\lib\site-packages\rest_framework_simple_api_key\models.py", line 15, in <module>
class AbstractAPIKeyManager(models.Manager):
File "C:\Users\DELL\anaconda3\lib\site-packages\rest_framework_simple_api_key\models.py", line 16, in AbstractAPIKeyManager
def get_api_key(self, pk: int | str):
TypeError: unsupported operand type(s) for |: 'type' and 'type'

Мой вопрос заключается в том, что использование патча для решения этой ошибки является хорошей идеей? Также я попробовал вызвать patch_get_api_key() в файле setting.py, но все равно получаю ошибку типа.

Никакое количество обезьяньих исправлений не поможет вам решить эту проблему. Чтобы наложить обезьяний патч на метод, необходимо импортировать модуль, а при импорте/загрузке модуля определение класса и, следовательно, определение метода произойдет, вызвав TypeError, прежде чем у вас появится шанс наложить патч.

У вас есть два разумных решения:

  1. Перейдите на Python 3.10
  2. .
  3. Зафиксируйте пакет, вызвавший ошибку, и сделайте его совместимым с Python 3.9 (версией, которую вы используете), или попросите сопровождающего пакета сделать его совместимым.
Вернуться на верх