Search code examples
pythonjsonpython-3.xabc

Create an ABC with abstract methods defined from json keys


Say I have a json file look like:

{
    "foo": ["hi", "there"],
    "bar": ["nothing"]
}

I'd like to create an abstract base class (ABC), where the name of abstract methods are the keys of the json above, i.e.:

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):

    @abstractmethod
    def foo(self):
        pass

    @abstractmethod
    def bar(self):
        pass

The problem is the json file actually has lots of keys. I wonder if there's any way like:

import json

with open("the_json.json") as f:
    the_json = json.load(f)

class MyABC(metaclass=ABCMeta):

    # for k in the_json.keys():
    #     create abstract method k

Thanks for the suggestions from the comments, but somehow it doesn't work as expected. Here is what I tried:

class MyABC(metaclass=ABCMeta):
    pass

def f(self):
    pass

setattr(MyABC, "foo", abstractmethod(f))
# I also tried
# setattr(MyABC, "foo", abstractmethod(lambda self: ...))

# Try to define another class that inherits MyABC
class MyClass(MyABC):
    pass

c = MyClass()
# Now this should trigger TypeError but it doesn't
# I can even call c.foo() without getting any errors

Solution

  • This may work :

    from abc import ABCMeta, abstractmethod
    
    with open("the_json.json") as f:
        the_json = json.load(f)
    
    class MyABC(metaclass=ABCMeta):
    
        def func(self):
            pass
    
        for k in the_json:
            locals()[k] = abstractmethod(func)
    
    # Delete attribute "func" is a must
    # Otherwise it becomes an additional abstract method in MyABC
    delattr(MyABC, "func")
    delattr(MyABC, "f")
    delattr(MyABC, "k")
    
    class MyClass(MyABC):
        pass
    
    MyClass()
    # TypeError: Can't instantiate abstract class MyClass with abstract methods bar, foo
    

    It will correctly throw an error if you try to instantiate MyABC, or a subclass of MyABC that doesn't implement the abstract methods.