The problem isn't so much if a specific service definition gets modified, it's more if they're trying to modify one, and accidentally modify many.
say they have a service with a ton of dependencies and they want to store it in a separate file:
class Application(miniboss.Service):
name = "python-todo"
image = "afroisalreadyin/python-todo:0.0.1"
env = {"DB_URI": "postgresql://dbuser:dbpwd@appdb:5432/appdb"}
ports = {8080: 8080}
stop_signal = "SIGINT"
def __init__(self):
with open('dependency_list') as f:
for dependency in f.readlines():
self.dependencies.append(dependency)
Once that class is initialized, any service that previously had zero dependencies, will now have everything in the file, because the list in miniboss.Service is shared by all instances of all subclasses that didn't override it.
One easy way to limit this is to define your miniboss.Service defaults in init instead of the toplevel. Then if users use mutable types at the top level, it only becomes an issue if they make subclasses, or if the process makes more than one instance of a particular class.
I still think immutable types are the best bet, but if they need mutable ones to throw some python magic in their somewhere along the build process, then tell them to define them within an __init__.
Or maybe just keep doing what your doing, and add a warning in the docs not to do screwy stuff like that.
Again, this really does look great I'm excited to see where it goes.