Skip to content
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 add_foo() methods for EntityList foo properties #117

Open
bworrell opened this issue Apr 17, 2014 · 4 comments
Open

Add add_foo() methods for EntityList foo properties #117

bworrell opened this issue Apr 17, 2014 · 4 comments

Comments

@bworrell
Copy link
Contributor

The introduction of EntityList greatly helped reduce the amount of code needed to write for python-stix classes, but also established a new pattern for working with list types. We should go back through the codebase and add the add_foo() methods where missing. This is related to #110.

@gtback
Copy link
Contributor

gtback commented Apr 17, 2014

I generally dislike this approach (which is why I never add them to classes 😉). It feels unpythonic to me, and more like Java or the generateDS bindings. The goal of EntityList is to make interacting with these list types feel exactly like working with Python lists, while supporting the XML import and export and enforcing the type of items that are allowed in the list, without a lot of boilerplate code.

I suppose for the sake of consistency it would be good to add them (though I would prefer removing all the others 😀).

You could also use some magic Python and put this (WARNING: pseudocode) on the stix.Entity class to prevent the boilerplate code:

def __getattr__(self, name):
    if not name.startswith("add_"):
        return object.__getattr__(self, name)
    # get everything after the first _
    real_attr = name.split("_", 1)[1]
    # return the append() function of whatever type is trying to be added,
    # which then gets called with whatever argument the caller tried to pass.
    return getattr(self, real_attr).append

I haven't actually tried running that function, but something like that is better (IMO) than 73 copies of almost-identical functions scattered throughout the code.

@bworrell
Copy link
Contributor Author

Hmm, this might work, though it would require ripping out all the old add_foo() functions and converting many of our list fields to EntityList instances..or checking to see if that add_foo() function already exists and returning it if it does.

...
if hasattr(self, name):
    return object.__getattr__(self, name)
...

@gtback
Copy link
Contributor

gtback commented Apr 17, 2014

It might just work as is, meaning we can leave the existing functions as is for now (that is, until I convince you to remove them 😉)

object.__getattr__(self, name)
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.

Note that if the attribute is found through the normal mechanism, __getattr__() is not called. (This is an intentional asymmetry between __getattr__() and __setattr__().) This is done both for efficiency reasons and because otherwise __getattr__() would have no way to access other attributes of the instance.

https://docs.python.org/2/reference/datamodel.html#object.__getattr__

Again, I haven't actually tested any of this.

@bworrell
Copy link
Contributor Author

Oh, nice! I was wondering if that was the behavior and considered looking up the docs...but didn't ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants