Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to define custom transmute? #97

Open
xbanke opened this issue Jun 5, 2020 · 1 comment
Open

how to define custom transmute? #97

xbanke opened this issue Jun 5, 2020 · 1 comment
Labels
enhancement New feature or request
Projects

Comments

@xbanke
Copy link

xbanke commented Jun 5, 2020

  • typical version: 2.0.15
  • Python version: 3.7.4
  • Operating System: Centos

Description

Hey, @seandstewart . There's some cases which user want to define custom transmute:

import json
import typic
from typing import Any

@typic.klass
class Foo:
    a: int
    b: str
    
    @classmethod
    def transmute(cls, v: Any) -> 'Foo':
        if isinstance(v, str):
            try:
                v = json.loads(v)
            except:
                pass
        if isinstance(v, str):
            v = v.split(',')
        if isinstance(v, list):
            return cls(*v)
        return typic.transmute(cls, v)

Expect:

Foo.transmute('1,abc')
# >>> Foo(a=1, b='abc')

However, after decorated by typic.klass, transmute is replaced.

What I Did

Currently, I have to define a metaclass as following:

import json
import typic
from typing import Any, Dict, Tuple, Type
from types import MethodType

class FooMeta(type):
    def __new__(mcs, name: str, bases: Tuple[Type, ...], namespace: Dict[str, Any]):
        cls = type.__new__(mcs, name, bases, namespace)
        transmute = getattr(cls, 'transmute', None)
        cls = typic.klass(cls)
        if isinstance(transmute, MethodType):
            setattr(cls, 'transmute', transmute)
            typic.register(transmute, lambda a: a is cls)
        return cls

    
class Foo(metaclass=FooMeta):
    a: int
    b: str
    
    @classmethod
    def transmute(cls, v: Any) -> 'Foo':
        if isinstance(v, str):
            try:
                v = json.loads(v)
            except:
                pass
        if isinstance(v, str):
            v = v.split(',')
        if isinstance(v, list):
            return cls(*v)
        return typic.transmute(cls, v)
@typic.al
def foo(f: Foo):
    print(f)

foo('1,abc')  # Foo(a=1, b='abc')

But, there's some error with pycharm type hinting.

@seandstewart seandstewart added the enhancement New feature or request label Jun 7, 2020
@seandstewart seandstewart added this to To do in v2.1 via automation Jun 7, 2020
@seandstewart seandstewart added this to the Typic 2.1 milestone Jun 7, 2020
@seandstewart
Copy link
Owner

Thanks for raising this issue, this relates to the work described in #56. I'll take this approach under consideration when I re-define the API for registering custom Ser/Des protocols!

@seandstewart seandstewart removed this from the Typic 2.1 milestone Jan 5, 2021
@seandstewart seandstewart removed this from To do in v2.1 Jan 5, 2021
@seandstewart seandstewart added this to To do in v2.6 via automation Jan 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
v2.6
To do
Development

No branches or pull requests

2 participants