> > > > >> mappers only support the addition of new attributes after construction. > There is of course clear_mappers() but that removes the entire graph of > mappers (emphasis on graph, which is why we don't get into the surgical > removal of individual mappers). There is also the prospect of creating a > new class, which I'm assuming is not desirable here. the mapped table > itself is completely core to the mapper itself after construction. > >> > >> The real question would be , why can't your join() be created before the > mapping. I can understand this kind of issue when using declarative, but > with plain mappers you'd want all Table metadata assembled ahead of time. > >> > >> A standard strategy when this kind of issue exists is to defer the > generation of mappers, which if its more convenient can be done using your > own mapper() callable that gathers up all the various mapper() arguments > into a list, then can emit the actual mapper() calls at some later point > (such as, build_my_mappers()). > > > > Thanks Mike. My mapper generation is actually deferred, but the point > > here is that the default modules build their mappers, so I can't just > > *extend* the base framework app if I can't replace one of it's > > mappers. I don't think this is such a weird pattern really, but if > > there is no other option, I suppose I will have to have the extension > > app make an explicit list of all mappers. > > let me see if i understand. You have some core library of classes, that > are designed to talk to particular database tables. The core library > generates the classes, defines table metadata, then maps the classes to the > tables. > > then, an application which is a user of that library, would like to import > it, have the library build up its full persistence model, some of it being > incorrect vs. what the application wants, then the application would > redefine how arbitrary members of that class hierarchy are mapped, as an > activity of "extending" the library. > > This seems like a relational database monkeypatch. if your library is > designed to be extended in such a way that an importer can redefine how the > library's class hierarchy relates to a set of database tables, it seems like > the library would need to provide explicit injection points for that kind of > functionality where the persistence is set up just once. As opposed to the > library defining a full persistence model, then tearing down some parts and > replacing them. > > Its also not clear why the "extension" here wouldn't be a more traditional > form of extension, that of subclassing those library classes you'd wish to > extend. User can be subclassed with MySpecialUser, MySpecialUser can then > be mapped in any way the application sees fit. It doesn't make much sense > that the core library knows about a User and knows what table it's mapped > to, and then that library has functions that would continue to work as > expected when User is suddenly re-mapped to a join instead of a single > table, I can't really imagine how that works actually. >
> > I guess consider this a use case for why someone might want to be able > > to delete a mapper. I'm a bit surprised that there is no way to do so, > > Its easy enough to "delete" a mapper, remove its instrumentation from the > class and de-associate the mapper totally. I can show you the API calls. > But then all the other mappers that might reference that class are now in an > invalid state, referencing a dead mapper. Join conditions inside of > relationships reference possibly dead columns linked to possibly dead > tables. All of that state is invalid, and replacing with a new mapper > would mean we'd have to track all of those endpoints and surgically figure > out all the new linkages - these are linkages whose calculation is deferred > until the endpoints exist, and then are "locked down" to create sometimes > very complicated graphs of dependencies between classes. So the ratio of > complexity (huge) to usefulness (marginal, as there is always a way to defer > mapping until the model is complete) is why this is not supported. > Right, I didn't do a thorough job of explaining it, so I agree with the your assessment of the monkey patch, but my pattern isn't quite what you described ( because of my poor explanation! ). I'm using Pyramid and taking advantage of the Zope Component Architecture quite a bit. So there is a an application 'package' in ZCA speak, with it's own set of ZCA registrations, domain model classes and their user interface classes are all registered using ZCA interfaces. My client app includes packages from the base framework, with their domain model registrations and mapper registrations. One of those package is my base auth package, good enough as is for most client apps that include that package. The whole framework is broken up into packaged by functionality ( auth package, cms package, etc ). Part of what a package does is register it's model components in the registry and register a utility for mapping those. That way a domain app can use any of the components, or easily override any of the components by registering it's own version of one of the components under the same interface ( IUser or whatever). Mapper making callables are one of the components. In this case, my client app needs a different user model, so it registers a different class using the IUser interface. I got stuck on how to override one mapper only. Reading your description, I can see why I wouldn't want to clobber an already created mapper, though that would have been easiest from my client app perspective. The solution I've come to that seems to be an okay compromise is to replace the entire auth packages make_mappers callable with an override from the client app, in which I replace the User mapper. As this callable is registered as a ZCA utility named 'auth_mappers', if I register it through a ZCA package that is included with <includeOverrides..> it just hides the other auth mappers callable and we don't have the User mapper getting called twice. Long winded, but might be useful to someone googling some day! Thanks for your explanation, it no doubt saved me from trying some kind of surgical mapper deletion that would bite me in the ass later. =) iain > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
