Recursively merge multiple values, combining attributes and dict items.
(values, policy: EvaluationPolicy)
| 1209 | |
| 1210 | |
| 1211 | def _merge_values(values, policy: EvaluationPolicy): |
| 1212 | """Recursively merge multiple values, combining attributes and dict items.""" |
| 1213 | if len(values) == 1: |
| 1214 | return values[0] |
| 1215 | |
| 1216 | types = {type(v) for v in values} |
| 1217 | merged_items = None |
| 1218 | key_values = {} |
| 1219 | attributes = set() |
| 1220 | for v in values: |
| 1221 | if policy.can_call(v.__dir__): |
| 1222 | attributes.update(dir(v)) |
| 1223 | try: |
| 1224 | if policy.can_call(v.items): |
| 1225 | try: |
| 1226 | for k, val in v.items(): |
| 1227 | key_values.setdefault(k, []).append(val) |
| 1228 | except Exception as e: |
| 1229 | pass |
| 1230 | elif policy.can_call(v.keys): |
| 1231 | try: |
| 1232 | for k in v.keys(): |
| 1233 | key_values.setdefault(k, []).append(None) |
| 1234 | except Exception as e: |
| 1235 | pass |
| 1236 | except Exception as e: |
| 1237 | pass |
| 1238 | |
| 1239 | if key_values: |
| 1240 | merged_items = { |
| 1241 | k: _merge_values(vals, policy) if vals[0] is not None else None |
| 1242 | for k, vals in key_values.items() |
| 1243 | } |
| 1244 | |
| 1245 | if len(types) == 1: |
| 1246 | t = next(iter(types)) |
| 1247 | if t not in (dict,) and not ( |
| 1248 | hasattr(next(iter(values)), "__getitem__") |
| 1249 | and ( |
| 1250 | hasattr(next(iter(values)), "items") |
| 1251 | or hasattr(next(iter(values)), "keys") |
| 1252 | ) |
| 1253 | ): |
| 1254 | if t in (list, set, tuple): |
| 1255 | return t |
| 1256 | return values[0] |
| 1257 | |
| 1258 | return _Duck(attributes=dict.fromkeys(attributes), items=merged_items) |
| 1259 | |
| 1260 | |
| 1261 | def _infer_return_value(node: ast.FunctionDef, context: EvaluationContext): |
no test coverage detected
searching dependent graphs…