Repository: facelessuser/soupsieve

Issue:
Compiled object cannot be pickled if contains a NullSelector object
We forgot to register `NullSelector` to be pickled. So if a compiled selector object contains a `NullSelector`, it will not pickle.

Discussion:

Patch:
diff --git a/.pyspelling.yml b/.pyspelling.yml
index 07224cf..4cf66ec 100644
--- a/.pyspelling.yml
+++ b/.pyspelling.yml
@@ -19,9 +19,7 @@ matrix:
       - title
       - alt
       ignores:
-      - ':is(code, pre)'
-      - 'a:is(.magiclink-compare, .magiclink-commit, .magiclink-repository)'
-      - 'span.keys'
+      - ':is(code, pre, a.magiclink, span.keys)'
       - ':is(.MathJax_Preview, .md-nav__link, .md-footer-custom-text, .md-source__repository, .headerlink, .md-icon)'
   - pyspelling.filters.url:
 
diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index 2106380..7a2beac 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -4,6 +4,10 @@
 
 - **NEW**: Add support for `:in-range` and `:out-of-range` selectors.
 
+## 1.6.3
+
+- **FIX**: Fix pickling issue when compiled selector contains a `NullSelector` object. (#70)
+
 ## 1.6.2
 
 - **FIX**: Fix pattern compile issues on Python < 2.7.4.
diff --git a/soupsieve/css_types.py b/soupsieve/css_types.py
index 7bb07b5..3f2c997 100644
--- a/soupsieve/css_types.py
+++ b/soupsieve/css_types.py
@@ -2,7 +2,16 @@
 from __future__ import unicode_literals
 from . import util
 
-__all__ = ('Selector', 'SelectorTag', 'SelectorAttribute', 'SelectorNth', 'SelectorList', 'Namespaces')
+__all__ = (
+    'Selector',
+    'NullSelector',
+    'SelectorTag',
+    'SelectorAttribute',
+    'SelectorNth',
+    'SelectorLang',
+    'SelectorList',
+    'Namespaces'
+)
 
 
 SEL_EMPTY = 0x1
@@ -291,8 +300,9 @@ def pickle_register(obj):
 
 
 pickle_register(Selector)
+pickle_register(NullSelector)
 pickle_register(SelectorTag)
 pickle_register(SelectorAttribute)
 pickle_register(SelectorNth)
-pickle_register(SelectorList)
 pickle_register(SelectorLang)
+pickle_register(SelectorList)


Test patch:
diff --git a/tests/test_soupsieve.py b/tests/test_soupsieve.py
index af94fef..a4943fb 100644
--- a/tests/test_soupsieve.py
+++ b/tests/test_soupsieve.py
@@ -184,17 +184,26 @@ class TestSoupSieve(unittest.TestCase):
         """Test copy and pickle."""
 
         # Test that we can pickle and unpickle
-        p1 = sv.compile('p[id]')
+        # We force a pattern that contains all custom types:
+        # `Selector`, `NullSelector`, `SelectorTag`, `SelectorAttribute`,
+        # `SelectorNth`, `SelectorLang`, `SelectorList`, and `Namespaces`
+        p1 = sv.compile(
+            'p.class#id[id]:nth-child(2):lang(en):focus', {'html': 'http://www.w3.org/TR/html4/'}
+        )
         sp1 = pickle.dumps(p1)
         pp1 = pickle.loads(sp1)
         self.assertTrue(pp1 == p1)
 
         # Test that we pull the same one from cache
-        p2 = sv.compile('p[id]')
+        p2 = sv.compile(
+            'p.class#id[id]:nth-child(2):lang(en):focus', {'html': 'http://www.w3.org/TR/html4/'}
+        )
         self.assertTrue(p1 is p2)
 
         # Test that we compile a new one when providing a different flags
-        p3 = sv.compile('p[id]', flags=0x10)
+        p3 = sv.compile(
+            'p.class#id[id]:nth-child(2):lang(en):focus', {'html': 'http://www.w3.org/TR/html4/'}, flags=0x10
+        )
         self.assertTrue(p1 is not p3)
         self.assertTrue(p1 != p3)