[Piglit] [PATCH 2/2] framework/backends/json.py: preserve 'tests' order

Tomi Sarvela tomi.p.sarvela at intel.com
Thu Feb 9 11:07:05 UTC 2017


New helper function numericlistdir() arranges the os.listdir()
in numerical order and deduplicates the code: reading in is done
in two places, finalize and _resume.

Use OrderedDict when reading data in.
---
 framework/backends/json.py | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/framework/backends/json.py b/framework/backends/json.py
index 174c0ca..6e67462 100644
--- a/framework/backends/json.py
+++ b/framework/backends/json.py
@@ -29,6 +29,8 @@ import os
 import posixpath
 import shutil
 import sys
+import re
+from collections import OrderedDict
 
 try:
     import simplejson as json
@@ -62,6 +64,16 @@ MINIMUM_SUPPORTED_VERSION = 7
 INDENT = 4
 
 
+def numericlistdir(path):
+    """Returns os.listdir with items sorted by their numerical value (if any)
+
+    Pass possible errors (FileNotFoundError, PermissionError) upwards
+    """
+    return sorted(os.listdir(path), key =
+        lambda x: (-1, x) if not re.match(r'^\d+', x)
+        else (int(re.findall(r'^\d+', x)[0]), x) )
+
+
 def piglit_encoder(obj):
     """ Encoder for piglit that can transform additional classes into json
 
@@ -125,12 +137,15 @@ class JSONBackend(FileBackend):
         containers that are still open and closes the file
 
         """
+        tests_dir = os.path.join(self._dest, 'tests')
+        file_list = numericlistdir(tests_dir)
+
         # If jsonstreams is not present then build a complete tree of all of
         # the data and write it with json.dump
         if not _STREAMS:
             # Create a dictionary that is full of data to be written to a
             # single file
-            data = collections.OrderedDict()
+            data = OrderedDict()
 
             # Load the metadata and put it into a dictionary
             with open(os.path.join(self._dest, 'metadata.json'), 'r') as f:
@@ -141,11 +156,10 @@ class JSONBackend(FileBackend):
                 data.update(metadata)
 
             # Add the tests to the dictionary
-            data['tests'] = collections.OrderedDict()
+            data['tests'] = OrderedDict()
 
-            test_dir = os.path.join(self._dest, 'tests')
-            for test in os.listdir(test_dir):
-                test = os.path.join(test_dir, test)
+            for test in file_list:
+                test = os.path.join(tests_dir, test)
                 if os.path.isfile(test):
                     # Try to open the json snippets. If we fail to open a test
                     # then throw the whole thing out. This gives us atomic
@@ -177,15 +191,14 @@ class JSONBackend(FileBackend):
                     s.write('__type__', 'TestrunResult')
                     with open(os.path.join(self._dest, 'metadata.json'),
                               'r') as n:
-                        s.iterwrite(six.iteritems(json.load(n)))
+                        s.iterwrite(six.iteritems(json.load(n), object_pairs_hook=OrderedDict))
 
                     if metadata:
                         s.iterwrite(six.iteritems(metadata))
 
-                    test_dir = os.path.join(self._dest, 'tests')
                     with s.subobject('tests') as t:
-                        for test in os.listdir(test_dir):
-                            test = os.path.join(test_dir, test)
+                        for test in file_list:
+                            test = os.path.join(tests_dir, test)
                             if os.path.isfile(test):
                                 try:
                                     with open(test, 'r') as f:
@@ -259,7 +272,7 @@ def _load(results_file):
 
     """
     try:
-        result = json.load(results_file)
+        result = json.load(results_file, object_pairs_hook=OrderedDict)
     except ValueError as e:
         raise exceptions.PiglitFatalError(
             'While loading json results file: "{}",\n'
@@ -283,11 +296,14 @@ def _resume(results_dir):
     assert meta['results_version'] == CURRENT_JSON_VERSION, \
         "Old results version, resume impossible"
 
-    meta['tests'] = {}
+    meta['tests'] = OrderedDict()
 
     # Load all of the test names and added them to the test list
-    for file_ in os.listdir(os.path.join(results_dir, 'tests')):
-        with open(os.path.join(results_dir, 'tests', file_), 'r') as f:
+    tests_dir = os.path.join(results_dir, 'tests')
+    file_list = numericlistdir(tests_dir)
+
+    for file_ in file_list:
+        with open(os.path.join(tests_dir, file_), 'r') as f:
             try:
                 meta['tests'].update(json.load(f))
             except ValueError:
-- 
2.9.3



More information about the Piglit mailing list