(self, cls)
| 476 | self.src.append(f'{f' {decorator}\n' if decorator else ''} def {name}({args}):\n{body}') |
| 477 | |
| 478 | def add_fns_to_class(self, cls): |
| 479 | # The source to all of the functions we're generating. |
| 480 | fns_src = '\n'.join(self.src) |
| 481 | |
| 482 | # The locals they use. |
| 483 | local_vars = ','.join(self.locals.keys()) |
| 484 | |
| 485 | # The names of all of the functions, used for the return value of the |
| 486 | # outer function. Need to handle the 0-tuple specially. |
| 487 | if len(self.names) == 0: |
| 488 | return_names = '()' |
| 489 | else: |
| 490 | return_names =f'({",".join(self.names)},)' |
| 491 | |
| 492 | # txt is the entire function we're going to execute, including the |
| 493 | # bodies of the functions we're defining. Here's a greatly simplified |
| 494 | # version: |
| 495 | # def __create_fn__(): |
| 496 | # def __init__(self, x, y): |
| 497 | # self.x = x |
| 498 | # self.y = y |
| 499 | # @recursive_repr |
| 500 | # def __repr__(self): |
| 501 | # return f"cls(x={self.x!r},y={self.y!r})" |
| 502 | # return __init__,__repr__ |
| 503 | |
| 504 | txt = f"def __create_fn__({local_vars}):\n{fns_src}\n return {return_names}" |
| 505 | ns = {} |
| 506 | exec(txt, self.globals, ns) |
| 507 | fns = ns['__create_fn__'](**self.locals) |
| 508 | |
| 509 | # Now that we've generated the functions, assign them into cls. |
| 510 | for name, fn in zip(self.names, fns): |
| 511 | fn.__qualname__ = f"{cls.__qualname__}.{fn.__name__}" |
| 512 | |
| 513 | try: |
| 514 | annotation_fields, return_type = self.method_annotations[name] |
| 515 | except KeyError: |
| 516 | pass |
| 517 | else: |
| 518 | annotate_fn = _make_annotate_function(cls, name, annotation_fields, return_type) |
| 519 | fn.__annotate__ = annotate_fn |
| 520 | |
| 521 | if self.unconditional_adds.get(name, False): |
| 522 | setattr(cls, name, fn) |
| 523 | else: |
| 524 | already_exists = _set_new_attribute(cls, name, fn) |
| 525 | |
| 526 | # See if it's an error to overwrite this particular function. |
| 527 | if already_exists and (msg_extra := self.overwrite_errors.get(name)): |
| 528 | error_msg = (f'Cannot overwrite attribute {fn.__name__} ' |
| 529 | f'in class {cls.__name__}') |
| 530 | if not msg_extra is True: |
| 531 | error_msg = f'{error_msg} {msg_extra}' |
| 532 | |
| 533 | raise TypeError(error_msg) |
| 534 | |
| 535 |
no test coverage detected