-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add plugin system for extending SolidPython #36
Add plugin system for extending SolidPython #36
Conversation
A couple of thoughts about this:
You're solution provides a different way for what I use to do like this: #myPlugin.py
from solid2 import *
def upLeft(x):
return x.up(1).left(1)
ObjectBase.upLeft = upLeft
>>> from solid2 import *
>>> import myPlugin
>>> cube().upLeft()
translate(v = [-1, 0, 0]) {
translate(v = [0, 0, 1]) {
cube();
}
} Intuitively I would prefer a solution like this: #solid2/core/extension_manager.py
[...]
def register_access_syntax_extension(exts):
if not isinstance(exts, Iterable):
exts = [exts]
from .object_base import ObjectBase
for fn in exts:
if hasattr(ObjectBase, fn.__name__):
raise Exception(f'Unable to register "{fn.__name__}" plugin, it would overwrite an existing plugin or method.')
setattr(ObjectBase, fn.__name__, fn)
#solid2/core/__init__.py
from .extension_manager import register_access_syntax_extension
>>> from solid2 import *
>>> def leftUp(x):
... return x.left(1).up(1)
...
>>> register_access_syntax_extension(leftUp)
>>> cube().leftUp()
translate(v = [0, 0, 1]) {
translate(v = [-1, 0, 0]) {
cube();
}
} Do you have any thoughts about my thoughts? ;) |
Thank you for reviewing the pull request! I read through all of your suggestions. Here are my thoughts:
def register_access_syntax_extension(exts):
if not isinstance(exts, Iterable):
exts = [exts]
if hasattr(ObjectBase, fn.__name__):
raise Exception(f'Unable to register "{fn.__name__}" plugin, it would overwrite an existing plugin or method.')
setattr(ObjectBase, fn.__name__, fn)
Those are my thoughts in detail, however I am completely okay with all of your changes. I think ability to easily extend the access syntax with a plugin or extension system is really valuable and all that really matters to me. A change like this is an advantage of SolidPython over the default OpenSCAD language and I think it would enable people to easily extend SolidPython without having to incorporate those extensions into the core code. |
The solution proposed in the mentioned branch implements your solution but slightly different integrated. I would suggest that solution.It keeps as much as possible out of the core and at the places they are supposed to belong. Furthermore it also complies with your thoughts mentioned, if I understood everything correct "on the fly". I'd love to see this -- the plugin extension space -- of solidpython growing! There is already a repository (and package) where I'd like to gather plugins. But the repo and package is atm actually a little mess, but we can clean it up. https://github.com/jeff-dh/solidpython2_extensions/tree/master/solid2_extensions |
It does not comply with all your ideas ;) I also thought about having different plugins / extensions and namespace clashes.... I don't have an opinion about it yet. All proposed solution so far have major drawbacks for me. I like that each extension registers itself and you only have to import and use it. I don't know yet how to solve the namespace clashes yet. Syntax: I totally agree, but solidpython is already extendible with some stuff (render extensions, root wrappers, fonts). I think it makes sense to have one central infrastructure that handles them all instead of several different approaches to more or less the same thing. You would end up having different extensions for different stuff instead of having one extension which might contain several single extensions for different "subsystems". List vs Dict: |
Awesome, thank you. That all makes sense to me. I reverted my commit and brought your alternative implementation into this pull request. |
Regarding namespace clashes I would suggest the following: Every extensions could prepend it's (access syntax) commands with something -> I think this might be good enough for the scope of SolidPython and if it turns out that it is not, we can adjust according to emerging needs. I'm wondering whether it is possible to move the extensions register stuff into function decorators: @solid2.register_access_syntax("some_alternative_name")
def leftUp(x):
return x.left(1).up(1)
@solid2.register_pre_render
def pre_render_extensions(...?):
[...] or similar..... |
Haha, yeah it should work: The docs say:
and the repl says: >>> def foo(fn):
... print("foo")
... return fn
...
>>> @foo
... def blub():
... print("blub")
...
foo
>>> blub()
blub
>>> @foo
... class bla:
... pass
...
foo So I assume the proposed decorators should be straight forward. If we find "good" names for the function decorators this would also solve the If you have better suggestions for the decorator names, let me know! |
(I can't push to your branch for some reason I don't understand.... it gets rejected ?!?) Have a look at this. |
note: my accessSyntaxExtension branch turned into a dev branch which already contains a couple other changes. If you like you can merge it completely into the branch of this pr, otherwise I will merge it directly into master at some point. |
Closed because #38 now includes these changes |
I am really enjoying solid python! I hope you consider this proposal, I think it would be really helpful to grow SolidPython.
I thought it would be really nice to have a standard way to extend SolidPython. Often it makes sense to just write a helper function, but sometimes it would be really valuable to add more fundamental functionality and make use of the function chaining. I initially did this for my own projects via inheritance, but it was difficult and didn't lend itself to breaking functionality out into reusable modules. I think a plugin system would be very convenient and open things up for third party modules.
This pull request creates a simple plugin system. A plugin would be a function (or collection of functions) that extend the built in shapes with additional chain-able functionality.
Usage example:
I imagine in a real situation someone would create a package, the package could be installed, and in your app you could register the plugin. Something like this: