> Hi Dave,
> unfortunately it's been awhile again since my last input to this.
> Sorry about that and happy new year everybody :).
> 
> Comments/answers on your suggestions below.
> 
> Another proposal/question from my side:
> I had a more detailed look at the internal workings of generateDS and 
> couldn't really make up my mind on figuring out why things are 
> implemented the way they are. So please correct me if I'm wrong. 
> 
> My problem mostly evolves around the factory functions for the 
> schema-based objects making their decision whether to return the object
> of type parent-class or type subclass. 
> Because this decision(implementation of the factory-functions)
> is made based on the  'subclass'-classvariable of parent. 
> This results in the parent-class only  being able to be usable by
> one subclass, namely the one who last set its name to the 'subclass' 
> variable in parent's class. 

Florian,

I'm still trying to come up with a solution to your problem.  I
believe I've got a way to do what you need, if I understand that
need correctly.

Here is what makes it a bit difficult -- We must be able to use the
submodules as a replacement for the supermodule.  This means that
the build methods (in the supermodule) must be able to create
instances of the specific submodule that we are using at that time.
Effectively, the superclass module must be wired to create
subclasses from a specific subclass module at any given time.

However, in your case, I believe, you want to be able to change
*which* subclass module is used while your application is running.
Do I have that right?  If so, ...

I've attached a Python script that can be used to "fix up" the
subclass references in a superclass module.  It uses the module's
__all__ attribute, which contains a list of generated classes, to
update each class.

Let's assume that you have two separate versions of the same
submodule: submodule_1 and submodule_2.  You have added different
code to each of these submodules.  Now, you want to be able to parse
an XML instance document and create instances of the classes in
submodule_1; later, while the same application is still running, you
want to be able to parse an XML doc and create instances of the
classes in submodule_2.  Here is how you might do that with the help
of this fix-up function:

    import fix_subclass_refs
    import supermodule
    import submodule_1
    import submodule_2

    fix_subclass_refs.fix_up_refs(supermodule, submodule_1)
    submodule_1.parse('data.xml')

    fix_subclass_refs.fix_up_refs(supermodule, submodule_2)
    submodule_2.parse('data.xml')

Does this solve your problem?

If we can get something like this to work for you, then we can talk
about including it with the distribution for others to use, also.

Dave


> 
> I would like to hear your opinion, if it's reasonable to change the 
> architecture
> of generateDS so that you call constructor/factory on the subclass rather 
> than the parent class to return the proper type instead of using the factory 
> in 
> the parent class.
> This could enable the system to use multiple subclasses with the same 
> parent and does not need the subclasses to link to their parent over the 
> 'subclass'-classvariable.
> In the current setup such an approach would break the buildChildren()-method 
> though.
> Or at least have it return objects of parent-class type instead of 
> subclass-type.
> So to work around this one would have to make generateDS put an adjusted 
> version
> of the buildChildren()-method into the subclasses as well which would work on 
> subclass-types 
> of that respective class instead of the types of the parent. 
> 
> I know this may be a long shot and will require quite an amount of change of 
> the inner 
> architecture, but nevertheless I would like to hear your opinion about it. 
> Also please tell me if
> I took a complete wrong turn in my thinking and I'm the only one needing a 
> solution for this 
> anyways ;)
> 
> Best Regards
> Florian Wilmshöver
> 
> > -----Ursprüngliche Nachricht-----
> > Von: Dave Kuhlman [mailto:dkuhl...@davekuhlman.org]
> > Gesendet: Freitag, 6. November 2015 00:37
> > An: Florian Wilmshoever
> > Cc: generateds-users@lists.sourceforge.net
> > Betreff: Re: [Generateds-users] subclass questions/issues
> > 
> > On Wed, Nov 04, 2015 at 05:01:47PM +0000, Florian Wilmshoever wrote:
> > >
> > > Hi Dave, Hi list,
> > >
> > > first of all thanks for working in the adjustments for the attribute
> > > references we talked about a while ago.
> > >
> > > generateDS has been working very well for me since then.
> > >
> > 
> > Florian,
> > 
> > Good to hear from you.  Glad to hear that generateDS.py is *mostly*
> > working well for you.
> > 
> > > Unfortunately like a couple of days ago I tried to integrate a second,
> > > generated subclass into my program and came across some unexpected
> > > behaviour.
> > >
> > > The setup is as follows.
> > > -generated parent class 'parent'
> > > -two generated subclasses 'subA' and 'subB'
> > 
> > How did you generate the subclass modules?  Did you use the "-s"
> > command line option?
> > 
> Yes, I did use the '-s'-option. 
> 
> > >
> > > In my own module I'm parsing a xml file according to the base xsd of 
> > > parent.
> > >
> > > My module imports both subclass-modules to either create an instance
> > > of 'subA' or 'subB' by using
> > >
> > > modulesubA.parse(filename) or modulesubB.parse(filename).
> > >
> > > The unexpected behaviour while testing this, no matter which parse
> > > function I call, both will return an object of the last imported
> > > subclass module.
> > >
> > > So if my imports look like this:
> > >
> > > 'import modulesubA'
> > > 'import modulesubB'
> > >
> > > Both function calls:
> > > 'modulesubA.parse(filename)'
> > > 'modulesubB.parse(filename)'
> > > will return an object of type 'subB'.
> > 
> > A couple of things to think about (which you are likely already aware of):
> > 
> > - When you import a module, it is only imported once, even if you
> >   try to import it twice.
> > 
> > - Therefore, there will only be one instance of the superclass
> >   module.
> > 
> > - And, therefore, that class variable 'subclass' will have a single
> >   value.
> > 
> 
> > >
> > > If you change the order of the imports, it will be the other way round.
> > >
> > > My initial observation is, that this is due to the assignment of the
> > > classvariable 'subclass' in 'parent'.
> > 
> > I believe you are right.
> > 
> > >
> > > It seems to get assigned from each modulesubA and modulesubB initially
> > > while importing them and after that the factory function of the main
> > > class will only return objects of the subclass which was assigned
> > > there last.
> > 
> > One thing to try is to make two copies of the superclass module, that is, 
> > copy
> > the file itself.  Or, if you are on Linux, make a symbolic link; I don't 
> > know how
> > to do that on MS Windows.  Then change the import statements in the
> > subclass modules so they import two different modules.
> > 
> I think this will be my fallback solution, though it's a bit contrary to my 
> understanding of how inheritance should work. 
> 
> > Or, here is an alternative that you can try -- Try to force the import to 
> > really
> > happen a second time by doing something like the
> > following:
> > 
> >        import sys
> >        sys.modules.pop('modulesuper')
> >        import modulesubA        # or modulesubB
> > 
> > Take a look at the documentation on 'sys.modules'.
> > (https://docs.python.org/2/library/sys.html#sys.modules)
> > It says:
> > 
> >     "This is a dictionary that maps module names to modules which have
> >     already been loaded. This can be manipulated to force reloading of
> >     modules and other tricks. Note that removing a module from this
> >     dictionary is not the same as calling reload() on the corresponding
> >     module object."
> > 
> > So, possibly, if you do the sys.modules.pop(mod_name) before each import
> > of a sub-module, that will change the behavior.
> > 
> I'd rather not let my code change the import order or reload modules if don't 
> absolutely 
> have to. From an architecture point of view it seems to be more prone to 
> error or 
> maintenance issues than just having two base classes with the same content. 
> 
> > Actually, copying the superclass module (or making symbolic links) seems to
> > me to be a better and less devious and less tricky approach.  But, of 
> > course, I
> > don't know your specific needs.
> > 
> I agree.  
> 
> > Let me know if any of the above solves your problem.
> > 
> > And, tell me if there is other help I can give.
> Thanks. I really appreciate the your input and support on the matter. 
> 
> > 
> > Dave
> > 
> > >
> > > I may have an idea on how this could be solved, but I would like to
> > > have some opinion or discussion from you first.
> > >
> > > I can also provide an minimal example of this but that will take me
> > > some more time, so I hope it gets understood like I described.
> > >
> > > Let me know if you can reproduce this behavior or need me to provide
> > > some more information.
> > >
> > > Thanks & Best Regards
> > > Florian Wilmshöver
> > >
> > >
> > 
> > --
> > 
> > Dave Kuhlman
> > http://www.davekuhlman.org
-- 

Dave Kuhlman
http://www.davekuhlman.org
#!/usr/bin/env python

"""
synopsis:
    Fix up subclass references so that the classes in the superclass
    module refer to classes in a specified submodule.
    The superclass module was generated with the generateDS.py "-o"
    command line option; the subclass module was generated with "-s".
    The intended use is to be able to switch between different versions
    of submodules generated from the same XML schema.
usage:
    python fix_subclass_refs.py <supermodname> <submodname1> <submodname2>
examples:
    From the command line for testing purposes:
        python fix_subclass_refs.py datalib datasub1 datasub2
    From within an application -- Suppose we want to switch between the use
    of submodule_1 and submodule_2 while our application is running:
        import fix_subclass_refs
        import supermodule
        import submodule_1
        import submodule_2
            ...
        fix_subclass_refs.fix_up_refs(supermodule, submodule_1)
        submodule_1.parse('data.xml')
            ...
        fix_subclass_refs.fix_up_refs(supermodule, submodule_2)
        submodule_2.parse('data.xml')
"""


from __future__ import print_function
import sys
import importlib


def fix_up_refs(supermod, submod):
    """Change the value of class variable "subclass" so that it refers
    to the subclass in "submod".
    """
    count = 0
    for superclassname in supermod.__all__:
        superclass = getattr(supermod, superclassname)
        if superclass.subclass is None:
            # never happens?
            print('*** {} missing subclass'.format(superclassname))
            pass
        else:
            subclassname = superclass.subclass.__name__
            subclass = getattr(submod, subclassname)
            superclass.subclass = subclass
            count += 1
    return count


def show(supermod):
    count = 0
    for superclassname in supermod.__all__:
        superclass = getattr(supermod, superclassname)
        print('subclass: {}'.format(superclass.subclass))
        count += 1
    return count


def test(supermodname, submodname1, submodname2):
    supermod = importlib.import_module(supermodname)
    submod1 = importlib.import_module(submodname1)
    importlib.import_module(submodname2)
    count = show(supermod)
    print('count: {}'.format(count))
    count = fix_up_refs(supermod, submod1)
    print('fix-up count: {}'.format(count))
    raw_input('Press Enter to continue ')
    print('-' * 50)
    count = show(supermod)
    print('count: {}'.format(count))


def main():
    args = sys.argv[1:]
    if len(args) != 3:
        sys.exit(__doc__)
    supermodname = args[0]
    submodname1 = args[1]
    submodname2 = args[2]
    test(supermodname, submodname1, submodname2)


if __name__ == '__main__':
    main()
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
generateds-users mailing list
generateds-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/generateds-users

Reply via email to