Skip to content

Instantly share code, notes, and snippets.

@zdxerr
Created June 7, 2020 10:39
Show Gist options
  • Save zdxerr/349e1a3221b4dce9dd652ad972501234 to your computer and use it in GitHub Desktop.
Save zdxerr/349e1a3221b4dce9dd652ad972501234 to your computer and use it in GitHub Desktop.
Use factory method to create objects based on description (str/dict).
"""
"""
from abc import ABC, abstractmethod
from functools import lru_cache
from collections.abc import Set, Mapping
class Task(ABC):
def __init__(self, context):
self.context = context
@classmethod
@lru_cache(maxsize=None)
def get_subclasses(cls):
"""
"""
subclasses = []
for subclass in cls.__subclasses__():
subclasses.append(subclass)
subclasses.extend(subclass.get_subclasses())
return subclasses
@classmethod
def factory(cls, context, task_description):
for task_type in cls.get_subclasses():
if isinstance(task_description, str) and isinstance(task_type.description, str):
if task_description == task_type.description:
return task_type(context)
elif isinstance(task_description, Mapping) and isinstance(task_type.description, Set):
if task_description.keys() >= task_type.description:
return task_type(context, **task_description)
else:
raise Exception("invalid task description: {task_description}")
def __repr__(self):
return f"<Task: {self.description}>"
@abstractmethod
def run(self):
pass
class ShutdownTask(Task):
description = "shutdown"
def run(self):
pass
class CloneTask(Task):
description = {"clone", "target"}
def __init__(self, context, clone, target, **kwargs):
super().__init__(context)
self.clone = clone
self.target = target
def __repr__(self):
return f"<Task: clone({self.clone}) target({self.target})>"
def run(self):
pass
class InstallTask(Task):
description = {"install"}
def __init__(self, context, install, **kwargs):
super().__init__(context)
self.install = install
def __repr__(self):
return f"<Task: install({self.install})>"
def run(self):
pass
class DryRunVirtualMachine:
def __init__(self, name):
self.name = name
def __repr__(self):
return f"<DryRunVirtualMachine {self.name}>"
class Context:
pass
if __name__ == "__main__":
TASKS = [
{
"install": "test",
"bla": 5,
},
"shutdown",
{
"clone": "test",
"target": "test2",
},
{
"install": "test",
"bla": 5,
},
]
context = Context()
context.vm = DryRunVirtualMachine("BLA") # dry_run
for n, task_description in enumerate(TASKS):
task = Task.factory(context, task_description)
print(n, task)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment