использование динамического определения класса python и динамического сопоставления классов amfast и генерации кода для генерации класса ActionScript - PullRequest
0 голосов
/ 20 декабря 2011

У меня есть фрагмент XML, который содержит иерархию объектов:

doc = """\
<RootObj val1="ValueOne" stat1="Stat1" stat2="Stat2">
  <internalarray type="array">
    <InternalObject val1="12" val2="12" />
    <InternalObject val1="13" val2="13" />
    <InternalObject val1="14" val2="14" />
    <InternalObject val1="15" val2="15" />
  </internalarray>
</RootObj>"""

Я использую XML-представление ElementTree для анализа xml:

from xml.etree import ElementTree as ET
...
xml_doc = ET.XML(doc)

Я рекурсивно перебираю элементы xml_doc, создавая определения классов, используя "namedtuple":

from collections import namedtuple
...
def buildClass(name, node):
  symbol_table = {}
  args = []
  varnames = ""
  for subnode in node:
    args.append(buildClass(subnode.tag, subnode))
    if (subnode.tag not in symbol_table):
      symbol_table[subnode.tag] = 1
      varnames += subnode.tag + " "

  print 'Building class for:', name
  for (key, value) in node.items():
    args.append(value)
    varnames += key + " "
  varnames = varnames.strip()
  if (not name[0] == name[0].upper()):
    #this is an array, do not create a class, just return an array
    #pop the last element, "array"
    args.pop()
    return args
  globals()[name] = namedtuple(name, varnames)
  obj = globals()[name](*args)
  return obj

Что называется так:

  rootObj = build_class(xml_doc.tag, xml_doc)

Использование дампа, функции, найденной в другом месте в StackOverflow:

def dump(obj):
  '''return a printable representation of an object for debugging'''
  newobj=obj
  if '__dict__' in dir(obj):
    newobj=obj.__dict__
    if ' object at ' in str(obj) and not newobj.has_key('__type__'):
      newobj['__type__']=str(obj)
    for attr in newobj:
      newobj[attr]=dump(newobj[attr])
  return newobj

Вы можете позвонить:

print dump(rootObj)

И посмотрите (я отформатировал интервал вручную):

RootObj(
  internalarray=[
    InternalObject(val2='12', val1='12'), 
    InternalObject(val2='13', val1='13'), 
    InternalObject(val2='14', val1='14'), 
    InternalObject(val2='15', val1='15')
  ], 
  val1='ValueOne', stat2='Stat2', stat1='Stat1')

Итак, мы знаем, что код на самом деле генерирует класс. Теперь, если вы используете amfast DynamicClassMapper и генератор кода:

import amfast
from amfast import class_def
from amfast.class_def.code_generator import CodeGenerator   
...
class_mapper = class_def.ClassDefMapper()
mapped_class = class_def.DynamicClassDef(RootObj, 'RootObj', ())
#OR
#mapped_class = class_def.DynamicClassDef(globals()[xml_doc.tag],xml_doc.tag, ())
#I tried both and received the same output
coder = CodeGenerator()
coder.generateFilesFromMapper(class_mapper, use_accessors=False,
  packaged=True, constructor=True, bindable=True, extends='Object')

Вы получаете файл, RootObj.as:

package
{
  [Bindable]
  [RemoteClass(alias='RootObj')]
  public dynamic class RootObj extends Object
  {
    public function RootObj():void
    {
      super();
    }
  }
}

В котором явно отсутствуют все атрибуты и еще много чего. Есть ли способ использовать эту методологию кодирования для вывода файла ActionScript, который на самом деле содержит правильное определение класса?

1 Ответ

0 голосов
/ 30 декабря 2011

Хорошо, очевидно, это то, что никто не знает, как это сделать, поэтому я нашел обходной путь.

Я изменил функцию buildClass () следующим образом:

def buildClass(name, node):
  global _classes
  symbol_table = {}
  args = []
  varnames = ""
  varnameswithtypes = ""
  for subnode in node:
    args.append(buildClass(subnode.tag, subnode))
    if (subnode.tag not in symbol_table):
      symbol_table[subnode.tag] = 1
      varnames += subnode.tag + " "
      if (not subnode.tag[0] == subnode.tag[0].upper()):
        varnameswithtypes += subnode.tag + ":array "
      else:
        varnameswithtypes += subnode.tag + ":object "

  print 'Building class for:', name
  for (key, value) in node.items():
    args.append(value)
    varnames += key + " "
    if (key == "variable_name"):
      varnameswithtypes+= key + ":" + value + " "
    elif (is_numeric(value)):
      varnameswithtypes+= key + ":numeric" + " "
    else:
      varnameswithtypes+= key + ":text" + " "
  varnames = varnames.strip()
  varnameswithtypes = varnameswithtypes.strip()

  if (_classes.has_key(name)):
    if (len(_classes[name]) < len(varnameswithtypes)):
      _classes[name] = varnameswithtypes
  else:
    _classes[name] = varnameswithtypes

  if (not name[0] == name[0].upper()):
    #this is an array, do not create a class, just return an array
    return args
  #print varnames, args
  globals()[name] = namedtuple(name, varnames)
  obj = globals()[name](*args)
  #print dump(obj)
  return obj

Затем добавил:

_classdefs = {}
def getClassDef(name):
  global _classdefs, _classes
  _classdefs[name] = "class " + name + "(object):\n   def __init__(self):\n"    
  classvars = _classes[name].split(" ")
  for x in classvars:
    vals = x.split(":")
    if (vals[1] == "array"):
      c = _classes[vals[0]].split(":")[0]
      if (not _classdefs.has_key(c)):
        getClassDef(c)
      _classdefs[name] += "    self." + vals[0] + " = []\n"
    elif (vals[1] == "text"):
      _classdefs[name] += "    self." + vals[0] + " = \"\"\n"
    elif (vals[1] == "numeric"):
      _classdefs[name] += "    self." + vals[0] + " = 0\n"
    elif (vals[1] == "object"):
      if (not _classdefs.has_key(vals[0])):
        getClassDef(vals[0])
      subclassvars = _classes[vals[0]].split(" ")
      for z in subclassvars:
        if (z.split(":")[0] == "variable_name"):
          _classdefs[name] += "    self." + z.split(":")[1] + " = " + vals[0] + "()\n"

Который вы называете так:

getClassDef("RootObj")
for x in _classdefs.keys():
  print _classdefs[x]

Использование xml:

<RootObj val1="ValueOne" stat1="Stat1" stat2="Stat2">
  <internalarray>
    <InternalObject val1="12" val2="12" />
    <InternalObject val1="13" val2="13" />
    <InternalObject val1="14" val2="14" />
    <InternalObject val1="15" val2="15" />
  </internalarray>
  <InternalObject2 val1="12" val2="13" variable_name="intObj2" />
</RootObj>

Код выведет:

class RootObj(object):
   def __init__(self):
    self.internalarray = []
    self.intObj2 = InternalObject2()
    self.val1 = ""
    self.stat2 = ""
    self.stat1 = ""

class InternalObject2(object):
   def __init__(self):
    self.val2 = 0
    self.val1 = 0

class InternalObject(object):
   def __init__(self):
    self.val2 = 0
    self.val1 = 0

Который затем можно сохранить в файл .py и импортировать для использования с генерацией кода amfast amfast, как обычно.Иди ко мне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...