Re: Dynamic Class Creation
In article <8d79f0cb-9c5b-4243-8891-a15fb311f...@z18g2000prh.googlegroups.com>, Josh English wrote: > > >Analog Science Fiction and Fact >Analog >Science Fiction >First Contact >Hard Science Fiction > >Stanley Schmidt, Editor >267 Broadway, 4th Floor >New York, NY 10007-2352 > >http://www.analogsf.com > > >A child element with text and an attribute or two, for example, pose a >problem. I can call Market.title but should I try Market.title.field >or Market.title_field. > >Multiple elements, such as keywords, are allowed in xml but harder to >map to the object. I don't know if I want to go create a list and >methods for accessing those keywords as a list, or redefine the rules >of my XML to not allow multiple child elements with the same tag. I >can't decide. You should always think "LIST!" any time you have the potential for multiple elements with the same semantic tag. Whether you do it as a list for all elements or as a combo dict/list is something you need to decide; the latter is faster in many ways but is more cumbersome: Market.title.keyword[1] (Instance attributes and dict keys are almost trivially convertible.) You would probably get some mileage out of looking at the ElementTree implementation. -- Aahz (a...@pythoncraft.com) <*> http://www.pythoncraft.com/ Why is this newsgroup different from all other newsgroups? -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic Class Creation
Josh English wrote: Chris, Thanks. This worked for the attributes, but I think the tactic is still misleading. There are child elements I can't quite determine how to deal with: Analog Science Fiction and Fact Analog Science Fiction First Contact Hard Science Fiction Stanley Schmidt, Editor 267 Broadway, 4th Floor New York, NY 10007-2352 http://www.analogsf.com A child element with text and an attribute or two, for example, pose a problem. I can call Market.title but should I try Market.title.field or Market.title_field. Multiple elements, such as keywords, are allowed in xml but harder to map to the object. I don't know if I want to go create a list and methods for accessing those keywords as a list, or redefine the rules of my XML to not allow multiple child elements with the same tag. I can't decide. Then the address is a bit of a bear. In short, I have to figure out the whole object interface to the XML and how I want that to work. Have you heard of or considered PyXB (http://pyxb.sourceforge.net/)? Not that I've much experience with it, but you can use it to generate python code from XML Schema files, and, I think, WSDL definitions. It's a bit of a rabbit hole, but then isn't that half the fun! The following might give you the idea. You start with a Schema schema.xsd, generate a python module from it, then read in some XML with the generated classes to get your custom objects. schema.xsd -- http://www.josh.com/schema/0.1"; xmlns:xs="http://www.w3.org/2001/XMLSchema"; xmlns:josh="http://www.josh.com/schema/0.1";> maxOccurs="unbounded"/> minOccurs="0"/> minOccurs="0"/> genbindings.sh --- #!/bin/sh pyxbgen -u schema.xsd -m market_binding -r demo.py --- s = """ http://www.josh.com/schema/0.1"; code="anlg" tier="ProMarket" mail="True"> Analog Science Fiction and Fact Analog Science Fiction First Contact Hard Science Fiction Stanley Schmidt, Editor 267 Broadway, 4th Floor New York http://www.analogsf.com """ import xml.dom.minidom import market_binding market = market_binding.CreateFromDOM(xml.dom.minidom.parseString(s).documentElement) print market.tier print market.code print market.keyword assert len(market.keyword) == 3 print market.address.name print market.toxml() -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic Class Creation
Chris, Thanks. This worked for the attributes, but I think the tactic is still misleading. There are child elements I can't quite determine how to deal with: Analog Science Fiction and Fact Analog Science Fiction First Contact Hard Science Fiction Stanley Schmidt, Editor 267 Broadway, 4th Floor New York, NY 10007-2352 http://www.analogsf.com A child element with text and an attribute or two, for example, pose a problem. I can call Market.title but should I try Market.title.field or Market.title_field. Multiple elements, such as keywords, are allowed in xml but harder to map to the object. I don't know if I want to go create a list and methods for accessing those keywords as a list, or redefine the rules of my XML to not allow multiple child elements with the same tag. I can't decide. Then the address is a bit of a bear. In short, I have to figure out the whole object interface to the XML and how I want that to work. Thanks for the suggestion. It is undeniably clever. Josh -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic Class Creation
On Tue, Mar 16, 2010 at 9:49 AM, Jack Diederich wrote: > On Tue, Mar 16, 2010 at 2:18 AM, Chris Rebert wrote: >> On Mon, Mar 15, 2010 at 11:01 PM, Josh English >> wrote: >>> What's the best way to create these helper methods? > > You can either define a catch-all __getattr__ method to look them up > dynamically, or as Chris kinda-suggested write descriptors for the > individual elements. > > class Market(): > def __init__(self, elem): > self._elem = elem > def __getattr__(self, name): > try: > # I'm assuming this raises a KeyError when not found > return self._elem.get(name) > except KeyError: > return self._elem.find(name) > def __setitem__(self, name, value): did you mean __setattr__ here? > The getattr/setattr method is easier to understand and will handle > arbitrary elements; for the descriptors version you'll have to define > one for each tag that might be used on the class. Cheers, Chris -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic Class Creation
On Tue, Mar 16, 2010 at 2:18 AM, Chris Rebert wrote: > On Mon, Mar 15, 2010 at 11:01 PM, Josh English > wrote: >> I have a large program with lots of data stored in XML. I'm upgrading >> my GUI to use ObjectListView, but with my data in XML, I don't have >> regular objects to interact with the OLV. I do have an XML validator >> that defines the structure of the XML elements, and I'm trying to >> dynamically create a class to wrap the XML element. >> >> So, an element like: >> >> >> Writers of the Future >> >> >> I want to create a class like: >> >> class Market(object): >> def __init__(self, elem): >> self._elem = elem >> >> def get_code(self): >> return self._elem.get('code') >> >> def set_code(self, value): >> self._elem.set('code', value) >> >> def get_title(self): >> return self._elem.find('title').text >> >> def set_title(self, value): >> node = self._elem.find('title') >> node.text = value >> >> Naturally, I don't want to hand code this for every interface but >> would like to create them dynamically. (The laziness of programming, I >> guess.) >> >> What's the best way to create these helper methods? You can either define a catch-all __getattr__ method to look them up dynamically, or as Chris kinda-suggested write descriptors for the individual elements. class Market(): def __init__(self, elem): self._elem = elem def __getattr__(self, name): try: # I'm assuming this raises a KeyError when not found return self._elem.get(name) except KeyError: return self._elem.find(name) def __setitem__(self, name, value): # like __getitem__ but for setting Chris' property maker function is almost like a descriptor class (how properties are implemented under the hood), here's a refactoring [untested] class ElemGetProperty(): def __init__(self, name): self.name = name def __get__(self, ob, cls): return ob._elem.get(self.name) def __set__(self, ob, val): ob._elem.set(self.name, val) You could write one property class for each kind of element (get/find) and then put them in your class like this class Market(): code = ElemGetProperty('code') title = ElemFindProeprty('title') The getattr/setattr method is easier to understand and will handle arbitrary elements; for the descriptors version you'll have to define one for each tag that might be used on the class. -Jack -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic Class Creation
On Mon, Mar 15, 2010 at 11:01 PM, Josh English wrote: > I have a large program with lots of data stored in XML. I'm upgrading > my GUI to use ObjectListView, but with my data in XML, I don't have > regular objects to interact with the OLV. I do have an XML validator > that defines the structure of the XML elements, and I'm trying to > dynamically create a class to wrap the XML element. > > So, an element like: > > > Writers of the Future > > > I want to create a class like: > > class Market(object): > def __init__(self, elem): > self._elem = elem > > def get_code(self): > return self._elem.get('code') > > def set_code(self, value): > self._elem.set('code', value) > > def get_title(self): > return self._elem.find('title').text > > def set_title(self, value): > node = self._elem.find('title') > node.text = value > > Naturally, I don't want to hand code this for every interface but > would like to create them dynamically. (The laziness of programming, I > guess.) > > I have tried several solutions that I found on various forums, but > they are all several years old. > > Questions: > > What's the best way to create these helper methods? Nested functions: def make_attr_getset(name): def get(self): return self._elem.get(name) def set(self, value): self._elem.set(name, value) return get, set get_code, set_code = make_attr_getset('code') def make_subelement_getset(name): def get(self): return self._elem.find(name).text def set(self, value): node = self._elem.find(name) node.text = value return get, set get_title, set_title = make_subelement_getset('title') > How can I attach them to the class and have it run? Use properties and setattr(): class Market(object): def __init__(... #same as before setattr(Market, 'code', property(get_code, set_code)) setattr(Market, 'title', property(get_title, set_title)) m = Market(the_XML) print m.title #=> Writers of the Future m.title = "Writers of the Past" print m.code #=> WotF m.code = "WofP" Cheers, Chris -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list