Repository: frictionlessdata/goodtables-py

Issue:
Add datapackages preset
# Overview

Required by https://github.com/frictionlessdata/goodtables.io/issues/17

Discussion:
roll: @amercader 
please take a look

Patch:
diff --git a/README.md b/README.md
index 2fc94ba..5173225 100644
--- a/README.md
+++ b/README.md
@@ -119,6 +119,7 @@ Goodtables by default supports the following presets:
 - table
 - tables
 - datapackage
+- datapackages
 
 #### Custom presets
 
diff --git a/examples/datapackages.py b/examples/datapackages.py
new file mode 100644
index 0000000..6545c9b
--- /dev/null
+++ b/examples/datapackages.py
@@ -0,0 +1,9 @@
+from pprint import pprint
+from goodtables import Inspector
+
+inspector = Inspector()
+report = inspector.inspect([
+    'data/datapackages/valid/datapackage.json',
+    {'source': 'data/datapackages/invalid/datapackage.json'},
+], preset='datapackages')
+pprint(report)
diff --git a/examples/tables.py b/examples/tables.py
index fba2af5..26e7ba0 100644
--- a/examples/tables.py
+++ b/examples/tables.py
@@ -3,7 +3,7 @@ from goodtables import Inspector
 
 inspector = Inspector()
 report = inspector.inspect([
+    'data/invalid.csv',
     {'source': 'data/valid.csv', 'schema': {'fields': [{'name': 'id'}, {'name': 'name'}]}},
-    {'source': 'data/invalid.csv'},
 ], preset='tables')
 pprint(report)
diff --git a/features/datapackages.yml b/features/datapackages.yml
new file mode 100644
index 0000000..bea1769
--- /dev/null
+++ b/features/datapackages.yml
@@ -0,0 +1,8 @@
+datapackages:
+  source:
+    - data/datapackages/valid/datapackage.json
+    - source: data/datapackages/invalid/datapackage.json
+  preset: datapackages
+  report:
+    - [3, 3, null, 'blank-row']
+    - [4, 4, null, 'blank-row']
diff --git a/goodtables/inspector.py b/goodtables/inspector.py
index 6d8be7b..70e6028 100644
--- a/goodtables/inspector.py
+++ b/goodtables/inspector.py
@@ -67,7 +67,9 @@ class Inspector(object):
             preset (str): dataset extraction preset
                 supported presets:
                     - table
+                    - tables
                     - datapackage
+                    - datapackages
             options (dict): source options
 
         Returns:
@@ -93,7 +95,7 @@ class Inspector(object):
 
         # Collect reports
         reports = []
-        if not errors:
+        if tables:
             tasks = []
             pool = ThreadPool(processes=len(tables))
             for table in tables:
diff --git a/goodtables/presets/__init__.py b/goodtables/presets/__init__.py
index 91d2f3b..d5c24f4 100644
--- a/goodtables/presets/__init__.py
+++ b/goodtables/presets/__init__.py
@@ -5,5 +5,6 @@ from __future__ import absolute_import
 from __future__ import unicode_literals
 
 from .datapackage import datapackage
+from .datapackages import datapackages
 from .table import table
 from .tables import tables
diff --git a/goodtables/presets/datapackages.py b/goodtables/presets/datapackages.py
new file mode 100644
index 0000000..408a36a
--- /dev/null
+++ b/goodtables/presets/datapackages.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import unicode_literals
+
+import six
+from copy import deepcopy
+from .datapackage import datapackage as datapackage_preset
+from ..register import preset
+
+
+# Module API
+
+@preset('datapackages')
+def datapackages(items):
+    errors = []
+    tables = []
+
+    # Add errors, tables
+    items = deepcopy(items)
+    for item in items:
+        if isinstance(item, six.string_types):
+            item_errors, item_tables = datapackage_preset(item)
+        else:
+            source = item.pop('source')
+            item_errors, item_tables = datapackage_preset(source, **item)
+        errors.extend(item_errors)
+        tables.extend(item_tables)
+
+    return errors, tables
diff --git a/goodtables/presets/tables.py b/goodtables/presets/tables.py
index 581c538..6ef002b 100644
--- a/goodtables/presets/tables.py
+++ b/goodtables/presets/tables.py
@@ -4,6 +4,8 @@ from __future__ import print_function
 from __future__ import absolute_import
 from __future__ import unicode_literals
 
+import six
+from copy import deepcopy
 from .table import table as table_preset
 from ..register import preset
 
@@ -16,9 +18,13 @@ def tables(items):
     tables = []
 
     # Add errors, tables
+    items = deepcopy(items)
     for item in items:
-        source = item.pop('source')
-        item_errors, item_tables = table_preset(source, **item)
+        if isinstance(item, six.string_types):
+            item_errors, item_tables = table_preset(item)
+        else:
+            source = item.pop('source')
+            item_errors, item_tables = table_preset(source, **item)
         errors.extend(item_errors)
         tables.extend(item_tables)
 


Test patch:
diff --git a/tests/presets/test_datapackages.py b/tests/presets/test_datapackages.py
new file mode 100644
index 0000000..6ca1ce7
--- /dev/null
+++ b/tests/presets/test_datapackages.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import unicode_literals
+
+from goodtables import presets
+
+
+# Test
+
+def test_datapackages():
+    errors, tables = presets.datapackages([
+        'data/datapackages/valid/datapackage.json',
+        {'source': 'data/datapackages/invalid/datapackage.json'},
+    ])
+    assert len(errors) == 0
+    assert len(tables) == 4
diff --git a/tests/presets/test_tables.py b/tests/presets/test_tables.py
new file mode 100644
index 0000000..4aedfcc
--- /dev/null
+++ b/tests/presets/test_tables.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import unicode_literals
+
+from goodtables import presets
+
+
+# Test
+
+def test_tables():
+    errors, tables = presets.tables([
+        'data/valid.csv',
+        {'source': 'data/invalid.csv'},
+    ])
+    assert len(errors) == 0
+    assert len(tables) == 2