Introduction
Hello everyone !
I am trying to develop multi-agent models in Python3. So my approach is to create basic classes and derive them to more concrete and specific ones. For instance, a class Bike inherits from Vehicle, itself inheriting from a basic Agent class.
Problem
I want to offer a clear specification of my classes init parameters using JSON Schema (and also use them for validation), but I am struggling to automate their generation. Let's look at an example:
class Agent:
SCHEMA = {
"properties": {
"agent_id": {
"type": "string",
"description": "unique identifier"
},
"network": {
"type": "string",
"description": "road network used by the agent to move"
},
"origin": {
"type": "integer",
"description": "origin position id",
},
"icon": {
"type": "string",
"description": "display icon"
}
},
"required": ["agent_id", "network", "origin", "icon"]
}
def __init__(self, agent_id, network, origin, icon):
self.id = agent_id
self.network = network
self.position = origin
self.icon = icon
def move(self, position):
self.position = position
class User(Agent):
SCHEMA = {
# that's what i want in the end, but i don't want to duplicate the common properties
"properties": {
"agent_id": {
"type": "string",
"description": "unique identifier"
},
# notice that there is no "network" property
"origin": {
"type": "integer",
"description": "origin position id",
},
"destination": {
"type": "integer",
"description": "destination position id",
},
"icon": {
"type": "string",
"description": "display icon"
}
},
"required": ["agent_id", "origin", "destination", "icon"]
}
def __init__(self, agent_id, origin, destination, icon="user"):
super().__init__(agent_id, "walk", origin, icon)
self.destination = destination
class Vehicle(Agent):
SCHEMA = {
# one way to inherit the schema could be like this, but it has its flaws
**super().SCHEMA,
"seats": {
"type": "integer",
"description": "capacity of the vehicle"
}
}
def __init__(self, agent_id, network, origin, seats, icon):
super().__init__(agent_id, network, origin, icon)
self.seats = seats
class Bike(Vehicle):
# i want a schema here too, but without the "seats" prop
# and maybe specify the default value for "icon" ?
def __init__(self, agent_id, origin, icon="bike"):
super().__init__(agent_id, "bike", origin, icon, 1)
class Car(Vehicle):
# quite same question here
def __init__(self, agent_id, origin, seats, icon="car"):
super().__init__(agent_id, "drive", origin, icon, seats)
As you can see, I want to write and add specifications as I add new parameters to my classes. I would like to re-use the schemas from higher classes in order to reduce code duplication, but it's hard. I have some ideas, for instance what I proposed above, but it does not allow stripping a parameter schema from the parent class for instance.. Maybe using a method would give me more control on how the schemas are built.
The question
I would like to know if there is a library that allows doing this, or, otherwise, I would be glad to have some advice on how to accomplish this.