python-javaobj icon indicating copy to clipboard operation
python-javaobj copied to clipboard

Custom transformer - create_instance invoked incorrectly?

Open UnitedMarsupials opened this issue 2 years ago • 2 comments

Hello!

I'm trying to parse a file serializing an ArrayList of custom functions -- and I cannot even get the basics going...

Below is my entire script. Without the default value (such as None) for the class_desc, I get an error:

  File "/home/mi/.local/lib/python3.9/site-packages/javaobj/v2/core.py", line 528, in _do_object
    instance = self._create_instance(class_desc)
  File "/home/mi/.local/lib/python3.9/site-packages/javaobj/v2/core.py", line 503, in _create_instance
    instance = transformer.create_instance(class_desc)
TypeError: create_instance() missing 1 required positional argument: 'class_desc'

If I put the default value, the call to create_instance goes through, and the method prints the value of self, which indicates, that it is the class_desc -- instead of referring to the transformer:

INFO:javaobj.parser:Reading next content
DEBUG:javaobj.parser:Reading new object: handle 7e0001, classdesc [classdesc 0x7e0000: name java.util.ArrayList, uid 8683452581122892189]
Self is [classdesc 0x7e0000: name java.util.ArrayList, uid 8683452581122892189], class_desc is None
Traceback ...

Please, advise. Thank you!

import javaobj.v2 as javaobj
import sys
import os
import json
import pprint
import logging

logging.basicConfig(level = logging.DEBUG)

class odrnavsFunctionInstance(javaobj.beans.JavaInstance):
	def __init__(self):
		javaobj.beans.JavaInstance.__init__(self)

	def load_from_instance(self):
		if not self.classdesc or self.classdesc not in self.field_data:
			return False

		fields = self.classdesc.fields_names
		values = [
			self.field_data[self.classdesc][self.classdesc.fields[i]]
			for i in range(len(fields))
		]
		self.field_data = dict(zip(fields, values))
		if not self.classdesc.super_class or \
		    self.classdesc.super_class not in self.annotations:
			return True
		super_class = self.annotations[self.classdesc.super_class][0]
		self.annotations = dict(zip(super_class.fields_names, super_class.field_data))
		return True

class odrnavsTransformer(javaobj.transformers.ObjectTransformer):

	def __init__(self, handled_classes = {
		'my.apps.datalayer.client.navs.shared.api.Function':
		    odrnavsFunctionInstance
	}):
		super(JavaRandomTransformer, self).__init__()
		self.instance = None
		self.handled_classes = handled_classes or {}

	def create_instance(self, class_desc = None):
		print('Self is %s, class_desc is %s' % (self, class_desc))
		if class_desc.name not in self.handled_classes:
			return None
		self.instance = self.handled_classes[class_desc.name]()
		return self.instance

if sys.argv[1].endswith('.gz'):
	import gzip
	opener = gzip.open
else:
	opener = open

obj = None
with opener(sys.argv[1], 'rb') as inp:
		obj = javaobj.load(inp, odrnavsTransformer)

pprint.pprint(obj)

UnitedMarsupials avatar Aug 02 '23 23:08 UnitedMarsupials

Hi Sorry for the long delay, I seem to have missed the notifications for this project.

Regarding your issue: the transformers given to javaobj.v2.load are supposed be instances, not classes. As a result, you should call obj = javaobj.load(inp, odrnavsTransformer()) instead of obj = javaobj.load(inp, odrnavsTransformer).

tcalmant avatar Apr 07 '24 19:04 tcalmant