{"action":"created","issue":{"url":"https://api.github.com/repos/astropy/astropy/issues/3679","labels_url":"https://api.github.com/repos/astropy/astropy/issues/3679/labels{/name}","comments_url":"https://api.github.com/repos/astropy/astropy/issues/3679/comments","events_url":"https://api.github.com/repos/astropy/astropy/issues/3679/events","html_url":"https://github.com/astropy/astropy/pull/3679","id":67698860,"number":3679,"title":"OrderedDescriptor and OrderedDescriptorContainer","user":{"login":"embray","id":676149,"avatar_url":"https://avatars.githubusercontent.com/u/676149?v=3","gravatar_id":"","url":"https://api.github.com/users/embray","html_url":"https://github.com/embray","followers_url":"https://api.github.com/users/embray/followers","following_url":"https://api.github.com/users/embray/following{/other_user}","gists_url":"https://api.github.com/users/embray/gists{/gist_id}","starred_url":"https://api.github.com/users/embray/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/embray/subscriptions","organizations_url":"https://api.github.com/users/embray/orgs","repos_url":"https://api.github.com/users/embray/repos","events_url":"https://api.github.com/users/embray/events{/privacy}","received_events_url":"https://api.github.com/users/embray/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/astropy/astropy/labels/Affects-release","name":"Affects-release","color":"0052cc"},{"url":"https://api.github.com/repos/astropy/astropy/labels/coordinates","name":"coordinates","color":"c7def8"},{"url":"https://api.github.com/repos/astropy/astropy/labels/Docs","name":"Docs","color":"02d7e1"},{"url":"https://api.github.com/repos/astropy/astropy/labels/Enhancement","name":"Enhancement","color":"fad8c7"},{"url":"https://api.github.com/repos/astropy/astropy/labels/modeling","name":"modeling","color":"c7def8"},{"url":"https://api.github.com/repos/astropy/astropy/labels/utils","name":"utils","color":"c7def8"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-04-10T22:51:18Z","updated_at":"2015-08-04T16:42:04Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/astropy/astropy/pulls/3679","html_url":"https://github.com/astropy/astropy/pull/3679","diff_url":"https://github.com/astropy/astropy/pull/3679.diff","patch_url":"https://github.com/astropy/astropy/pull/3679.patch"},"body":"This PR implements two new classes that provide a *generic* implementation of a pattern that has come up in a couple places, and I anticipate using again.  The pattern is having a class that implements some *descriptor*, which will be instantiated multiple times at the level of a class declaration, and where we want to be able to record the *order* in which those descriptors were created in the class definition.\r\n\r\nThe two examples of this in Astropy currently, are `Model`, which uses the `Parameter` descriptor to declare parameters of a model, and the `FrameAttribute` class used with coordinate frames in the coordinates package.\r\n\r\nI thought of trying to generalize this pattern because I recently started writing yet another class that worked exactly the same way, for a modeling update.  It's worth noting that in Python 3 the `__prepare__` magic method mostly supplants this pattern.  But there are some advantages to `OrderedDescriptor` + `OrderedDescriptorContainer` over `__prepare__`, such as automatic assignment to a `.name` attribute on the descriptors based on the name of the attribute they were assigned to.  I think inheritance/subclassing is also handled pretty well here.\r\n\r\nFor more details see the docstrings for `OrderedDescriptor` and `OrderedDescriptorContainer`.  This PR also updates the modeling package and the coordinates package to use these new classes.  Feedback is appreciated."},"comment":{"url":"https://api.github.com/repos/astropy/astropy/issues/comments/127669225","html_url":"https://github.com/astropy/astropy/pull/3679#issuecomment-127669225","issue_url":"https://api.github.com/repos/astropy/astropy/issues/3679","id":127669225,"user":{"login":"embray","id":676149,"avatar_url":"https://avatars.githubusercontent.com/u/676149?v=3","gravatar_id":"","url":"https://api.github.com/users/embray","html_url":"https://github.com/embray","followers_url":"https://api.github.com/users/embray/followers","following_url":"https://api.github.com/users/embray/following{/other_user}","gists_url":"https://api.github.com/users/embray/gists{/gist_id}","starred_url":"https://api.github.com/users/embray/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/embray/subscriptions","organizations_url":"https://api.github.com/users/embray/orgs","repos_url":"https://api.github.com/users/embray/repos","events_url":"https://api.github.com/users/embray/events{/privacy}","received_events_url":"https://api.github.com/users/embray/received_events","type":"User","site_admin":false},"created_at":"2015-08-04T16:42:04Z","updated_at":"2015-08-04T16:42:04Z","body":"Rebased this again--going to go ahead and merge soon as I get the green light from CI.\r\n\r\nI hoped that this would improve some of the problems with subclassing models, but it's still tricky due to deeper reasons (though it will *help*).  I'll go ahead with this as is and address the model subclassing problems separately (#4035)."}}