merge two lists, maintaining ordering as much as possible. this is to reconcile vars(cls) with cls.__annotations__. Example:: >>> a = ["__tablename__", "id", "x", "created_at"] >>> b = ["id", "name", "data", "y", "created_at"] >>> merge_lists_w_ordering(a, b)
(a: List[Any], b: List[Any])
| 56 | |
| 57 | |
| 58 | def merge_lists_w_ordering(a: List[Any], b: List[Any]) -> List[Any]: |
| 59 | """merge two lists, maintaining ordering as much as possible. |
| 60 | |
| 61 | this is to reconcile vars(cls) with cls.__annotations__. |
| 62 | |
| 63 | Example:: |
| 64 | |
| 65 | >>> a = ["__tablename__", "id", "x", "created_at"] |
| 66 | >>> b = ["id", "name", "data", "y", "created_at"] |
| 67 | >>> merge_lists_w_ordering(a, b) |
| 68 | ['__tablename__', 'id', 'name', 'data', 'y', 'x', 'created_at'] |
| 69 | |
| 70 | This is not necessarily the ordering that things had on the class, |
| 71 | in this case the class is:: |
| 72 | |
| 73 | class User(Base): |
| 74 | __tablename__ = "users" |
| 75 | |
| 76 | id: Mapped[int] = mapped_column(primary_key=True) |
| 77 | name: Mapped[str] |
| 78 | data: Mapped[Optional[str]] |
| 79 | x = Column(Integer) |
| 80 | y: Mapped[int] |
| 81 | created_at: Mapped[datetime.datetime] = mapped_column() |
| 82 | |
| 83 | But things are *mostly* ordered. |
| 84 | |
| 85 | The algorithm could also be done by creating a partial ordering for |
| 86 | all items in both lists and then using topological_sort(), but that |
| 87 | is too much overhead. |
| 88 | |
| 89 | Background on how I came up with this is at: |
| 90 | https://gist.github.com/zzzeek/89de958cf0803d148e74861bd682ebae |
| 91 | |
| 92 | """ |
| 93 | overlap = set(a).intersection(b) |
| 94 | |
| 95 | result = [] |
| 96 | |
| 97 | current, other = iter(a), iter(b) |
| 98 | |
| 99 | while True: |
| 100 | for element in current: |
| 101 | if element in overlap: |
| 102 | overlap.discard(element) |
| 103 | other, current = current, other |
| 104 | break |
| 105 | |
| 106 | result.append(element) |
| 107 | else: |
| 108 | result.extend(other) |
| 109 | break |
| 110 | |
| 111 | return result |
| 112 | |
| 113 | |
| 114 | def coerce_to_immutabledict(d: Mapping[_KT, _VT]) -> immutabledict[_KT, _VT]: |