Python - automating the creation of class instances - python

I have dozens of classes built in this fashion:
class playlist_type_1(radio):
'''child class'''
def __init__(self,user, type):
radio.__init__(self, user, type)
class playlist_type_2(radio):
'''child class'''
def __init__(self,user,type):
radio.__init__(self, user, type)
they inherit from:
class radio(self, user, type):
'''parent class'''
since I will have many users, I'm trying build a model for creating instances like so:
thom = playlist_type1('Thom Yorke', 'playlist_type_1')
the user himself, thom, will chose his playlist_type_n at command line via:
string = raw_input('Choose a playlist type> ')
and instance will be created and run:
thom = playlist_type1('Thom Yorke', string)
can this be implemented within class scope?

Create a mapping of names to classes and then instantiate the class based on that:
class PlaylistType1(Radio):
pass
class PlaylistType2(Radio):
pass
playlist_types = {
PlaylistType1.__name__: PlaylistType1,
PlaylistType2.__name__: PlaylistType2,
}
...
playlist = playlist_types[chosen_type](user)

Related

Indirect inheritance in Python through decorators

I want to define a decorator (let's name it subcollection) that behaves like this:
class ParentClass:
name = None
def __init__(self, name=None):
self.name = name
#subcollection
class ChildClass:
def greet(self):
print(f'Hello from {self.outter.name}')
parent_class = ParentClass('Mahdi')
child_class = parent_class.ChildClass()
assert child_class.greet() == 'Hello from Mahdi'
I'm trying to achieve a complicated inheritance in python that confused me. This is needed to create a nested unstructured ORM.
I probably could do this with factory functions, but I'm wondering if there is any workaround to pass the parent_class instance at the time of the child_class creation with decorators?!

Access child class variable in parent class with no instances

I have a class that other classes herit from:
class BaseManager:
model = Base
#classmethod
def get_by_id(cls, db: Session, id: int):
return db.query(cls.model).filter(cls.model.id == id).one()
class UserManager(BaseManager):
model = User
And it is used this way:
user = UserManager.get_by_id(db=db, id=user_id)
But the UserManager is ignoring the model defined in it, using the Base defined on BaseManager. How can I proceed?
I have already saw implementations such as django forms using metaclass and for example this question over here Access child class variable in parent class but I think that they don't apply to this context, i tried and did not succeed.

Django. How to create model instance in test db using objects fabric?

I want to make my unit tests setUp function clear from repeating tons of model creation lines like 1) create user 2) now create employee with fk to this user and etc.
In order to do that I've made a simple factory of dummy objects but I might've done some mistakes or just misunderstood something. Here's a piece of factory (dummy_data is just a bunch of dicts):
from abc import ABC
from users.models import User
from employees.models import Employee
from .dummy_data import(
user_data,
employee_data,
)
class DummyObjectFactory(ABC):
"""Fabric representing dummy test objects"""
def get_dummy_object(self):
"""Return dummy object"""
class DummyUser(DummyObjectFactory):
def get_dummy_object(self) -> User:
return User.objects.create_user(**user_data)
class DummyEmployee(DummyObjectFactory):
def get_dummy_object(self) -> Employee:
user = DummyUser().get_dummy_object()
return Employee.objects.create(**employee_data, user=user)
dummy_factory = {
"User": DummyUser().get_dummy_object(),
"Employee": DummyEmployee().get_dummy_object(),
}
dummy_factory = dot_dict(dummy_factory)
Then I make a dot notaion dictionary of all kinds of fabrics for easy calling them buy dummy_factory.Name . My intetion was that I call fabric with the desired model name and it creates it's instance.
The problem is: when I call it in some test's setUp method like so test_user = dummy_factory.User it creates object in actual database but I want it to be in test database.
Example of test:
class TestEmployeesListView(TestCase):
def setUp(self):
self.test_user = dummy_factory.User
self.test_employee = dummy_factory.Employee
self.client = Client()
def test_listview_deny_anonymous_user(self):
response = self.client.get(reverse('employees:employees-list'))
self.assertRedirects(response, '/login/?next=/employees/')
Yes, I've searched for the solution and found Factory boy and Faker libraries, but I want to complete my fabric, make it work properly. Thanks for your attention.
So I made it work. What I did was:
Added #abstractmethod decorator in the abstract class.
Every concrete factory methods must have a #classmethod decorator and recieve cls as an argument:
class DummyUser(DummyObjectFactory):
#classmethod
def get_dummy_object(cls) -> User:
return User.objects.create_user(**user_data)
It just work as intended: factory creates objects in test db. Thank you folks for participation.

Initialize additional object in Django model instance and pass model instance

Some calculations became too complex to maintain inside my model, so I decided to move them out and break the code in several classes and modules.
There's a single class serving as a facade which I would like to have available in a model instance to pass data to it.
It is being constructed from model instance:
class Calculator:
def __init__(self, field1: date, field2: float):
self.field1= field1
self.field2 = field2
#classmethod
def from_django_model(cls, django_model_instance):
field1 = django_model_instance.field1
field2 = float(django_model_instance.field2)
Currently I call it inside each property on my model like so:
class DjangoModel(models.Model):
# initialize the calculator
def calculator(self, group):
return calculator.Calculator.from_django_model(self)
# use it
#cached_property
def calculated_field(self):
try:
return self.calculator().calculation_method
except AttributeError:
return "Field not set!"
I feel this is not a good solution, since now on multiple methods I'm initializing the calculator object multiple times.
I would like to construct it once when the model is initialized and then pass it to the model instance.
I tried doing this with model manager, but the model instance is not available with it.

Making two classes reference eachother

I'm trying to make a text adventure where different "place" classes can point to eachother.
For instance, I have a Manager class that has a reference to each place. Then I have a Home class, and a Club class, with references to eachother through manager. The problem is that I can't instantiate them due to the circular reference.
Here's how I solved it, but it's ugly, because I have to create the places member inside of a method instead of __init__.
class Manager:
def __init__(self):
self.home = Home(self)
self.club = Club(self)
class Home:
def __init__(self, manager):
self.places = {}
self.manager = manager
def display_plot_and_get_option (self):
print "where do you want to go?"
return 'club' #get this from user
def get_next_place(self, place_name):
self.places = { #THIS IS THE BAD PART, which should be in __init__ but can't
'home':self.manaer.home
'club':self.manaer.club }
return self.places[place_name]
class Club:
#similar code to Home
pass
manager = Manager()
while (True):
place_name = manager.current_place.display_plot_and_get_option()
manager.current_place = manager.current_place.get_next_place(place_name)
In c++ I would set my dict up in the constructor, where it should be, and it would use the pointer of the Manager's home or club members, since I only want 1 instance of each place. How can I do this in python?
edit: expanded code example
You can just have a dictionary that holds the references, and call the methods straight from the Manager (which shouldn't really be named Manager, as it does not serve that purpose now) instance.
class Home(object):
pass
class Club(object):
pass
PLACES = {
'home': Home(),
'club': Club()
}
class Manager(object):
def display_plot_and_get_option(self):
return raw_input('Where do you want to go?')
def get_next_place(self, place_name):
return PLACES[place_name]
m = Manager()
while 1:
place_name = m.display_plot_and_get_option()
m.get_next_place(place_name)
Assuming that Home and Club are just a couple of the many places you plan to include in your game, it would probably be advantageous to create a Place class. Specific classes can either inherit from Place or have a name as a data member. Then you can model connections with a tree or graph.

Categories

Resources