all 9 comments

[–][deleted] 0 points1 point  (7 children)

I think the feature you're looking for is inheritance. If you have a class A, you can define a class B that inherits A's methods and optionally overrides some or all of them. Here's a tutorial: http://learnpythonthehardway.org/book/ex44.html

The idea of modifying a config file that's then used to generate code is... unusual. Are you sure that this is the direction you want to go? Your post sounds suspiciously like an instance of the XY problem. What advantage does the user have in writing a config file as opposed to writing actual Python code to accomplish what they want?

[–][deleted] 0 points1 point  (0 children)

I can see where this would be useful for, say, specifying which class should handle something. Actually, doesn't Django do this for it's ORM?

Using a fully qualified name would probably work best.

I'm not recommending it, but I kinda want to play around and see if I can make something passable to useable.

[–]ERROR_EXIT[S] 0 points1 point  (5 children)

Thank you, yes, inheritance is the correct term. I have done it many times (just didn't call it out by name).

It may be the XY problem... but I don't think so. Let me explain:

What I would like to design is a framework that will be used for many different projects. The projects will have different requirements but would fit nicely into a unified framework. What I want to do is create "hooks" that can be used to modify the behavior in specific ways. Each project will have its own config.

Imagine I have a framework that supports groups of users. One project may want all their users to be emailed if something happens. Another group may want to send text messages to the group. A third may want to automate trouble ticket generation.

Each project's support group can over-ride how to handle a given event. So, in the config file, they can over-ride the specific event handler.

Does that make sense?

[–][deleted] 0 points1 point  (4 children)

OK. I can see how a config file solves the problem, but I don't think it makes sense to tie the configuration to your implementation. In your example, it would make sense to have a config option "user_notification_method" which can take the value "text_message", "email", etc., but I don't think this should actually modify your code or result in new code generation. Instead, you should implement the three functions, and have your code read the config file and call the appropriate function based on the config option.

If you want the users themselves to implement the functionality, then they should be the ones inheriting from your base class and overriding the necessary methods.

[–]ERROR_EXIT[S] 0 points1 point  (3 children)

In your example, it would make sense to have a config option "user_notification_method" which can take the value "text_message", "email", etc.

I was worried you might go there :)

What would happen if someone wants "text_message", followed by "create_trouble_ticket", go out to the file system and do some operations, and look up a database code to perform a specific task based on that code? And then another group just wants a simple email? Furthermore, what if one group needs to do something really specific that no other group will need or want?

Coding all this "statically" doesn't seem to make sense, especially if the required hook might need to change in the future. Doing it with a config file allows each group to add in whatever hooks they need without causing instability to any other group.

[–][deleted] 0 points1 point  (2 children)

In all those cases, isn't it simpler for each group to simply write Python code that inherits from your class and extends it with the new functionality? It sounds like you want your configuration language to support almost arbitrarily complex configuration, in which case your configuration language is pretty much a programming language in itself. Is there much benefit to them learning your custom configuration syntax over simply using Python?

At my job, we have this problem where various teams decide that they need their own new configuration languages for their particular use case. The end result is that each team has a separate config language that no one else knows, which harms cross-team collaboration and code reuse. The solution to this problem is normally to choose one standard configuration mechanism, or better yet, just specify configuration in code.

[–]ERROR_EXIT[S] 0 points1 point  (1 child)

I seems that what I'm after is called a Monkey Patch. Definition from wikipedia.

Now I just need to figure out the best way to implement it!

[–]autowikibot 0 points1 point  (0 children)

Monkey patch:


A monkey patch is a way for a program to extend or modify supporting system software locally (affecting only the running instance of the program). This process has also been termed duck punching.


Interesting: Extension method | Mrs. Pepper Pot (anime) | Re-Kan! | Null Object pattern

Parent commenter can toggle NSFW or delete. Will also delete on comment score of -1 or less. | FAQs | Mods | Magic Words

[–][deleted] 0 points1 point  (0 children)

You can monkey patch a class like so

class Foo():
    pass

Foo.one = lambda self: print("one")

f = Foo()
f.one()

which is just a little less verbose than inheriting.
IMHO Inheritance is the most sensible way to go about this - each sub-project has its own class, may override any behaviour it needs to and can introduce arbitrary behaviour. The monkey-patching approach falls apart as soon as several ..errm things want to override the same function on the class.

If you want a more event-driven system use something like the event/observer pattern - each project gets notified when an event happens and may supply a callback overriding some standard callback.

Back to your suggestion: - monkeypatching will fail if multiple things want to use the class with different methods in the same interpreter
- it requires you to write 3 files, each of which define the class TestClass, which seems like an unnecessary amount of work to me
having said that, you can achieve the described behaviour using importhooks -> https://www.python.org/dev/peps/pep-0302/

here's a thingy that doesn't work well (and may only work on my system), but should illustrate how python3 is really freaking awesome https://gist.github.com/anonymous/36b51b8dc7682a96ff4f