|
2598 | 2598 | "print(dataclass_src(DC))" |
2599 | 2599 | ] |
2600 | 2600 | }, |
| 2601 | + { |
| 2602 | + "cell_type": "code", |
| 2603 | + "execution_count": null, |
| 2604 | + "metadata": {}, |
| 2605 | + "outputs": [], |
| 2606 | + "source": [ |
| 2607 | + "#| export\n", |
| 2608 | + "def nullable_dc(cls):\n", |
| 2609 | + " \"Like `dataclass`, but default of `None` added to fields without defaults\"\n", |
| 2610 | + " from dataclasses import dataclass, field\n", |
| 2611 | + " from inspect import get_annotations\n", |
| 2612 | + " for k,v in get_annotations(cls).items():\n", |
| 2613 | + " if not hasattr(cls,k): setattr(cls, k, field(default=None))\n", |
| 2614 | + " return dataclass(cls)" |
| 2615 | + ] |
| 2616 | + }, |
| 2617 | + { |
| 2618 | + "cell_type": "code", |
| 2619 | + "execution_count": null, |
| 2620 | + "metadata": {}, |
| 2621 | + "outputs": [ |
| 2622 | + { |
| 2623 | + "data": { |
| 2624 | + "text/plain": [ |
| 2625 | + "Person(name='Bob', age=None, city='Unknown')" |
| 2626 | + ] |
| 2627 | + }, |
| 2628 | + "execution_count": null, |
| 2629 | + "metadata": {}, |
| 2630 | + "output_type": "execute_result" |
| 2631 | + } |
| 2632 | + ], |
| 2633 | + "source": [ |
| 2634 | + "@nullable_dc\n", |
| 2635 | + "class Person: name: str; age: int; city: str = \"Unknown\"\n", |
| 2636 | + "Person(name=\"Bob\")" |
| 2637 | + ] |
| 2638 | + }, |
| 2639 | + { |
| 2640 | + "cell_type": "code", |
| 2641 | + "execution_count": null, |
| 2642 | + "metadata": {}, |
| 2643 | + "outputs": [], |
| 2644 | + "source": [ |
| 2645 | + "#| export\n", |
| 2646 | + "def make_nullable(cls):\n", |
| 2647 | + " from dataclasses import dataclass, fields, MISSING\n", |
| 2648 | + " if hasattr(cls, '_nullable'): return\n", |
| 2649 | + " cls._nullable = True\n", |
| 2650 | + "\n", |
| 2651 | + " @patch\n", |
| 2652 | + " def __init__(self:cls, *args, **kwargs):\n", |
| 2653 | + " flds = fields(cls)\n", |
| 2654 | + " dargs = {k.name:v for k,v in zip(flds, args)}\n", |
| 2655 | + " for f in flds:\n", |
| 2656 | + " nm = f.name\n", |
| 2657 | + " if nm not in dargs and nm not in kwargs and f.default is None and f.default_factory is MISSING:\n", |
| 2658 | + " kwargs[nm] = None\n", |
| 2659 | + " self._orig___init__(*args, **kwargs)\n", |
| 2660 | + " \n", |
| 2661 | + " for f in fields(cls):\n", |
| 2662 | + " if f.default is MISSING and f.default_factory is MISSING: f.default = None" |
| 2663 | + ] |
| 2664 | + }, |
| 2665 | + { |
| 2666 | + "cell_type": "code", |
| 2667 | + "execution_count": null, |
| 2668 | + "metadata": {}, |
| 2669 | + "outputs": [ |
| 2670 | + { |
| 2671 | + "data": { |
| 2672 | + "text/plain": [ |
| 2673 | + "Person(name='Bob', age=None, city='NY')" |
| 2674 | + ] |
| 2675 | + }, |
| 2676 | + "execution_count": null, |
| 2677 | + "metadata": {}, |
| 2678 | + "output_type": "execute_result" |
| 2679 | + } |
| 2680 | + ], |
| 2681 | + "source": [ |
| 2682 | + "@dataclass\n", |
| 2683 | + "class Person: name: str; age: int; city: str = \"Unknown\"\n", |
| 2684 | + "\n", |
| 2685 | + "make_nullable(Person)\n", |
| 2686 | + "Person(\"Bob\", city='NY')" |
| 2687 | + ] |
| 2688 | + }, |
| 2689 | + { |
| 2690 | + "cell_type": "code", |
| 2691 | + "execution_count": null, |
| 2692 | + "metadata": {}, |
| 2693 | + "outputs": [ |
| 2694 | + { |
| 2695 | + "data": { |
| 2696 | + "text/plain": [ |
| 2697 | + "Person(name='Bob', age=None, city='Unknown')" |
| 2698 | + ] |
| 2699 | + }, |
| 2700 | + "execution_count": null, |
| 2701 | + "metadata": {}, |
| 2702 | + "output_type": "execute_result" |
| 2703 | + } |
| 2704 | + ], |
| 2705 | + "source": [ |
| 2706 | + "Person(name=\"Bob\")" |
| 2707 | + ] |
| 2708 | + }, |
| 2709 | + { |
| 2710 | + "cell_type": "code", |
| 2711 | + "execution_count": null, |
| 2712 | + "metadata": {}, |
| 2713 | + "outputs": [ |
| 2714 | + { |
| 2715 | + "data": { |
| 2716 | + "text/plain": [ |
| 2717 | + "Person(name='Bob', age=34, city='Unknown')" |
| 2718 | + ] |
| 2719 | + }, |
| 2720 | + "execution_count": null, |
| 2721 | + "metadata": {}, |
| 2722 | + "output_type": "execute_result" |
| 2723 | + } |
| 2724 | + ], |
| 2725 | + "source": [ |
| 2726 | + "Person(\"Bob\", 34)" |
| 2727 | + ] |
| 2728 | + }, |
| 2729 | + { |
| 2730 | + "cell_type": "code", |
| 2731 | + "execution_count": null, |
| 2732 | + "metadata": {}, |
| 2733 | + "outputs": [], |
| 2734 | + "source": [ |
| 2735 | + "#| export\n", |
| 2736 | + "def mk_dataclass(cls):\n", |
| 2737 | + " from dataclasses import dataclass, field, is_dataclass, MISSING\n", |
| 2738 | + " from inspect import get_annotations\n", |
| 2739 | + " if is_dataclass(cls): return make_nullable(cls)\n", |
| 2740 | + " for k,v in get_annotations(cls).items():\n", |
| 2741 | + " if not hasattr(cls,k) or getattr(cls,k) is MISSING:\n", |
| 2742 | + " setattr(cls, k, field(default=None))\n", |
| 2743 | + " dataclass(cls, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)" |
| 2744 | + ] |
| 2745 | + }, |
| 2746 | + { |
| 2747 | + "cell_type": "code", |
| 2748 | + "execution_count": null, |
| 2749 | + "metadata": {}, |
| 2750 | + "outputs": [ |
| 2751 | + { |
| 2752 | + "data": { |
| 2753 | + "text/plain": [ |
| 2754 | + "Person(name='Bob', age=None, city='Unknown')" |
| 2755 | + ] |
| 2756 | + }, |
| 2757 | + "execution_count": null, |
| 2758 | + "metadata": {}, |
| 2759 | + "output_type": "execute_result" |
| 2760 | + } |
| 2761 | + ], |
| 2762 | + "source": [ |
| 2763 | + "class Person: name: str; age: int; city: str = \"Unknown\"\n", |
| 2764 | + "\n", |
| 2765 | + "mk_dataclass(Person)\n", |
| 2766 | + "Person(name=\"Bob\")" |
| 2767 | + ] |
| 2768 | + }, |
2601 | 2769 | { |
2602 | 2770 | "cell_type": "markdown", |
2603 | 2771 | "metadata": {}, |
|
0 commit comments