Instance() vs create_instance()

Why are there 2 ways to do the same thing in Pyblish? And expectation issues that come with it.

example:

context = pyblish.api.Context()
instance_a = pyblish.api.Instance(name="MyInstanceA", parent=context)

instance_b = context.create_instance(name="MyInstanceB")

both create an instance,
but when you want to change from a context instance to non context instance and change context.create_instance to pyblish.api.Instance,
your code can break if you have any kwargs other than name and parent. (example family)

i’d expect these to have similar behaviour, except for maybe the parent kwarg
these have similar behaviour as expected

proxy1 = pyblish.api.Instance
proxy2 = context.create_instance
instance_a = proxy1 (name="MyInstanceA", parent=context)
instance_b = proxy2 (name="MyInstanceB")

but this doesn’t work

instance_a = proxy1 (name="MyInstanceA", family='mesh', parent=context)
instance_b = proxy2 (name="MyInstanceB", family='mesh')

is there a reason we don’t take instance.data.update(kwargs) and move it to the Instance init?

def create_instance(self, name, **kwargs):
    instance = Instance(name, parent=self)
    instance.data.update(kwargs)
    return instance

change this

class Instance(AbstractEntity):
    def __init__(self, name, parent=None):
        super(Instance, self).__init__(name, parent)
        self._data["family"] = "default"
        self._data["name"] = name

to

class Instance(AbstractEntity):
    def __init__(self, name, parent=None, **kwargs):
        super(Instance, self).__init__(name, parent)
        self._data["family"] = "default"
        self._data["name"] = name
        self.data.update(kwargs)

The two instances you create are identical and there is no distinction between a “context instance” and a “non-context instance”.

If you have a peek at the source for create_instance() you’ll find this.

    def create_instance(self, name, **kwargs):
        instance = Instance(name, parent=self)
        instance.data.update(kwargs)
        return instance

That is the entire source for create_instance and you could type that in yourself if you’d like to, the result will be identical.

As you can see in the source, the reason you can pass keyword arguments is because the function takes a **kwargs. You can achieve the same result with an Instance by doing something like:

instance = api.Instance("MyInstanceA", **dict(family="mesh", parent=context))

But I’m not sure why you would want that.

Haven’t got an answer for you here, there are a million things never done in Pyblish that won’t have a reason for not having been done. :slight_smile: It is what it is. However, I’d be happy to tell you more about the things that were done, and why they were done that way.

thanks for getting back
i’ve put in a PR https://github.com/pyblish/pyblish-base/pull/372