basically I've got a booking class with fields each declared manually. I am curious if theres a more neat solution for the given task.
class Booking:
def __init__(self, json_data):
self.referenceNumber = json_data["referenceNumber"]
self.fromDate = json_data["fromDate"]
self.preferredDate1 = json_data["preferredDate1"]
self.preferredTimeFrom = json_data["preferredTimeFrom"]
self.time = json_data["time"]
self.partySize = json_data["partySize"]
self.budgetAmountTotal = json_data["budgetAmountTotal"]
self.budgetAmountPerPerson = json_data["budgetAmountPerPerson"]
self.budgetCurrencySign = json_data["budgetCurrencySign"]
self.venueName = json_data["venueName"]
self.venueId = json_data["venueId"]
self.cityName = json_data["cityName"]
self.clientName = json_data["clientName"]
self.clientContactName = json_data["clientContactName"]
self.status = json_data["status"]
self.statusText = json_data["statusText"]
self.assigneeId = json_data["assigneeId"]
self.assignee = json_data["assignee"]
self.lastAction = json_data["lastAction"]
self.inquiryChannel = json_data["inquiryChannel"]
self.venueDateFormat = json_data["venueDateFormat"]
self.bookingId = json_data["bookingId"]
self.inquiryHold = json_data["inquiryHold"]
self.isSpaceSelectedForHolds = json_data["isSpaceSelectedForHolds"]
self.id = json_data["id"]
bonus if i am not given an unresolved reference warning when I am calling for the attribute.
A simple self.__dict__.update(json_data) might do the trick.
Given the code in the question, access to attributes would be, for example, in the style of:
Booking().fromDate
However, if you don't mind accessing the value by its key name then you can greatly simplify the code as follows:
class Booking:
def __init__(self, json_data):
self._json = json.data
def __getitem__(self, key):
return self._json.get(key)
Then (for example)...
pd = {'fromDate': '2022/10/18'}
print(Booking(pd)['fromDate'])
How about this?
def set_attr_from_json(obj, json_data):
for key, value in json_data.items():
setattr(obj, key, value)
class Booking:
def __init__(self, json_data):
set_attr_from_json(self, json_data)
Since you want to control how your class attributes should be built, I think you should use metaclass like this
import json
from types import SimpleNamespace
class BookingMeta(type):
def __call__(self, json_data):
obj = super().__call__(json_data)
obj = json.loads(json.dumps(json_data), object_hook=lambda d: SimpleNamespace(**d))
return obj
class Booking(metaclass=BookingMeta):
def __init__(self, json_data):
pass
b = Booking({"name": {"first_name": "hello", "last_name": "world"}, "age": 23, "sub": ["maths", "Science"]})
print(b.name.first_name)
print(b.age)
#hello
#23
First thing first - upon suggestions, please do your best to be understandable for newbies as if it is too complex, it may not be much useful as I need to furtherly continue after the current ask. Thank you in advance for that :)
I'm trying to define an object with multiple variables that I may use.
So far I was able to create the basic class for myself (with just ID of the object), but I am now struggling to add the rest of the variables needed for the object.
The data that I have to store with the multiple instance of the object is as follows:
id of the user - this is the value thru which I need to be searching thru the objects as I will have multiple entries of the below example data for different time intervals that I need to count. It does not need to be changed within the objects variables.
Name - The name of the person for whom I will be counting the hours spent. It is static (does not need to be changed within the objects variables).
Started timestamp and Ended timestamp - The time within which the person has executed things. As I will have multiple instances of data coming towards the object, I need to check for overlapping of shifts and if so, such hours to be avoided, but if extra hours beside the overlapped - to be added. E.g. if overlapping is not a perfect match, then the additional time spent to be added to the "total spent hours". The data received for both timestamps are in format that I convert into datatime with "datetime.strptime(start, '%Y-%m-%dT%H:%M:%S+02:00')
Schedule ID - it is the ID of the entry for the started and ended timestamps. It may be saved as an array as it will not be used except for reporting purposes - e.g. the person has processed things during it's first shift (start_timestamp thru end_timestamp).
Array of contacts that I need to separate to two different values - one for e-mail, other for phone number (including country code). The array returns as [email, country_code, phone_number]
Quote of example data that I have:
PersonID: ID1234
Name: Anton Todorov
Started at: 2022-12-26T00:00:00+02:00
Ended at: 2022-12-26T02:00:00+02:00
Schedule ID: SCHEDID1
Contacts: ['a.todorov#e-mail.email', 359, '000000000']
---===Separator===---
PersonID: ID5678
Name: Morgan Freeman
Started at: 2022-12-26T02:00:00+02:00
Ended at: 2022-12-26T14:00:00+02:00
Schedule ID: SCHEDID2
Contacts: ['slogan#draftkings.com', 1, '0000000000']
---===Separator===---
PersonID: ID1234
Name: Anton Todorov
Started at: 2022-12-26T14:00:00+02:00
Ended at: 2022-12-27T02:00:00+02:00
Schedule ID: SCHEDID3
Contacts: ['a.todorov#e-mail.email', 359, '000000000']
So with that on, I have to calculate the total hours that each person has spend from within these sections of data that I have.
The object that I have so far is as follows:
class DataItem(object):
def __init__(self, person_id):
self._person_id = person_id
self._updatable_id = ""
#property
def person_id(self):
return self._person_id
#property
def updatable_id(self):
return self._updatable_id
#updatable_id.setter
def updatable_id(self, value):
self._updatable_id = value
#updatable_id.deleter
def updatable_id(self):
del self._updatable_id
class Persons(object):
def __init__(self):
self._ids = []
def find_person_by_id(self, person_id):
# search by id
existing = [i for i in self._ids if i.person_id == person_id]
if not existing:
# create and append
existing_person = DataItem(id)
self._ids.append(existing_person)
else:
# assign to existing
existing_person = existing[0]
# return the object to be acted upon
return existing_person
So.. Would someone be able to assist me with furtherly developing the object so that I may be storing the data properly inside of each of its instances, please?
I would gladly appreciate all detailed suggestions (especially as soon as I am also able to understand them).
Thank you all in advance!
I finally developed what I was looking for.
A bit messy, but that does exactly what I need.
Thanks to #Robert Lee for the attempt, despite it was not what I chose to continue with.
class PersonData(object):
def __init__(self, email, country_code, phone_number, user_id, names):
self._email = email
self._country_code = country_code
self._phone_number = phone_number
self._user_id = user_id
self._names = names
self._started = []
self._ended = []
self._schedule_id = []
#property
def email(self):
return self._email
#property
def country_code(self):
return self._country_code
#property
def phone_number(self):
return self._phone_number
#property
def user_id(self):
return self._user_id
#property
def names(self):
return self._names
#property
def started(self):
return self._started
#started.setter
def started(self, started):
self._started.append(started)
#started.deleter
def started(self):
del self._started
#property
def ended(self):
return self._ended
#ended.setter
def ended(self, ended):
self._ended.append(ended)
#ended.deleter
def ended(self):
del self._ended
#property
def schedule_id(self):
return self._schedule_id
#schedule_id.setter
def schedule_id(self, schedule_id):
self._schedule_id.append(schedule_id)
#schedule_id.deleter
def schedule_id(self):
del self._schedule_id
class PeopleBuffer(object):
def __init__(self):
self._people = []
def find_by_id(self, email, country_code, phone_number, user_id, names):
# search by id
existing = [i for i in self._people if i.user_id == user_id]
if not existing:
# create and append if not found
existing_person = PersonData(email, country_code, phone_number, user_id, names)
self._people.append(existing_person)
else:
# assign to existing
existing_person = existing[0]
# return an object to be acted upon
return existing_person
def return_all(self):
for each_person in self._people:
print("each_person: ")
print("Email: %s" % each_person.email)
print("Country Code: %s" % each_person.country_code)
print("Phone Number: %s" % each_person.phone_number)
print("User Id: %s" % each_person.user_id)
print("Names: %s" % each_person.names)
print("Started: %s" % each_person.started)
print("Ended: %s" % each_person.ended)
print("ScheduleId: %s" % each_person.schedule_id)
class MainApplication(object):
def __init__(self):
self._buffer = PeopleBuffer()
def _populate_person(self, email, country_code, phone_number, user_id, names, started, ended, schedule_id):
person = self._buffer.find_by_id(email, country_code, phone_number, user_id, names)
person.started.append(started)
person.ended.append(ended)
person.schedule_id.append(schedule_id)
def _print_people(self):
self._buffer.return_all()
def main(self):
while input("Continue? ") != "No":
user_id = input("Enter UserId: ")
names = input("Enter Name: ")
started = input("Enter Started: ")
ended = input("Enter Ended: ")
schedule_id = input("Enter ScheduleId: ")
email = input("Enter Email: ")
country_code = input("Enter CountryCode: ")
phone_number = input("Enter PhoneNumber: ")
self._populate_person(email, country_code, phone_number, user_id, names, started, ended, schedule_id)
self._print_people()
def main():
app = MainApplication()
app.main()
if __name__ == '__main__':
main()
Based on what you are doing I would consider doing json data format and do something like this. Please excuse my quick and dirty code but I think fundamentally you are looking for a way to create a data format that might work for your scenario.
Looking over it one more time, I feel like this might be the format you are looking for
[
{
"person_id": "ID1234",
"name": "Anton Todorov",
"schedule": [
{
"schedule_id": "SCHEDID1",
"started_at": "2022-12-26T00:00:00+02:00",
"ended_at": "2022-12-26T02:00:00+02:00"
},
{
"schedule_id": "SCHEDID3",
"started_at": "2022-12-26T14:00:00+02:00",
"ended_at": "2022-12-27T02:00:00+02:00"
}
],
"contact_info": {
"email": "a.todorov#e-mail.email",
"country_code": 359,
"phone_number": "000000000"
}
},
{
"person_id": "ID5678",
"name": "Morgan Freeman",
"schedule": [
{
"schedule_id": "SCHEDID2",
"started_at": "2022-12-26T02:00:00+02:00",
"ended_at": "2022-12-26T14:00:00+02:00"
}
],
"contact_info": {
"email": "slogan#draftkings.com",
"country_code": 1,
"phone_number": "000000000"
}
}
]
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
def main():
people = list()
person = dict()
person['person_id'] = 'ID1234'
person['name'] = 'Anton Todorov'
person['schedule'] = list()
schedule = dict()
schedule['schedule_id'] = 'SCHEDID1'
schedule['started_at'] = '2022-12-26T00:00:00+02:00'
schedule['ended_at'] = '2022-12-26T02:00:00+02:00'
person['schedule'].append(schedule)
schedule = dict()
schedule['schedule_id'] = 'SCHEDID3'
schedule['started_at'] = '2022-12-26T14:00:00+02:00'
schedule['ended_at'] = '2022-12-27T02:00:00+02:00'
person['schedule'].append(schedule)
contact_info = dict()
contact_info['email'] = 'a.todorov#e-mail.email'
contact_info['country_code'] = 359
contact_info['phone_number'] = '000000000'
person['contact_info'] = contact_info
people.append(person)
person = dict()
person['person_id'] = 'ID5678'
person['name'] = 'Morgan Freeman'
person['schedule'] = list()
schedule = dict()
schedule['schedule_id'] = 'SCHEDID2'
schedule['started_at'] = '2022-12-26T02:00:00+02:00'
schedule['ended_at'] = '2022-12-26T14:00:00+02:00'
person['schedule'].append(schedule)
contact_info = dict()
contact_info['email'] = 'slogan#draftkings.com'
contact_info['country_code'] = 1
contact_info['phone_number'] = '000000000'
person['contact_info'] = contact_info
people.append(person)
print(json.dumps(people, indent=4))
if __name__ == '__main__':
main()
First things first; Your example feels more like a Java example written in Python. Instance variables are in practice properties, so all of your #property methods is redundant code.
dataclasses module is implemented for cases like yours. For example,
Schedule data class:
# schedule.py
from dataclasses import dataclass, field
from datetime import datetime
from typing import Union
#dataclass(unsafe_hash=True)
class Schedule:
schedule_id: str
start: Union[str, datetime]
end: Union[str, datetime]
def __post_init__(self):
self.start = self._datetime_converter(self.start)
self.end = self._datetime_converter(self.end)
def _datetime_converter(self, dt: str):
return datetime.strptime(dt, '%Y-%m-%dT%H:%M:%S+02:00')
def overlaps_with(self, other: Schedule):
return not ((self.start >= other.end) ^ (other.start >= self.end))
#property
def deltatime(self):
return self.end - self.start
Worker data class:
# worker.py
from functools import reduce
from dataclasses import dataclass, field
from .schedule import Schedule
#dataclass
class Worker:
person_id: str
name: str
contacts: str = field(repr=False)
schedules: set[Schedule] = field(init=False, default_factory=set)
email: str = field(init=False, default='')
country: int = field(init=False, default=-1)
phone: str = field(init=False, default='')
def __post_init__(self):
self.email, self.country, self.phone = self.contacts
#classmethod
def add_from_json(cls, worker_id: str, file: str):
NotImplemented
def overlapping_schedules(self, schedule: Schedule):
return filter(lambda s: s.overlaps_with(schedule), self.schedules)
def schedule_overlaps(self, schedule: Schedule):
return any(self.overlapping_schedules(schedule))
def add_schedule(self, schedule: Schedule):
if not self.schedule_overlaps(schedule):
self.schedules.update({schedule})
else:
NotImplemented
def add_schedules_from_json(self, file: str):
NotImplemented
def remove_schedule(self, schedule: Schedule):
self.schedules -= {schedule}
#property
def total_time_scheduled(self):
deltas = map(lambda s: s.deltatime, self.schedules)
return reduce(lambda x, y: x + y, deltas)
def __hash__(self):
return hash(id(self.person_id))
def __eq__(self, other):
return self.person_id == other.person_id
In theory you don't really need to create a Workers class. The methods __hash__ and __eq__ take care of that and you just need to create a set[Worker]. However, if you still want to create a Workers class, just loop over the existing methods.
class User:
def __init__(self, username):
self.username = username
#classmethod
def get_user(cls):
return cls(input("Username: "))
class Budget(User):
def __init__(self, monthtly_income):
super().__init__(User.get_user())
self.monthly_income = monthtly_income
self.perc_lis = []
self.category_obj_lis = []
self.category_name_lis = []
self.value_lis = []
...
# creates objects and adds them to a list
for i in range(len(self.category_name_lis)):
self.category_obj_lis.append("")
self.category_obj_lis[i] = Category(self.category_name_lis[i], self.monthly_income)
...
class Category(Budget):
def __init__(self, name, monthly_income):
super().__init__(monthly_income)
self.name = name
self.perc = 0
self.amt = 0
self.left = 0
self.max = 0
# defines the percentage for each category
def get_perc(self):
self.perc = float(input(f"{self.name}: "))
When I run this it asks for username 3 times after I have asked for the categories because I create each Category object in a loop. Username is asked for at the start of the code. I need the category class to be a child class because I need the monthly_income variable to use in code not posted. I am not very good at inheritance so i could easily be missing something obvious. Is there a way for each instance of Category to not ask for username and just use the one already asked in the beginning? I apologize if this is somewhat confusing but idk where to go from here.
I would like to not define the input variables multiple times when they are equivalent for all resolver. How can I achieve that?
import graphene
class GeoInput(graphene.InputObjectType):
lat = graphene.Float(required=True)
lng = graphene.Float(required=True)
#property
def latlng(self):
return "({},{})".format(self.lat, self.lng)
class Address(graphene.ObjectType):
latlng = graphene.String()
class Test(graphene.ObjectType):
test_string = graphene.String()
class Query(graphene.ObjectType):
address = graphene.Field(Address, geo=GeoInput(required=True))
test = graphene.Field(Test, geo=GeoInput(required=True))
def resolve_address(self, info, geo):
return Address(latlng=geo.latlng)
def resolve_test(self, info, geo):
return Test(test_string="({},{})".format(geo.lat, geo.lng))
schema = graphene.Schema(query=Query)
query = """
query something{
address(geo: {lat:32.2, lng:12}) {
latlng
}
test(geo: {lat:32.2, lng:12}) {
testString
}
}
"""
if __name__ == "__main__":
result = schema.execute(query)
print(result.data["address"]["latlng"],
result.data["test"]["testString"])
Is there any way doing it for the whole query class, like initializing variables?
for some reason when I try to add an object to a dictionary in a class, where the dictionary belongs to another class and objects are added/removed by class functions it always seems to fail adding.
Heres the datahandler :
class datastore():
def __init__(self, dict=None):
self.objectStore = {}
self.stringStore = {}
if dict is not None:
self.objectStore = dict
def __addobj__(self,obj,name):
print("adddedval")
self.objectStore[name] = obj
def __getobject__(self,name):
_data = self.objectStore.get(name)
return _data
def __ripobj__(self,name,append):
if isinstance(append, object):
self.objectStore[name] = append
def __returnstore__(self):
return self.objectStore
def __lst__(self):
return self.objectStore.items()
and heres the trigger code to try to add the item :
if self.cmd=="addtkinstance-dev":
print("Adding a tk.Tk() instance to dataStore")
#$$ below broken $$#
_get = datastore.__dict__["__returnstore__"](self.dat)
_get["test-obj"] = tk.Tk()
datastore.__init__(self.dat, dict=_get)
#--------------------------------------------#
tool(tk.Tk(), "test-obj", datastore())
and also heres the init for the class that trys to add the object
class cmdproc(tk.Tk, datastore):
def __init__(self,lst,variable_mem,restable):
self.pinst = stutils(lst,restable,variable_mem)
self.vinst = varutils(variable_mem,lst,restable)
self.tki = tkhandler()
self.dat = datastore(dict=None)
datastore.__init__(self, dict=datastore.__returnstore__(self.dat))
tk.Tk.__init__(self)
self.lst = lst
self.vdat = variable_mem
self.restable = restable
please help this is seriously baffling me
(note that tkhandler dosn't have to do with anything)