diff --git a/PKG-INFO b/PKG-INFO
index ee50d594037bae70cb7aa580678385bba6d6bb3b..4ebf75eb543b6701682666b555d50f6c7fb7b97a 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: swh.model
-Version: 0.0.67
+Version: 0.0.68
 Summary: Software Heritage data model
 Home-page: https://forge.softwareheritage.org/diffusion/DMOD/
 Author: Software Heritage developers
@@ -34,6 +34,7 @@ Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
 Classifier: Operating System :: OS Independent
 Classifier: Development Status :: 5 - Production/Stable
+Requires-Python: >=3.7
 Description-Content-Type: text/markdown
 Provides-Extra: cli
 Provides-Extra: testing
diff --git a/setup.py b/setup.py
index f0ea60468c4f15816640b2d17491d5108d044d54..4955e1ddda62b4777554c38b74b4e5ab23bc3767 100755
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python3
-# Copyright (C) 2015-2018  The Software Heritage developers
+# Copyright (C) 2015-2020  The Software Heritage developers
 # See the AUTHORS file at the top-level directory of this distribution
 # License: GNU General Public License version 3, or any later version
 # See top-level LICENSE file for more information
@@ -42,6 +42,7 @@ setup(
     description="Software Heritage data model",
     long_description=long_description,
     long_description_content_type="text/markdown",
+    python_requires=">=3.7",
     author="Software Heritage developers",
     author_email="swh-devel@inria.fr",
     url="https://forge.softwareheritage.org/diffusion/DMOD/",
diff --git a/swh.model.egg-info/PKG-INFO b/swh.model.egg-info/PKG-INFO
index ee50d594037bae70cb7aa580678385bba6d6bb3b..4ebf75eb543b6701682666b555d50f6c7fb7b97a 100644
--- a/swh.model.egg-info/PKG-INFO
+++ b/swh.model.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: swh.model
-Version: 0.0.67
+Version: 0.0.68
 Summary: Software Heritage data model
 Home-page: https://forge.softwareheritage.org/diffusion/DMOD/
 Author: Software Heritage developers
@@ -34,6 +34,7 @@ Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
 Classifier: Operating System :: OS Independent
 Classifier: Development Status :: 5 - Production/Stable
+Requires-Python: >=3.7
 Description-Content-Type: text/markdown
 Provides-Extra: cli
 Provides-Extra: testing
diff --git a/swh/model/hypothesis_strategies.py b/swh/model/hypothesis_strategies.py
index f5dbe26efa5715c51eda342c1a39de1087a1a182..1940fa4432d9286fb3213857b2c18829f1e3c26b 100644
--- a/swh/model/hypothesis_strategies.py
+++ b/swh/model/hypothesis_strategies.py
@@ -380,30 +380,66 @@ def snapshots(*, min_size=0, max_size=100, only_objects=False):
     ).map(Snapshot.from_dict)
 
 
-def objects():
-    return one_of(
-        origins().map(lambda x: ("origin", x)),
-        origin_visits().map(lambda x: ("origin_visit", x)),
-        origin_visit_statuses().map(lambda x: ("origin_visit_update", x)),
-        snapshots().map(lambda x: ("snapshot", x)),
-        releases().map(lambda x: ("release", x)),
-        revisions().map(lambda x: ("revision", x)),
-        directories().map(lambda x: ("directory", x)),
-        contents().map(lambda x: ("content", x)),
-    )
+def objects(blacklist_types=("origin_visit_status",), split_content=False):
+    """generates a random couple (type, obj)
+
+    which obj is an instance of the Model class corresponding to obj_type.
+
+    `blacklist_types` is a list of obj_type to exclude from the strategy.
+
+    If `split_content` is True, generates Content and SkippedContent under different
+    obj_type, resp. "content" and "skipped_content".
+    """
+    strategies = [
+        ("origin", origins),
+        ("origin_visit", origin_visits),
+        ("origin_visit_status", origin_visit_statuses),
+        ("snapshot", snapshots),
+        ("release", releases),
+        ("revision", revisions),
+        ("directory", directories),
+    ]
+    if split_content:
+        strategies.append(("content", present_contents))
+        strategies.append(("skipped_content", skipped_contents))
+    else:
+        strategies.append(("content", contents))
+    args = [
+        obj_gen().map(lambda x, obj_type=obj_type: (obj_type, x))
+        for (obj_type, obj_gen) in strategies
+        if obj_type not in blacklist_types
+    ]
+    return one_of(*args)
 
 
-def object_dicts():
+def object_dicts(blacklist_types=("origin_visit_status",), split_content=False):
     """generates a random couple (type, dict)
 
     which dict is suitable for <ModelForType>.from_dict() factory methods.
+
+    `blacklist_types` is a list of obj_type to exclude from the strategy.
+
+    If `split_content` is True, generates Content and SkippedContent under different
+    obj_type, resp. "content" and "skipped_content".
+
     """
-    return one_of(
-        origins_d().map(lambda x: ("origin", x)),
-        origin_visits_d().map(lambda x: ("origin_visit", x)),
-        snapshots_d().map(lambda x: ("snapshot", x)),
-        releases_d().map(lambda x: ("release", x)),
-        revisions_d().map(lambda x: ("revision", x)),
-        directories_d().map(lambda x: ("directory", x)),
-        contents_d().map(lambda x: ("content", x)),
-    )
+    strategies = [
+        ("origin", origins_d),
+        ("origin_visit", origin_visits_d),
+        ("origin_visit_status", origin_visit_statuses_d),
+        ("snapshot", snapshots_d),
+        ("release", releases_d),
+        ("revision", revisions_d),
+        ("directory", directories_d),
+    ]
+    if split_content:
+        strategies.append(("content", present_contents_d))
+        strategies.append(("skipped_content", skipped_contents_d))
+    else:
+        strategies.append(("content", contents_d))
+    args = [
+        obj_gen().map(lambda x, obj_type=obj_type: (obj_type, x))
+        for (obj_type, obj_gen) in strategies
+        if obj_type not in blacklist_types
+    ]
+    return one_of(*args)
diff --git a/swh/model/tests/test_hypothesis_strategies.py b/swh/model/tests/test_hypothesis_strategies.py
index b790f9a37f44568f5e55dfba46126a413c41c67d..d3ac5ef42053e7e5c4dcc2760ec6e1147ae12962 100644
--- a/swh/model/tests/test_hypothesis_strategies.py
+++ b/swh/model/tests/test_hypothesis_strategies.py
@@ -14,14 +14,41 @@ from swh.model.model import TargetType
 
 
 target_types = ("content", "directory", "revision", "release", "snapshot", "alias")
-
-
-@given(objects())
+all_but_skipped_content = (
+    "origin",
+    "origin_visit",
+    "origin_visit_status",
+    "snapshot",
+    "release",
+    "revision",
+    "directory",
+    "content",
+)
+
+
+@given(objects(blacklist_types=()))
 def test_generation(obj_type_and_obj):
     (obj_type, object_) = obj_type_and_obj
     attr.validate(object_)
 
 
+@given(objects(split_content=False))
+def test_generation_merged_content(obj_type_and_obj):
+    # we should never generate a "skipped_content" here
+    assert obj_type_and_obj[0] != "skipped_content"
+
+
+@given(objects(split_content=True, blacklist_types=all_but_skipped_content))
+def test_generation_split_content(obj_type_and_obj):
+    # we should only generate "skipped_content"
+    assert obj_type_and_obj[0] == "skipped_content"
+
+
+@given(objects(blacklist_types=("origin_visit", "directory")))
+def test_generation_blacklist(obj_type_and_obj):
+    assert obj_type_and_obj[0] not in ("origin_visit", "directory")
+
+
 def assert_nested_dict(obj):
     """Tests the object is a nested dict and contains no more class
     from swh.model.model."""
@@ -38,7 +65,7 @@ def assert_nested_dict(obj):
         assert False, obj
 
 
-@given(object_dicts())
+@given(object_dicts(blacklist_types=()))
 def test_dicts_generation(obj_type_and_obj):
     (obj_type, object_) = obj_type_and_obj
     assert_nested_dict(object_)
@@ -59,6 +86,23 @@ def test_dicts_generation(obj_type_and_obj):
             assert branch is None or branch["target_type"] in target_types
 
 
+@given(object_dicts(split_content=False))
+def test_dicts_generation_merged_content(obj_type_and_obj):
+    # we should never generate a "skipped_content" here
+    assert obj_type_and_obj[0] != "skipped_content"
+
+
+@given(object_dicts(split_content=True, blacklist_types=all_but_skipped_content))
+def test_dicts_generation_split_content(obj_type_and_obj):
+    # we should only generate "skipped_content"
+    assert obj_type_and_obj[0] == "skipped_content"
+
+
+@given(object_dicts(blacklist_types=("release", "content")))
+def test_dicts_generation_blacklist(obj_type_and_obj):
+    assert obj_type_and_obj[0] not in ("release", "content")
+
+
 @given(objects())
 def test_model_to_dicts(obj_type_and_obj):
     (obj_type, object_) = obj_type_and_obj
diff --git a/version.txt b/version.txt
index 8ac5b0a6fb155c6bc6030ec75bcb80041d11ae2c..6e573540240e09d4868751ab4d15c75b4032f198 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-v0.0.67-0-gd52549f
\ No newline at end of file
+v0.0.68-0-g1037e88
\ No newline at end of file