Уведомления

Группа в Telegram: @pythonsu

#1 Май 21, 2021 20:12:34

Master_Sergius
Зарегистрирован: 2013-09-12
Сообщения: 271
Репутация: +  7  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

Здравствуйте, мне понравилось обсуждение моего предыдущего дурацкого вопроса http://python.su/forum/topic/40304/, и я решил замутить еще одно

Начнем с сути проблемы: есть апишка (всё та же, но не суть), все ответы которой представляются в сдк как объекты/модели (можно сказать, аналог ORM):

  
class User:
    first_name = None
    last_name = None
    position = None
 
users = group_and_users_client.list_users()
 
# сырой ответ от API: [{"userId": "xxx", "firstName": "John", "lastName": "Connor", "position": "Tester"}]
# в переменной users будет список объектов типа User такого вида:
 
for user in users:
     print(user.first_name, user.last_name, user.position)

Есть Enum Positions:

  
from aenum import Enum, extend_enum
 
 
class Position(
    str,
    Enum
):
    DEV = "DEV"
    TESTER = "TESTER"
    MANAGER = "MANAGER"
 
    @classmethod
    def _missing_(cls, value):
        value_upper_case = value.upper()
        try:
            return getattr(cls, value_upper_case)
        except:
            extend_enum(Position, value_upper_case, value_upper_case)
            return getattr(cls, value_upper_case)

То есть, если нет позиции в списке, то список расширяется спокойно. Даже не спрашивайте, почему так )
Фокус в том, что есть наследование от класса User:
   
class Dev(User):
   position = 'DEV'
 
class Tester(User):
   position = 'TESTER'
 
class MANAGER(User):
   position = 'MANAGER'

И вот, если есть позиция в Enum, то возвращается соответствующая модель, а если позиции нет в списке, то возвращается базовый класс User, где position = Position(“any_position”)
Итого, получается, что в тех известных моделях, position - строчка (str), а в базовой модели - Position.

Выходит наша sdk возвращает несовместимые типы позиций:

  
for user in users:
   print(user.position, type(user.position))
  
# выхлоп (AQA - Automation QA):
DEV <class 'str'>
TESTER <class 'str'>
Position.AQA <aenum 'Position'>

И вот задача, надо сделать типы совестимыми, но, блин, без breaking change!!!
То есть, выходит, что вдруг кто-то решал для себя проблему таким образом:
   
if isinstance(user.position, str):
   print(user.position)
else:
   print(user.position.value)
 
# или наоборот
if isinstance(user.position, Position):
   print(user.position.value)
else:
   print(user.position)

то, надо сделать так, чтобы и оно работало и просто все position были строчками!!!

Пока что мне удалось придумать лишь половину решения:
 class PositionWrapper(str):
    def __new__(cls, position):
        if isinstance(position, Enum):
            return str.__new__(cls, position.value)
        return str.__new__(cls, position)
 
    def __init__(self, position):
        self.position = position
 
    def __str__(self):
        return self.value
 
    @property
    def value(self):
        if isinstance(self.position, Enum):
            return self.position.value
        return self.position 

А вот наследоваться от Position никак нельзя:
  File "/Users/bserhii/Projects/work/okta/venv/lib/python3.8/site-packages/aenum/__init__.py", line 1638, in __prepare__
    member_type, first_enum = metacls._get_mixins_(bases)
  File "/Users/bserhii/Projects/work/okta/venv/lib/python3.8/site-packages/aenum/__init__.py", line 2263, in _get_mixins_
    raise TypeError("cannot extend enumerations via subclassing")
TypeError: cannot extend enumerations via subclassing

В общем, что делать?



———————————————————————————
Мой блог о семействе *nix: http://nixtravelling.blogspot.com/

Отредактировано Master_Sergius (Май 21, 2021 20:13:35)

Офлайн

#2 Май 21, 2021 21:11:52

AD0DE412
Зарегистрирован: 2019-05-12
Сообщения: 1130
Репутация: +  44  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

кхм кхм эээ ок enum неизменяемый но вам нужно сделать его ну или что бы это походило на “изменяемый” enum так?
и второе без изменений в существующем коде (новый добавить можно)



1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Отредактировано AD0DE412 (Май 21, 2021 21:28:47)

Офлайн

#3 Май 21, 2021 21:27:57

Master_Sergius
Зарегистрирован: 2013-09-12
Сообщения: 271
Репутация: +  7  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

Мне нужно сделать, чтобы:
1)
Вместо такого:

  
for user in users:
   print(user.position)
   
# выхлоп (AQA - Automation QA):
DEV <class 'str'>
TESTER <class 'str'>
Position.AQA <aenum 'Position'>

было что-то вроде такого:
  
for user in users:
   print(user.position)
   
# выхлоп (AQA - Automation QA):
DEV <class 'str'>
TESTER <class 'str'>
AQA <class 'str'>

2) не внести “breaking change”, то есть не поломать то, что могло б работать для других юзеров, то есть, если вдруг они обходили проблему через проверку инстансов, чтоб привести все к одному виду.



———————————————————————————
Мой блог о семействе *nix: http://nixtravelling.blogspot.com/

Офлайн

#4 Май 21, 2021 21:29:45

AD0DE412
Зарегистрирован: 2019-05-12
Сообщения: 1130
Репутация: +  44  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

John Crawford 13 Мар 2019 в 20:00 ?
зы хотя скоре всего нет
наверное вы уже прошерстили че как и где в этих интернетах



1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Отредактировано AD0DE412 (Май 21, 2021 21:32:17)

Офлайн

#5 Май 21, 2021 21:43:50

Master_Sergius
Зарегистрирован: 2013-09-12
Сообщения: 271
Репутация: +  7  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

Не уверен, что это поможет, разве что переписать по-другому класс Position и тогда плясать оттуда.
Даже не знаю, как без “breaking change” чтоб для “старых” пользователей нашей SDK работало это:

   
for user in users:
   if isinstance(user.position, str):
      print(user.position)
   else:
      print(user.position.value)
  
# или наоборот
for user in users:
   if isinstance(user.position, Position):
      print(user.position.value)
   else:
      print(user.position)

А для “новых” пользователей SDK работало это:

  
for user in users:
   print(user.position)

И всюду чтоб одинаковый тип… бред… но насяльнике хочет, чтоб без “breaking change”



———————————————————————————
Мой блог о семействе *nix: http://nixtravelling.blogspot.com/

Офлайн

#6 Май 21, 2021 21:50:22

AD0DE412
Зарегистрирован: 2019-05-12
Сообщения: 1130
Репутация: +  44  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

ну там вроде уникальность теряется
вернее ... объекты эээ исходные и то что получилось не true



1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Отредактировано AD0DE412 (Май 21, 2021 21:55:52)

Офлайн

#7 Май 21, 2021 22:39:23

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2741
Репутация: +  183  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

> В общем, что делать?

Нормально проектировать программу, а не заниматься ерундой. У тебя position должен быть перечислением. Множественное наследование из класса Position нужно удалить и всё отрефакторить.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#8 Май 22, 2021 04:11:55

AD0DE412
Зарегистрирован: 2019-05-12
Сообщения: 1130
Репутация: +  44  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

Rodegast ну так там у нее/него там ситуация



1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Офлайн

#9 Май 22, 2021 06:31:24

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

AD0DE412
ну так там у нее/него там ситуация
Ну так а некоторые высочайшим указом повелевают числу пи стать равным трем. Посылать надо “насяльнике ” вот и все.

Master_Sergius
но насяльнике хочет, чтоб без “breaking change”
Master_Sergius
что вдруг кто-то решал для себя проблему таким образом….
странное у вас понимание “breaking change”. “breaking change” Это когда нарушаются соглашения декларируемые в документации к продукту. Для нормальных продуктов это означает что новая версия продукта перестала проходить тесты.

Ваша задача поменять класс на строку и прогнать тесты. А если кто-то там, например в китае, поковырялся в носу и написал код полагаясь на интроспекцию свою мудрость и еще незнамо что, так это не ваша проблема. Китайцев много, а караван идет.



Офлайн

#10 Май 22, 2021 14:56:55

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2741
Репутация: +  183  -
Профиль   Отправить e-mail  

Один объект, который ведет себя как два разных объекта

> ну так там у нее/него там ситуация

А почему у него такая ситуация? Да потому что “наша sdk возвращает несовместимые типы позиций”. В место того что бы исправить ошибку и возвращать данные одного типа они предложили её костылём закрыть, а теперь при помощи другого костыля они этот костыль чинят.
С таким подходом “ситуации” для них уже должны быть нормой.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version