(root)/
libredwg-0.13/
test/
xmlsuite/
helper.py
       1  # -*- indent-tabs-mode:1 tab-width:4 mode:python minor-mode:whitespace -*-
       2  import libxml2
       3  import re
       4  import os
       5  import glob
       6  
       7  
       8  '''
       9  This class has all the colors to be used with colored output
      10  terminal.
      11  '''
      12  class ESC[4;38;5;81mbcolors:
      13  	HEADER = '\033[95m'
      14  	OKBLUE = '\033[94m'
      15  	OKGREEN = '\033[92m'
      16  	WARNING = '\033[93m'
      17  	FAIL = '\033[91m'
      18  	ENDC = '\033[0m'
      19  
      20  
      21  '''
      22  This functions uses the script to generate xml which can be used for
      23  comparison later.
      24  
      25  @param string dwgdir The path to DWG dir
      26  '''
      27  def generatexml(dwgdir):
      28  	# This beats ‘sys.argv[0]’, which is not guaranteed to be set.
      29  	me = os.getenv ("PYTHON")
      30  	if not me:
      31  		me = "python"
      32  	srcdir = os.path.dirname(__file__)
      33  	current_dir = os.getcwd()
      34  	os.chdir(dwgdir)
      35  	for filename in glob.glob ("*/*.txt"):
      36  		# maybe add double-quotes for the script?
      37  		os.system (me + " " + srcdir + "/txttoxml.py " + filename + " "
      38  					  + current_dir + "/test_output")
      39  	os.chdir(current_dir)
      40  
      41  '''
      42  This functions main aim is to process special types of attributes
      43  which are difficult to equate to each other. Currently this only
      44  handles 2D and 3D point. It converts these string in certain format
      45  so that they can be equated
      46  
      47  @param string attr the attribute to be processed
      48  @return string The processed attribute
      49  '''
      50  def processattr(attr):
      51  	pattern = re.compile(r"(\d+\.\d{1,})\s{0,1}")
      52  	if re.search(pattern, attr):
      53  		#extract the numbers and adjust them
      54  		extract_pattern = re.compile(r"(\d+\.\d{1,})\s{0,1}");
      55  		result = extract_pattern.findall(attr)
      56  		for no in range(len(result)):
      57  			result[no] = float(result[no])
      58  
      59  		#if its a 3d point
      60  		if len(result) == 3:
      61  			return "(%.2f %.2f %.2f)" % (round(result[0],2), round(result[1],2),
      62  										 round(result[2],2))
      63  		elif len(result) == 2:
      64  			return "(%.2f %.2f)" % round(round(result[0],2), round(result[1],2))
      65  	else:
      66  		return attr
      67  
      68  '''
      69  This function takes handle to both ideal file which came from AutoCAD and
      70  practical file which came from LibreDWG and compares them to emit out the
      71  result
      72  
      73  @param ideal Name of the ideal file
      74  @param practical Name of the practical file
      75  
      76  return array[2]
      77  [0] = The percentage of entity that matched
      78  [1] = The unmatched attributes with following format
      79  	{attrname, original, duplicate}
      80  	attrname =  Name of the attribute
      81  	original = Value came from AutoCAD
      82  	duplicate = Value that came from LibreDWG.
      83  '''
      84  def xmlprocess(ideal, practical):
      85  	doc = libxml2.parseFile(ideal)
      86  
      87  	root = doc.getRootElement()
      88  	child = root.children
      89  
      90  	# Let's first collect all the entities present in the file
      91  	original_entities = []
      92  
      93  	while child is not None:
      94  		if child.type == "element":
      95  			original_entities.insert(len(original_entities), child)
      96  		child = child.next
      97  
      98  	doc2 = libxml2.parseFile(practical)
      99  
     100  	root2 = doc2.getRootElement()
     101  	child2 = root2.children
     102  
     103  	duplicate_entities = []
     104  
     105  	while child2 is not None:
     106  		if child2.type == "element":
     107  			duplicate_entities.insert(len(duplicate_entities), child2)
     108  		child2 = child2.next
     109  
     110  	match = 0
     111  
     112  	# Now its time for comparison, For each dwg entity
     113  	for original, duplicate in zip(original_entities, duplicate_entities):
     114  		original_attributes = {}
     115  		duplicate_attributes = {}
     116  		excluded_attributes = ["Delta", "id", "Document", "Visible", "text",
     117  							   "Application", "Hyperlinks"]
     118  
     119  		# collect original attributes. Removing the attributes here, so the
     120  		# total length is also set
     121  		try:
     122  			#print (ideal + " original.properties")
     123  			for attr in original.properties:
     124  				if attr.name not in excluded_attributes:
     125  					original_attributes[attr.name] = processattr(attr.content)
     126  		except (TypeError):
     127  			print ("Need python3 compatible libxml2 with __next__ iterator")
     128  
     129  		try:
     130  			for attr in duplicate.properties:
     131  				duplicate_attributes[attr.name] = processattr(attr.content)
     132  		except (TypeError):
     133  			pass
     134  
     135  		unmatched_attr = []
     136  		# collect duplicate attributes and check if it matches with
     137  		# original ones
     138  		for key,value in original_attributes.items():
     139  			try:
     140  				if value == duplicate_attributes[key]:
     141  					match += 1
     142  				else:
     143  					# The attributes didn't match.
     144  					# Report the unmatched attribute
     145  					unmatched_attr.append({"attrname" : key, "original" : value,
     146  									"duplicate" : duplicate_attributes[key]})
     147  
     148  			except Exception:
     149  				# This exception would occur when
     150  				# We can't find the given attribute
     151  
     152  				unmatched_attr.append({"attrname" : key, "original" : value,
     153  									 "duplicate" : ""})
     154  				continue
     155  
     156  	# What are the total number of attributes
     157  	try:
     158  		total_attr = len(original_attributes)
     159  		if total_attr == 0:
     160  			percent_each = 0
     161  		else:
     162  			percent_each = 100 / total_attr
     163  	except NameError:
     164  		return [0,[]]
     165  		raise
     166  
     167  
     168  	res_percent = percent_each*match;
     169  
     170  	doc.freeDoc()
     171  	doc2.freeDoc()
     172  
     173  	return [res_percent, unmatched_attr]