Hello community,

here is the log from the commit of package python-pyrsistent for 
openSUSE:Factory checked in at 2018-08-12 20:55:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyrsistent (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyrsistent.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyrsistent"

Sun Aug 12 20:55:48 2018 rev:2 rq:628726 version:0.14.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyrsistent/python-pyrsistent.changes      
2017-09-11 16:18:30.392803896 +0200
+++ /work/SRC/openSUSE:Factory/.python-pyrsistent.new/python-pyrsistent.changes 
2018-08-12 20:55:52.429528308 +0200
@@ -1,0 +2,17 @@
+Sat Aug 11 06:34:31 UTC 2018 - tchva...@suse.com
+
+- Drop the test conditional
+- Use %license macro
+
+-------------------------------------------------------------------
+Fri Aug 10 23:33:25 UTC 2018 - jsi...@suse.de
+
+- Version jump to 0.14.4
+  * Fix PClass double-factory-ing in a few situations.
+  * Fix #121, regression in PClass.set() 
+  * Fix regression where type names break sequence fields
+  * Allowing 'set' as a valid container for multiple fields.
+  * Fix #131 Clarify that dot-notation can be used for element access on PMaps
+  * Fix #133 Python 3.7 compatibility
+
+-------------------------------------------------------------------

Old:
----
  pyrsistent-0.13.0.tar.gz

New:
----
  pyrsistent-0.14.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pyrsistent.spec ++++++
--- /var/tmp/diff_new_pack.CPMraf/_old  2018-08-12 20:55:52.929529324 +0200
+++ /var/tmp/diff_new_pack.CPMraf/_new  2018-08-12 20:55:52.929529324 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pyrsistent
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -13,29 +13,26 @@
 # published by the Open Source Initiative.
 
 # Please submit bugfixes or comments via http://bugs.opensuse.org/
+#
 
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
-%bcond_without  test
 Name:           python-pyrsistent
-Version:        0.13.0
+Version:        0.14.4
 Release:        0
-License:        MIT
 Summary:        Persistent, Functional, Immutable data structures
-Url:            http://github.com/tobgu/pyrsistent/
+License:        MIT
 Group:          Development/Languages/Python
+URL:            http://github.com/tobgu/pyrsistent/
 Source:         
https://files.pythonhosted.org/packages/source/p/pyrsistent/pyrsistent-%{version}.tar.gz
-BuildRequires:  fdupes
-BuildRequires:  python-rpm-macros
 BuildRequires:  %{python_module devel}
-BuildRequires:  %{python_module setuptools}
-%if %{with test}
 BuildRequires:  %{python_module hypothesis}
 BuildRequires:  %{python_module pytest}
+BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module six}
-%endif
+BuildRequires:  fdupes
+BuildRequires:  python-rpm-macros
 Requires:       python-six
-
 %python_subpackages
 
 %description
@@ -59,16 +56,14 @@
 %python_install
 %python_expand %fdupes %{buildroot}%{$python_sitearch}
 
-%if %{with test}
 %check
 %{python_expand export PYTHONPATH=%{buildroot}%{$python_sitearch}
 py.test-%{$python_bin_suffix}
 }
-%endif
 
 %files %{python_files}
-%defattr(-,root,root,-)
-%doc CHANGES.txt LICENCE.mit README README.rst
+%license LICENCE.mit
+%doc CHANGES.txt README README.rst
 %{python_sitearch}/*
 
 %changelog

++++++ pyrsistent-0.13.0.tar.gz -> pyrsistent-0.14.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/CHANGES.txt 
new/pyrsistent-0.14.4/CHANGES.txt
--- old/pyrsistent-0.13.0/CHANGES.txt   2017-09-01 11:51:36.000000000 +0200
+++ new/pyrsistent-0.14.4/CHANGES.txt   2018-07-08 11:51:59.000000000 +0200
@@ -1,5 +1,28 @@
 Revision history
 ----------------
+v0.14.4, 2018-07-08
+ * Fix #133, minor Python 3.7 compatibility issue. Pyrsistent is now 
officially Python 3.7 compliant!
+
+v0.14.3, 2018-06-11
+ * Fix #123 regression where type names break sequence fields. Thanks @doozr 
for this!
+ * Fix #124 using the class name to make AttributeError on __getattr__ more 
informative for PRecords.
+   Thanks @neilvyas for this!
+ * Fix #125 how fields handle type arguments. Thanks @neilvyas for this!
+
+v0.14.2, 2017-12-06
+ * Fix #121, regression in PClass.set() introduced in 0.14.1.
+
+v0.14.1, 2017-11-27
+ * Equality check performance improvements for pvectors and pmaps. Thanks 
@dtomas for this!
+ * Avoid calling factories multiple times for fields that do not change, see 
PR #120 for for
+   details. Thanks @teepark for this!
+
+v0.14.0, 2017-10-08
+ * Fix #117, pmap now accepts iterators as input to constructor. Thanks 
@Julian for this!
+ * Drop support for Python 2.6. Nothing has been done in this release that 
will explicitly
+   break pyrsistent for 2.6 but it will not be considered moving forward.  
Dropping 2.6
+   support is the reason for stepping the second decimal instead of the third.
+
 v0.13.0, 2017-09-01
  * Fix #113, Skip field factories when loading pickled objects. There is a
    minor backwards incompatibilty in the behaviour because of this. Thanks
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/LICENCE.mit 
new/pyrsistent-0.14.4/LICENCE.mit
--- old/pyrsistent-0.13.0/LICENCE.mit   2017-01-06 18:46:49.000000000 +0100
+++ new/pyrsistent-0.14.4/LICENCE.mit   2018-07-07 15:53:48.000000000 +0200
@@ -1,4 +1,4 @@
-Copyright (c) 2017 Tobias Gustafsson
+Copyright (c) 2018 Tobias Gustafsson
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/PKG-INFO 
new/pyrsistent-0.14.4/PKG-INFO
--- old/pyrsistent-0.13.0/PKG-INFO      2017-09-01 13:11:16.000000000 +0200
+++ new/pyrsistent-0.14.4/PKG-INFO      2018-07-08 11:57:12.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pyrsistent
-Version: 0.13.0
+Version: 0.14.4
 Summary: Persistent/Functional/Immutable data structures
 Home-page: http://github.com/tobgu/pyrsistent/
 Author: Tobias Gustafsson
@@ -570,8 +570,8 @@
         Compatibility
         -------------
         
-        Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5 and 
PyPy (Python 2.7 compatible). It will most likely work
-        on all other versions >= 3.4 but no guarantees are given. :)
+        Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5, 3.6 
and PyPy (Python 2 and 3 compatible). It will most
+        likely work on all other versions >= 3.4 but no guarantees are given. 
:)
         
         Compatibility issues
         ~~~~~~~~~~~~~~~~~~~~
@@ -643,18 +643,50 @@
         
         Julian Berman https://github.com/Julian
         
+        Dennis Tomas https://github.com/dtomas
+        
+        Neil Vyas https://github.com/neilvyas
+        
+        doozr https://github.com/doozr
+        
         Contributing
         ------------
         
-        If you experience problems please log them on GitHub. If you want to 
contribute code, please fork the code and submit a pull request.
+        Want to contribute? That's great! If you experience problems please 
log them on GitHub. If you want to contribute code,
+        please fork the repository and submit a pull request.
+        
+        Run tests
+        ~~~~~~~~~
+        .. _tox: https://tox.readthedocs.io/en/latest/
+        
+        Tests can be executed using tox_.
+        
+        Install tox: ``pip install tox``
+        
+        Run test for Python 2.7: ``tox -epy27``
+        
+        Project status
+        --------------
+        Pyrsistent can be considered stable and mature (who knows, there may 
even be a 1.0 some day :-)). The project is
+        maintained, bugs fixed, PRs reviewed and merged and new releases made. 
I currently do not have time for development
+        of new features or functionality which I don't have use for myself. 
I'm more than happy to take PRs for new
+        functionality though!
+        
+        There are a bunch of issues marked with ``enhancement`` and ``help 
wanted`` that contain requests for new functionality
+        that would be nice to include. The level of difficulty and extend of 
the issues varies, please reach out to me if you're
+        interested in working on any of them.
+        
+        If you feel that you have a grand master plan for where you would like 
Pyrsistent to go and have the time to put into
+        it please don't hesitate to discuss this with me and submit PRs for 
it. If all goes well I'd be more than happy to add
+        additional maintainers to the project!
         
 Platform: UNKNOWN
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: PyPy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/README new/pyrsistent-0.14.4/README
--- old/pyrsistent-0.13.0/README        2017-09-01 11:53:08.000000000 +0200
+++ new/pyrsistent-0.14.4/README        2018-07-07 15:53:48.000000000 +0200
@@ -562,8 +562,8 @@
 Compatibility
 -------------
 
-Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5 and PyPy 
(Python 2.7 compatible). It will most likely work
-on all other versions >= 3.4 but no guarantees are given. :)
+Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5, 3.6 and PyPy 
(Python 2 and 3 compatible). It will most
+likely work on all other versions >= 3.4 but no guarantees are given. :)
 
 Compatibility issues
 ~~~~~~~~~~~~~~~~~~~~
@@ -635,7 +635,39 @@
 
 Julian Berman https://github.com/Julian
 
+Dennis Tomas https://github.com/dtomas
+
+Neil Vyas https://github.com/neilvyas
+
+doozr https://github.com/doozr
+
 Contributing
 ------------
 
-If you experience problems please log them on GitHub. If you want to 
contribute code, please fork the code and submit a pull request.
+Want to contribute? That's great! If you experience problems please log them 
on GitHub. If you want to contribute code,
+please fork the repository and submit a pull request.
+
+Run tests
+~~~~~~~~~
+.. _tox: https://tox.readthedocs.io/en/latest/
+
+Tests can be executed using tox_.
+
+Install tox: ``pip install tox``
+
+Run test for Python 2.7: ``tox -epy27``
+
+Project status
+--------------
+Pyrsistent can be considered stable and mature (who knows, there may even be a 
1.0 some day :-)). The project is
+maintained, bugs fixed, PRs reviewed and merged and new releases made. I 
currently do not have time for development
+of new features or functionality which I don't have use for myself. I'm more 
than happy to take PRs for new
+functionality though!
+
+There are a bunch of issues marked with ``enhancement`` and ``help wanted`` 
that contain requests for new functionality
+that would be nice to include. The level of difficulty and extend of the 
issues varies, please reach out to me if you're
+interested in working on any of them.
+
+If you feel that you have a grand master plan for where you would like 
Pyrsistent to go and have the time to put into
+it please don't hesitate to discuss this with me and submit PRs for it. If all 
goes well I'd be more than happy to add
+additional maintainers to the project!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/README.rst 
new/pyrsistent-0.14.4/README.rst
--- old/pyrsistent-0.13.0/README.rst    2017-09-01 11:53:08.000000000 +0200
+++ new/pyrsistent-0.14.4/README.rst    2018-07-07 15:53:48.000000000 +0200
@@ -562,8 +562,8 @@
 Compatibility
 -------------
 
-Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5 and PyPy 
(Python 2.7 compatible). It will most likely work
-on all other versions >= 3.4 but no guarantees are given. :)
+Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5, 3.6 and PyPy 
(Python 2 and 3 compatible). It will most
+likely work on all other versions >= 3.4 but no guarantees are given. :)
 
 Compatibility issues
 ~~~~~~~~~~~~~~~~~~~~
@@ -635,7 +635,39 @@
 
 Julian Berman https://github.com/Julian
 
+Dennis Tomas https://github.com/dtomas
+
+Neil Vyas https://github.com/neilvyas
+
+doozr https://github.com/doozr
+
 Contributing
 ------------
 
-If you experience problems please log them on GitHub. If you want to 
contribute code, please fork the code and submit a pull request.
+Want to contribute? That's great! If you experience problems please log them 
on GitHub. If you want to contribute code,
+please fork the repository and submit a pull request.
+
+Run tests
+~~~~~~~~~
+.. _tox: https://tox.readthedocs.io/en/latest/
+
+Tests can be executed using tox_.
+
+Install tox: ``pip install tox``
+
+Run test for Python 2.7: ``tox -epy27``
+
+Project status
+--------------
+Pyrsistent can be considered stable and mature (who knows, there may even be a 
1.0 some day :-)). The project is
+maintained, bugs fixed, PRs reviewed and merged and new releases made. I 
currently do not have time for development
+of new features or functionality which I don't have use for myself. I'm more 
than happy to take PRs for new
+functionality though!
+
+There are a bunch of issues marked with ``enhancement`` and ``help wanted`` 
that contain requests for new functionality
+that would be nice to include. The level of difficulty and extend of the 
issues varies, please reach out to me if you're
+interested in working on any of them.
+
+If you feel that you have a grand master plan for where you would like 
Pyrsistent to go and have the time to put into
+it please don't hesitate to discuss this with me and submit PRs for it. If all 
goes well I'd be more than happy to add
+additional maintainers to the project!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/_pyrsistent_version.py 
new/pyrsistent-0.14.4/_pyrsistent_version.py
--- old/pyrsistent-0.13.0/_pyrsistent_version.py        2017-09-01 
11:51:54.000000000 +0200
+++ new/pyrsistent-0.14.4/_pyrsistent_version.py        2018-07-08 
11:51:36.000000000 +0200
@@ -1 +1 @@
-__version__ = '0.13.0'
+__version__ = '0.14.4'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pvectorcmodule.c 
new/pyrsistent-0.14.4/pvectorcmodule.c
--- old/pyrsistent-0.13.0/pvectorcmodule.c      2016-04-03 08:41:08.000000000 
+0200
+++ new/pyrsistent-0.14.4/pvectorcmodule.c      2018-07-07 15:53:48.000000000 
+0200
@@ -365,6 +365,16 @@
     vlen = vt->count;
     wlen = wt->count;
 
+    if (vlen != wlen) {
+        if (op == Py_EQ) {
+            Py_INCREF(Py_False);
+            return Py_False;
+        } else if (op == Py_NE) {
+            Py_INCREF(Py_True);
+            return Py_True;
+        }
+    }
+
     /* Search for the first index where items are different. */
     PyObject *left = NULL;
     PyObject *right = NULL;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_checked_types.py 
new/pyrsistent-0.14.4/pyrsistent/_checked_types.py
--- old/pyrsistent-0.13.0/pyrsistent/_checked_types.py  2017-09-01 
11:44:01.000000000 +0200
+++ new/pyrsistent-0.14.4/pyrsistent/_checked_types.py  2018-07-07 
15:53:48.000000000 +0200
@@ -1,5 +1,7 @@
 from collections import Iterable
 import six
+
+from pyrsistent._compat import Enum, string_types
 from pyrsistent._pmap import PMap, pmap
 from pyrsistent._pset import PSet, pset
 from pyrsistent._pvector import PythonPVector, python_pvector
@@ -12,7 +14,7 @@
     __slots__ = ()
 
     @classmethod
-    def create(cls, source_data, _bypass_factories=False):
+    def create(cls, source_data, _factory_fields=None):
         raise NotImplementedError()
 
     def serialize(self, format=None):
@@ -20,7 +22,7 @@
 
 
 def _restore_pickle(cls, data):
-    return cls.create(data, _bypass_factories=True)
+    return cls.create(data, _factory_fields=set())
 
 
 class InvariantException(Exception):
@@ -45,17 +47,61 @@
             missing_fields=', '.join(self.missing_fields))
 
 
+_preserved_iterable_types = (
+        Enum,
+)
+"""Some types are themselves iterable, but we want to use the type itself and
+not its members for the type specification. This defines a set of such types
+that we explicitly preserve.
+
+Note that strings are not such types because the string inputs we pass in are
+values, not types.
+"""
+
+
+def maybe_parse_user_type(t):
+    """Try to coerce a user-supplied type directive into a list of types.
+
+    This function should be used in all places where a user specifies a type,
+    for consistency.
+
+    The policy for what defines valid user input should be clear from the 
implementation.
+    """
+    is_type = isinstance(t, type)
+    is_preserved = isinstance(t, type) and issubclass(t, 
_preserved_iterable_types)
+    is_string = isinstance(t, string_types)
+    is_iterable = isinstance(t, Iterable)
+
+    if is_preserved:
+        return [t]
+    elif is_string:
+        return [t]
+    elif is_type and not is_iterable:
+        return [t]
+    elif is_iterable:
+        # Recur to validate contained types as well.
+        ts = t
+        return tuple(e for t in ts for e in maybe_parse_user_type(t))
+    else:
+        # If this raises because `t` cannot be formatted, so be it.
+        raise TypeError(
+            'Type specifications must be types or strings. Input: {}'.format(t)
+        )
+
+
+def maybe_parse_many_user_types(ts):
+    # Just a different name to communicate that you're parsing multiple user
+    # inputs. `maybe_parse_user_type` handles the iterable case anyway.
+    return maybe_parse_user_type(ts)
+
+
 def _store_types(dct, bases, destination_name, source_name):
-    def to_list(elem):
-        if not isinstance(elem, Iterable) or isinstance(elem, 
six.string_types):
-            return [elem]
-        return list(elem)
-
-    dct[destination_name] = to_list(dct[source_name]) if source_name in dct 
else []
-    dct[destination_name] += sum([to_list(b.__dict__[source_name]) for b in 
bases if source_name in b.__dict__], [])
-    dct[destination_name] = tuple(dct[destination_name])
-    if not all(isinstance(t, type) or isinstance(t, six.string_types) for t in 
dct[destination_name]):
-        raise TypeError('Type specifications must be types or strings')
+    maybe_types = maybe_parse_many_user_types([
+        d[source_name]
+        for d in ([dct] + [b.__dict__ for b in bases]) if source_name in d
+    ])
+
+    dct[destination_name] = maybe_types
 
 
 def _merge_invariant_results(result):
@@ -207,20 +253,20 @@
     return tuple(typs) + (type(None),)
 
 
-def _checked_type_create(cls, source_data, _bypass_factories=False):
-        if isinstance(source_data, cls):
-            return source_data
-
-        # Recursively apply create methods of checked types if the types of 
the supplied data
-        # does not match any of the valid types.
-        types = get_types(cls._checked_types)
-        checked_type = next((t for t in types if issubclass(t, CheckedType)), 
None)
-        if checked_type:
-            return cls([checked_type.create(data)
-                        if not any(isinstance(data, t) for t in types) else 
data
-                        for data in source_data])
+def _checked_type_create(cls, source_data, _factory_fields=None):
+    if isinstance(source_data, cls):
+        return source_data
+
+    # Recursively apply create methods of checked types if the types of the 
supplied data
+    # does not match any of the valid types.
+    types = get_types(cls._checked_types)
+    checked_type = next((t for t in types if issubclass(t, CheckedType)), None)
+    if checked_type:
+        return cls([checked_type.create(data)
+                    if not any(isinstance(data, t) for t in types) else data
+                    for data in source_data])
 
-        return cls(source_data)
+    return cls(source_data)
 
 @six.add_metaclass(_CheckedTypeMeta)
 class CheckedPVector(PythonPVector, CheckedType):
@@ -447,7 +493,7 @@
         return dict(serializer(format, k, v) for k, v in self.items())
 
     @classmethod
-    def create(cls, source_data, _bypass_factories=False):
+    def create(cls, source_data, _factory_fields=None):
         if isinstance(source_data, cls):
             return source_data
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_compat.py 
new/pyrsistent-0.14.4/pyrsistent/_compat.py
--- old/pyrsistent-0.13.0/pyrsistent/_compat.py 1970-01-01 01:00:00.000000000 
+0100
+++ new/pyrsistent-0.14.4/pyrsistent/_compat.py 2018-07-07 15:53:48.000000000 
+0200
@@ -0,0 +1,9 @@
+from six import string_types
+
+
+# enum compat
+try:
+    from enum import Enum
+except:
+    class Enum(object): pass
+    # no objects will be instances of this class
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_field_common.py 
new/pyrsistent-0.14.4/pyrsistent/_field_common.py
--- old/pyrsistent-0.13.0/pyrsistent/_field_common.py   2017-06-04 
10:28:26.000000000 +0200
+++ new/pyrsistent-0.14.4/pyrsistent/_field_common.py   2018-07-07 
15:53:48.000000000 +0200
@@ -1,23 +1,20 @@
 from collections import Iterable
 import six
+
 from pyrsistent._checked_types import (
-    CheckedType, CheckedPSet, CheckedPMap, CheckedPVector,
-    optional as optional_type, InvariantException, get_type, wrap_invariant,
-    _restore_pickle)
-
-
-try:
-    from enum import Enum as _Enum
-except:
-    class _Enum(object): pass
-    # no objects will be instances of this class
-
-
-def isenum(type_):
-    try:
-        return issubclass(type_, _Enum)
-    except TypeError:
-        return False  # type_ is not a class
+    CheckedPMap,
+    CheckedPSet,
+    CheckedPVector,
+    CheckedType,
+    InvariantException,
+    _restore_pickle,
+    get_type,
+    maybe_parse_user_type,
+    maybe_parse_many_user_types,
+)
+from pyrsistent._checked_types import optional as optional_type
+from pyrsistent._checked_types import wrap_invariant
+from pyrsistent._compat import Enum
 
 
 def set_fields(dct, bases, name):
@@ -91,11 +88,19 @@
     :param serializer: function that returns a serialized version of the field
     """
 
-    if isinstance(type, Iterable) and not isinstance(type, six.string_types) 
and not isenum(type):
-        # Enums and strings are iterable types
-        types = set(type)
+    # NB: We have to check this predicate separately from the predicates in
+    # `maybe_parse_user_type` et al. because this one is related to supporting
+    # the argspec for `field`, while those are related to supporting the valid
+    # ways to specify types.
+
+    # Multiple types must be passed in one of the following containers. Note
+    # that a type that is a subclass of one of these containers, like a
+    # `collections.namedtuple`, will work as expected, since we check
+    # `isinstance` and not `issubclass`.
+    if isinstance(type, (list, set, tuple)):
+        types = set(maybe_parse_many_user_types(type))
     else:
-        types = set([type])
+        types = set(maybe_parse_user_type(type))
 
     invariant_function = wrap_invariant(invariant) if invariant != 
PFIELD_NO_INVARIANT and callable(invariant) else invariant
     field = _PField(type=types, invariant=invariant_function, initial=initial,
@@ -159,7 +164,7 @@
 
 def _types_to_names(types):
     """Convert a tuple of types to a human-readable string."""
-    return "".join(typ.__name__.capitalize() for typ in types)
+    return "".join(get_type(typ).__name__.capitalize() for typ in types)
 
 def _make_seq_field_type(checked_class, item_type):
     """Create a subclass of the given checked class with the given item 
type."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_immutable.py 
new/pyrsistent-0.14.4/pyrsistent/_immutable.py
--- old/pyrsistent-0.13.0/pyrsistent/_immutable.py      2015-09-28 
20:48:39.000000000 +0200
+++ new/pyrsistent-0.14.4/pyrsistent/_immutable.py      2018-07-08 
09:16:39.000000000 +0200
@@ -1,3 +1,5 @@
+import sys
+
 import six
 
 
@@ -60,9 +62,14 @@
 
         return ''
 
+    verbose_string = ""
+    if sys.version_info < (3, 7):
+        # Verbose is no longer supported in Python 3.7
+        verbose_string = ", verbose={verbose}".format(verbose=verbose)
+
     quoted_members = ', '.join("'%s'" % m for m in members)
     template = """
-class {class_name}(namedtuple('ImmutableBase', [{quoted_members}], 
verbose={verbose})):
+class {class_name}(namedtuple('ImmutableBase', 
[{quoted_members}]{verbose_string})):
     __slots__ = tuple()
 
     def __repr__(self):
@@ -82,7 +89,7 @@
 """.format(quoted_members=quoted_members,
                member_set="set([%s])" % quoted_members if quoted_members else 
'set()',
                frozen_member_test=frozen_member_test(),
-               verbose=verbose,
+               verbose_string=verbose_string,
                class_name=name)
 
     if verbose:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_pclass.py 
new/pyrsistent-0.14.4/pyrsistent/_pclass.py
--- old/pyrsistent-0.13.0/pyrsistent/_pclass.py 2017-09-01 11:44:01.000000000 
+0200
+++ new/pyrsistent-0.14.4/pyrsistent/_pclass.py 2018-07-07 15:53:48.000000000 
+0200
@@ -45,12 +45,12 @@
     """
     def __new__(cls, **kwargs):    # Support *args?
         result = super(PClass, cls).__new__(cls)
-        bypass_factories = kwargs.pop('_bypass_factories', False)
+        factory_fields = kwargs.pop('_factory_fields', None)
         missing_fields = []
         invariant_errors = []
         for name, field in cls._pclass_fields.items():
             if name in kwargs:
-                if not bypass_factories:
+                if factory_fields is None or name in factory_fields:
                     value = field.factory(kwargs[name])
                 else:
                     value = kwargs[name]
@@ -97,16 +97,18 @@
         if args:
             kwargs[args[0]] = args[1]
 
+        factory_fields = set(kwargs)
+
         for key in self._pclass_fields:
             if key not in kwargs:
                 value = getattr(self, key, _MISSING_VALUE)
                 if value is not _MISSING_VALUE:
                     kwargs[key] = value
 
-        return self.__class__(**kwargs)
+        return self.__class__(_factory_fields=factory_fields, **kwargs)
 
     @classmethod
-    def create(cls, kwargs, _bypass_factories=False):
+    def create(cls, kwargs, _factory_fields=None):
         """
         Factory method. Will create a new PClass of the current type and 
assign the values
         specified in kwargs.
@@ -114,7 +116,7 @@
         if isinstance(kwargs, cls):
             return kwargs
 
-        return cls(_bypass_factories=_bypass_factories, **kwargs)
+        return cls(_factory_fields=_factory_fields, **kwargs)
 
     def serialize(self, format=None):
         """
@@ -199,12 +201,13 @@
 
 
 class _PClassEvolver(object):
-    __slots__ = ('_pclass_evolver_original', '_pclass_evolver_data', 
'_pclass_evolver_data_is_dirty')
+    __slots__ = ('_pclass_evolver_original', '_pclass_evolver_data', 
'_pclass_evolver_data_is_dirty', '_factory_fields')
 
     def __init__(self, original, initial_dict):
         self._pclass_evolver_original = original
         self._pclass_evolver_data = initial_dict
         self._pclass_evolver_data_is_dirty = False
+        self._factory_fields = set()
 
     def __getitem__(self, item):
         return self._pclass_evolver_data[item]
@@ -212,6 +215,7 @@
     def set(self, key, value):
         if self._pclass_evolver_data.get(key, _MISSING_VALUE) is not value:
             self._pclass_evolver_data[key] = value
+            self._factory_fields.add(key)
             self._pclass_evolver_data_is_dirty = True
 
         return self
@@ -222,6 +226,7 @@
     def remove(self, item):
         if item in self._pclass_evolver_data:
             del self._pclass_evolver_data[item]
+            self._factory_fields.discard(item)
             self._pclass_evolver_data_is_dirty = True
             return self
 
@@ -232,7 +237,8 @@
 
     def persistent(self):
         if self._pclass_evolver_data_is_dirty:
-            return 
self._pclass_evolver_original.__class__(**self._pclass_evolver_data)
+            return 
self._pclass_evolver_original.__class__(_factory_fields=self._factory_fields,
+                                                           
**self._pclass_evolver_data)
 
         return self._pclass_evolver_original
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_pmap.py 
new/pyrsistent-0.14.4/pyrsistent/_pmap.py
--- old/pyrsistent-0.13.0/pyrsistent/_pmap.py   2017-02-26 14:48:27.000000000 
+0100
+++ new/pyrsistent-0.14.4/pyrsistent/_pmap.py   2018-07-07 15:53:48.000000000 
+0200
@@ -22,7 +22,8 @@
     semantics are the same (more or less) the same function names have been 
used but for some cases it is not possible,
     for example assignments and deletion of values.
 
-    PMap implements the Mapping protocol and is Hashable.
+    PMap implements the Mapping protocol and is Hashable. It also supports 
dot-notation for
+    element access.
 
     Random access and insert is log32(n) where n is the size of the map.
 
@@ -39,6 +40,8 @@
     pmap({'c': 3, 'b': 3})
     >>> m3['c']
     3
+    >>> m3.c
+    3
     """
     __slots__ = ('_size', '_buckets', '__weakref__', '_cached_hash')
 
@@ -91,7 +94,9 @@
         try:
             return self[key]
         except KeyError:
-            raise AttributeError("PMap has no attribute '{0}'".format(key))
+            raise AttributeError(
+                "{0} has no attribute '{1}'".format(type(self).__name__, key)
+            )
 
     def iterkeys(self):
         for k, _ in self.iteritems():
@@ -125,7 +130,24 @@
     def __repr__(self):
         return 'pmap({0})'.format(str(dict(self)))
 
-    __eq__ = Mapping.__eq__
+    def __eq__(self, other):
+        if self is other:
+            return True
+        if not isinstance(other, Mapping):
+            return NotImplemented
+        if len(self) != len(other):
+            return False
+        if isinstance(other, PMap):
+            if (hasattr(self, '_cached_hash') and hasattr(other, 
'_cached_hash')
+                    and self._cached_hash != other._cached_hash):
+                return False
+            if self._buckets == other._buckets:
+                return True
+            return dict(self.iteritems()) == dict(other.iteritems())
+        elif isinstance(other, dict):
+            return dict(self.iteritems()) == other
+        return dict(self.iteritems()) == dict(six.iteritems(other))
+
     __ne__ = Mapping.__ne__
 
     def __lt__(self, other):
@@ -378,7 +400,16 @@
 
 
 def _turbo_mapping(initial, pre_size):
-    size = pre_size or (2 * len(initial)) or 8
+    if pre_size:
+        size = pre_size
+    else:
+        try:
+            size = 2 * len(initial) or 8
+        except Exception:
+            # Guess we can't figure out the length. Give up on length hinting,
+            # we can always reallocate later.
+            size = 8
+
     buckets = size * [None]
 
     if not isinstance(initial, Mapping):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_precord.py 
new/pyrsistent-0.14.4/pyrsistent/_precord.py
--- old/pyrsistent-0.13.0/pyrsistent/_precord.py        2017-09-01 
11:44:01.000000000 +0200
+++ new/pyrsistent-0.14.4/pyrsistent/_precord.py        2018-07-07 
15:53:48.000000000 +0200
@@ -38,7 +38,7 @@
         if '_precord_size' in kwargs and '_precord_buckets' in kwargs:
             return super(PRecord, cls).__new__(cls, kwargs['_precord_size'], 
kwargs['_precord_buckets'])
 
-        bypass_factories = kwargs.pop('_bypass_factories', False)
+        factory_fields = kwargs.pop('_factory_fields', None)
 
         initial_values = kwargs
         if cls._precord_initial_values:
@@ -46,7 +46,7 @@
                                   for k, v in 
cls._precord_initial_values.items())
             initial_values.update(kwargs)
 
-        e = _PRecordEvolver(cls, pmap(), _bypass_factories=bypass_factories)
+        e = _PRecordEvolver(cls, pmap(), _factory_fields=factory_fields)
         for k, v in initial_values.items():
             e[k] = v
 
@@ -77,7 +77,7 @@
                                  ', '.join('{0}={1}'.format(k, repr(v)) for k, 
v in self.items()))
 
     @classmethod
-    def create(cls, kwargs, _bypass_factories=False):
+    def create(cls, kwargs, _factory_fields=None):
         """
         Factory method. Will create a new PRecord of the current type and 
assign the values
         specified in kwargs.
@@ -85,7 +85,7 @@
         if isinstance(kwargs, cls):
             return kwargs
 
-        return cls(_bypass_factories=_bypass_factories, **kwargs)
+        return cls(_factory_fields=_factory_fields, **kwargs)
 
     def __reduce__(self):
         # Pickling support
@@ -100,14 +100,14 @@
 
 
 class _PRecordEvolver(PMap._Evolver):
-    __slots__ = ('_destination_cls', '_invariant_error_codes', 
'_missing_fields', '_bypass_factories')
+    __slots__ = ('_destination_cls', '_invariant_error_codes', 
'_missing_fields', '_factory_fields')
 
-    def __init__(self, cls, original_pmap, _bypass_factories=False):
+    def __init__(self, cls, original_pmap, _factory_fields=None):
         super(_PRecordEvolver, self).__init__(original_pmap)
         self._destination_cls = cls
         self._invariant_error_codes = []
         self._missing_fields = []
-        self._bypass_factories = _bypass_factories
+        self._factory_fields = _factory_fields
 
     def __setitem__(self, key, original_value):
         self.set(key, original_value)
@@ -115,7 +115,7 @@
     def set(self, key, original_value):
         field = self._destination_cls._precord_fields.get(key)
         if field:
-            if not self._bypass_factories:
+            if self._factory_fields is None or field in self._factory_fields:
                 try:
                     value = field.factory(original_value)
                 except InvariantException as e:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent/_pvector.py 
new/pyrsistent-0.14.4/pyrsistent/_pvector.py
--- old/pyrsistent-0.13.0/pyrsistent/_pvector.py        2015-11-01 
21:27:28.000000000 +0100
+++ new/pyrsistent-0.14.4/pyrsistent/_pvector.py        2018-07-07 
15:53:48.000000000 +0200
@@ -76,10 +76,10 @@
         return iter(self.tolist())
 
     def __ne__(self, other):
-        return compare_pvector(self, other, operator.ne)
+        return self._count != len(other) or compare_pvector(self, other, 
operator.ne)
 
     def __eq__(self, other):
-        return self is other or compare_pvector(self, other, operator.eq)
+        return self is other or self._count == len(other) and 
compare_pvector(self, other, operator.eq)
 
     def __gt__(self, other):
         return compare_pvector(self, other, operator.gt)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent.egg-info/PKG-INFO 
new/pyrsistent-0.14.4/pyrsistent.egg-info/PKG-INFO
--- old/pyrsistent-0.13.0/pyrsistent.egg-info/PKG-INFO  2017-09-01 
13:11:16.000000000 +0200
+++ new/pyrsistent-0.14.4/pyrsistent.egg-info/PKG-INFO  2018-07-08 
11:57:12.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pyrsistent
-Version: 0.13.0
+Version: 0.14.4
 Summary: Persistent/Functional/Immutable data structures
 Home-page: http://github.com/tobgu/pyrsistent/
 Author: Tobias Gustafsson
@@ -570,8 +570,8 @@
         Compatibility
         -------------
         
-        Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5 and 
PyPy (Python 2.7 compatible). It will most likely work
-        on all other versions >= 3.4 but no guarantees are given. :)
+        Pyrsistent is developed and tested on Python 2.6, 2.7, 3.4, 3.5, 3.6 
and PyPy (Python 2 and 3 compatible). It will most
+        likely work on all other versions >= 3.4 but no guarantees are given. 
:)
         
         Compatibility issues
         ~~~~~~~~~~~~~~~~~~~~
@@ -643,18 +643,50 @@
         
         Julian Berman https://github.com/Julian
         
+        Dennis Tomas https://github.com/dtomas
+        
+        Neil Vyas https://github.com/neilvyas
+        
+        doozr https://github.com/doozr
+        
         Contributing
         ------------
         
-        If you experience problems please log them on GitHub. If you want to 
contribute code, please fork the code and submit a pull request.
+        Want to contribute? That's great! If you experience problems please 
log them on GitHub. If you want to contribute code,
+        please fork the repository and submit a pull request.
+        
+        Run tests
+        ~~~~~~~~~
+        .. _tox: https://tox.readthedocs.io/en/latest/
+        
+        Tests can be executed using tox_.
+        
+        Install tox: ``pip install tox``
+        
+        Run test for Python 2.7: ``tox -epy27``
+        
+        Project status
+        --------------
+        Pyrsistent can be considered stable and mature (who knows, there may 
even be a 1.0 some day :-)). The project is
+        maintained, bugs fixed, PRs reviewed and merged and new releases made. 
I currently do not have time for development
+        of new features or functionality which I don't have use for myself. 
I'm more than happy to take PRs for new
+        functionality though!
+        
+        There are a bunch of issues marked with ``enhancement`` and ``help 
wanted`` that contain requests for new functionality
+        that would be nice to include. The level of difficulty and extend of 
the issues varies, please reach out to me if you're
+        interested in working on any of them.
+        
+        If you feel that you have a grand master plan for where you would like 
Pyrsistent to go and have the time to put into
+        it please don't hesitate to discuss this with me and submit PRs for 
it. If all goes well I'd be more than happy to add
+        additional maintainers to the project!
         
 Platform: UNKNOWN
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: PyPy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/pyrsistent.egg-info/SOURCES.txt 
new/pyrsistent-0.14.4/pyrsistent.egg-info/SOURCES.txt
--- old/pyrsistent-0.13.0/pyrsistent.egg-info/SOURCES.txt       2017-09-01 
13:11:16.000000000 +0200
+++ new/pyrsistent-0.14.4/pyrsistent.egg-info/SOURCES.txt       2018-07-08 
11:57:12.000000000 +0200
@@ -8,6 +8,7 @@
 setup.py
 pyrsistent/__init__.py
 pyrsistent/_checked_types.py
+pyrsistent/_compat.py
 pyrsistent/_field_common.py
 pyrsistent/_helpers.py
 pyrsistent/_immutable.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/setup.py 
new/pyrsistent-0.14.4/setup.py
--- old/pyrsistent-0.13.0/setup.py      2017-02-26 18:20:54.000000000 +0100
+++ new/pyrsistent-0.14.4/setup.py      2018-07-08 10:28:47.000000000 +0200
@@ -71,11 +71,11 @@
         'Intended Audience :: Developers',
         'License :: OSI Approved :: MIT License',
         'Operating System :: OS Independent',
-        'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: Implementation :: PyPy',
     ],
     test_suite='tests',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/bag_test.py 
new/pyrsistent-0.14.4/tests/bag_test.py
--- old/pyrsistent-0.13.0/tests/bag_test.py     2017-01-06 18:12:59.000000000 
+0100
+++ new/pyrsistent-0.14.4/tests/bag_test.py     2018-07-07 15:53:48.000000000 
+0200
@@ -140,3 +140,11 @@
 def test_update_no_elements():
     b = pbag([1, 2, 2])
     assert b.update([]) is b
+
+
+def test_iterable():
+    """
+    PBags can be created from iterables even though they can't be len() hinted.
+    """
+
+    assert pbag(iter("a")) == pbag(iter("a"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/class_test.py 
new/pyrsistent-0.14.4/tests/class_test.py
--- old/pyrsistent-0.13.0/tests/class_test.py   2017-09-01 11:44:01.000000000 
+0200
+++ new/pyrsistent-0.14.4/tests/class_test.py   2018-07-07 15:53:48.000000000 
+0200
@@ -23,6 +23,7 @@
 
 class UniqueThing(PClass):
     id = field(type=uuid.UUID, factory=uuid.UUID)
+    x = field(type=int)
 
 
 def test_evolve_pclass_instance():
@@ -407,6 +408,46 @@
 
     MyClass2()
 
+
 def test_pickle_with_one_way_factory():
     thing = UniqueThing(id='25544626-86da-4bce-b6b6-9186c0804d64')
     assert pickle.loads(pickle.dumps(thing)) == thing
+
+
+def test_evolver_with_one_way_factory():
+    thing = UniqueThing(id='cc65249a-56fe-4995-8719-ea02e124b234')
+    ev = thing.evolver()
+    ev.x = 5  # necessary to prevent persistent() returning the original
+    assert ev.persistent() == UniqueThing(id=str(thing.id), x=5)
+
+
+def test_set_doesnt_trigger_other_factories():
+    thing = UniqueThing(id='b413b280-de76-4e28-a8e3-5470ca83ea2c')
+    thing.set(x=5)
+
+
+def test_set_does_trigger_factories():
+    class SquaredPoint(PClass):
+        x = field(factory=lambda x: x ** 2)
+        y = field()
+
+    sp = SquaredPoint(x=3, y=10)
+    assert (sp.x, sp.y) == (9, 10)
+
+    sp2 = sp.set(x=4)
+    assert (sp2.x, sp2.y) == (16, 10)
+
+
+def test_value_can_be_overridden_in_subclass_new():
+    class X(PClass):
+        y = pvector_field(int)
+
+        def __new__(cls, **kwargs):
+            items = kwargs.get('y', None)
+            if items is None:
+                kwargs['y'] = ()
+            return super(X, cls).__new__(cls, **kwargs)
+
+    a = X(y=[])
+    b = a.set(y=None)
+    assert a == b
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/deque_test.py 
new/pyrsistent-0.14.4/tests/deque_test.py
--- old/pyrsistent-0.13.0/tests/deque_test.py   2017-09-01 11:44:01.000000000 
+0200
+++ new/pyrsistent-0.14.4/tests/deque_test.py   2018-07-07 15:53:48.000000000 
+0200
@@ -282,3 +282,12 @@
 def test_supports_weakref():
     import weakref
     weakref.ref(dq(1, 2))
+
+
+def test_iterable():
+    """
+    PDeques can be created from iterables even though they can't be len()
+    hinted.
+    """
+
+    assert pdeque(iter("a")) == pdeque(iter("a"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/field_test.py 
new/pyrsistent-0.14.4/tests/field_test.py
--- old/pyrsistent-0.13.0/tests/field_test.py   2017-06-04 10:28:26.000000000 
+0200
+++ new/pyrsistent-0.14.4/tests/field_test.py   2018-07-07 15:53:48.000000000 
+0200
@@ -1,18 +1,27 @@
-from pyrsistent import field
+from pyrsistent._compat import Enum
 
+from pyrsistent import field, pvector_field
 
-def test_enum():
-    try:
-        from enum import Enum
-    except ImportError:
-        # skip enum test if Enums are not available
-        return
-
-    class TestEnum(Enum):
-        x = 1
-        y = 2
 
+# NB: This derives from the internal `pyrsistent._compat.Enum` in order to
+# simplify coverage across python versions. Since we use
+# `pyrsistent._compat.Enum` in `pyrsistent`'s implementation, it's useful to
+# use it in the test coverage as well, for consistency.
+class TestEnum(Enum):
+    x = 1
+    y = 2
+
+
+def test_enum():
     f = field(type=TestEnum)
 
     assert TestEnum in f.type
     assert len(f.type) == 1
+
+
+# This is meant to exercise `_seq_field`.
+def test_pvector_field_enum_type():
+    f = pvector_field(TestEnum)
+
+    assert len(f.type) == 1
+    assert TestEnum is list(f.type)[0].__type__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/list_test.py 
new/pyrsistent-0.14.4/tests/list_test.py
--- old/pyrsistent-0.13.0/tests/list_test.py    2015-09-28 20:40:21.000000000 
+0200
+++ new/pyrsistent-0.14.4/tests/list_test.py    2018-07-07 15:53:48.000000000 
+0200
@@ -197,4 +197,13 @@
 def test_supports_weakref():
     import weakref
     weakref.ref(plist())
-    weakref.ref(plist([1, 2]))
\ No newline at end of file
+    weakref.ref(plist([1, 2]))
+
+
+def test_iterable():
+    """
+    PLists can be created from iterables even though they can't be len()
+    hinted.
+    """
+
+    assert plist(iter("a")) == plist(iter("a"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/map_test.py 
new/pyrsistent-0.14.4/tests/map_test.py
--- old/pyrsistent-0.13.0/tests/map_test.py     2017-02-26 14:48:27.000000000 
+0100
+++ new/pyrsistent-0.14.4/tests/map_test.py     2018-07-07 15:53:48.000000000 
+0200
@@ -117,13 +117,11 @@
     assert map2['a'] == 3
 
 
-def test_supports_hash_and_equals():
+def test_hash():
     x = m(a=1, b=2, c=3)
     y = m(a=1, b=2, c=3)
-    
+
     assert hash(x) == hash(y)
-    assert x == y
-    assert not (x != y)
 
 
 def test_same_hash_when_content_the_same_but_underlying_vector_size_differs():
@@ -156,6 +154,72 @@
     hash(x)
 
 
+def test_equal():
+    x = m(a=1, b=2, c=3)
+    y = m(a=1, b=2, c=3)
+
+    assert x == y
+    assert not (x != y)
+
+    assert y == x
+    assert not (y != x)
+
+
+def test_equal_to_dict():
+    x = m(a=1, b=2, c=3)
+    y = dict(a=1, b=2, c=3)
+
+    assert x == y
+    assert not (x != y)
+
+    assert y == x
+    assert not (y != x)
+
+
+def test_equal_with_different_bucket_sizes():
+    x = pmap({'a': 1, 'b': 2}, 50)
+    y = pmap({'a': 1, 'b': 2}, 10)
+
+    assert x == y
+    assert not (x != y)
+
+    assert y == x
+    assert not (y != x)
+
+
+def test_equal_with_different_insertion_order():
+    x = pmap([(i, i) for i in range(50)], 10)
+    y = pmap([(i, i) for i in range(49, -1, -1)], 10)
+
+    assert x == y
+    assert not (x != y)
+
+    assert y == x
+    assert not (y != x)
+
+
+def test_not_equal():
+    x = m(a=1, b=2, c=3)
+    y = m(a=1, b=2)
+
+    assert x != y
+    assert not (x == y)
+
+    assert y != x
+    assert not (y == x)
+
+
+def test_not_equal_to_dict():
+    x = m(a=1, b=2, c=3)
+    y = dict(a=1, b=2, d=4)
+
+    assert x != y
+    assert not (x == y)
+
+    assert y != x
+    assert not (y == x)
+
+
 def test_update_with_multiple_arguments():
     # If same value is present in multiple sources, the rightmost is used.
     x = m(a=1, b=2, c=3)    
@@ -399,7 +463,10 @@
     with pytest.raises(AttributeError) as error:
         m1.b
 
-    assert "'b'" in str(error.value)
+    error_message = str(error.value)
+
+    assert "'b'" in error_message
+    assert type(m1).__name__ in error_message
 
 
 def test_pmap_unorderable():
@@ -419,3 +486,11 @@
 def test_supports_weakref():
     import weakref
     weakref.ref(m(a=1))
+
+
+def test_iterable():
+    """
+    PMaps can be created from iterables even though they can't be len() hinted.
+    """
+
+    assert pmap(iter([("a", "b")])) == pmap([("a", "b")])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/record_test.py 
new/pyrsistent-0.14.4/tests/record_test.py
--- old/pyrsistent-0.13.0/tests/record_test.py  2017-09-01 11:44:01.000000000 
+0200
+++ new/pyrsistent-0.14.4/tests/record_test.py  2018-07-07 15:53:48.000000000 
+0200
@@ -24,6 +24,12 @@
     id = field(type=uuid.UUID, factory=uuid.UUID)
 
 
+class Something(object):
+    pass
+
+class Another(object):
+    pass
+
 def test_create():
     r = ARecord(x=1, y='foo')
     assert r.x == 1
@@ -443,9 +449,6 @@
     """
     The created set class name is based on the type of items in the set.
     """
-    class Something(object):
-        pass
-
     class Record(PRecord):
         value = pset_field(Something)
         value2 = pset_field(int)
@@ -458,15 +461,31 @@
     The created set class name is based on the multiple given types of
     items in the set.
     """
-    class Something(object):
-        pass
-
     class Record(PRecord):
         value = pset_field((Something, int))
 
     assert (Record().value.__class__.__name__ ==
             "SomethingIntPSet")
 
+def test_pset_field_name_string_type():
+    """
+    The created set class name is based on the type of items specified by name
+    """
+    class Record(PRecord):
+        value = pset_field("record_test.Something")
+    assert Record().value.__class__.__name__ == "SomethingPSet"
+
+
+def test_pset_multiple_string_types_field_name():
+    """
+    The created set class name is based on the multiple given types of
+    items in the set specified by name
+    """
+    class Record(PRecord):
+        value = pset_field(("record_test.Something", "record_test.Another"))
+
+    assert Record().value.__class__.__name__ == "SomethingAnotherPSet"
+
 def test_pvector_field_initial_value():
     """
     ``pvector_field`` results in initial value that is empty.
@@ -566,9 +585,6 @@
     """
     The created set class name is based on the type of items in the set.
     """
-    class Something(object):
-        pass
-
     class Record(PRecord):
         value = pvector_field(Something)
         value2 = pvector_field(int)
@@ -581,15 +597,31 @@
     The created vector class name is based on the multiple given types of
     items in the vector.
     """
-    class Something(object):
-        pass
-
     class Record(PRecord):
         value = pvector_field((Something, int))
 
     assert (Record().value.__class__.__name__ ==
             "SomethingIntPVector")
 
+def test_pvector_field_name_string_type():
+    """
+    The created set class name is based on the type of items in the set
+    specified by name.
+    """
+    class Record(PRecord):
+        value = pvector_field("record_test.Something")
+    assert Record().value.__class__.__name__ == "SomethingPVector"
+
+def test_pvector_multiple_string_types_field_name():
+    """
+    The created vector class name is based on the multiple given types of
+    items in the vector.
+    """
+    class Record(PRecord):
+        value = pvector_field(("record_test.Something", "record_test.Another"))
+
+    assert Record().value.__class__.__name__ == "SomethingAnotherPVector"
+
 def test_pvector_field_create_from_nested_serialized_data():
     class Foo(PRecord):
         foo = field(type=str)
@@ -696,19 +728,13 @@
     """
     class Record(PRecord):
         value = pmap_field(int, int, optional=True)
-    assert ((Record(value={1: 2}).value, Record(value=None).value) ==
-            pmap({1: 2}), None)
+    assert (Record(value={1: 2}).value, Record(value=None).value) == \
+           (pmap({1: 2}), None)
 
 def test_pmap_field_name():
     """
     The created map class name is based on the types of items in the map.
     """
-    class Something(object):
-        pass
-
-    class Another(object):
-        pass
-
     class Record(PRecord):
         value = pmap_field(Something, Another)
         value2 = pmap_field(int, float)
@@ -721,12 +747,6 @@
     The created map class name is based on the types of items in the map,
     including when there are multiple supported types.
     """
-    class Something(object):
-        pass
-
-    class Another(object):
-        pass
-
     class Record(PRecord):
         value = pmap_field((Something, Another), int)
         value2 = pmap_field(str, (int, float))
@@ -734,6 +754,27 @@
              Record().value2.__class__.__name__) ==
             ("SomethingAnotherToIntPMap", "StrToIntFloatPMap"))
 
+def test_pmap_field_name_string_type():
+    """
+    The created map class name is based on the types of items in the map
+    specified by name.
+    """
+    class Record(PRecord):
+        value = pmap_field("record_test.Something", "record_test.Another")
+    assert Record().value.__class__.__name__ == "SomethingToAnotherPMap"
+
+def test_pmap_field_name_multiple_string_types():
+    """
+    The created map class name is based on the types of items in the map,
+    including when there are multiple supported types.
+    """
+    class Record(PRecord):
+        value = pmap_field(("record_test.Something", "record_test.Another"), 
int)
+        value2 = pmap_field(str, ("record_test.Something", 
"record_test.Another"))
+    assert ((Record().value.__class__.__name__,
+             Record().value2.__class__.__name__) ==
+            ("SomethingAnotherToIntPMap", "StrToSomethingAnotherPMap"))
+
 def test_pmap_field_invariant():
     """
     The ``invariant`` parameter is passed through to ``field``.
@@ -774,6 +815,7 @@
 
     assert MyRecord() == MyRecord(a=2)
 
+
 def test_pickle_with_one_way_factory():
     """
     A field factory isn't called when restoring from pickle.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/set_test.py 
new/pyrsistent-0.14.4/tests/set_test.py
--- old/pyrsistent-0.13.0/tests/set_test.py     2017-01-06 18:16:36.000000000 
+0100
+++ new/pyrsistent-0.14.4/tests/set_test.py     2018-07-07 15:53:48.000000000 
+0200
@@ -168,3 +168,11 @@
 def test_update_no_elements():
     s1 = s(1, 2)
     assert s1.update([]) is s1
+
+
+def test_iterable():
+    """
+    PSets can be created from iterables even though they can't be len() hinted.
+    """
+
+    assert pset(iter("a")) == pset(iter("a"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyrsistent-0.13.0/tests/vector_test.py 
new/pyrsistent-0.14.4/tests/vector_test.py
--- old/pyrsistent-0.13.0/tests/vector_test.py  2017-02-26 18:11:22.000000000 
+0100
+++ new/pyrsistent-0.14.4/tests/vector_test.py  2018-07-07 15:53:48.000000000 
+0200
@@ -907,3 +907,12 @@
 
     with pytest.raises(ValueError):
         repr(pvector([A()]))
+
+
+def test_iterable(pvector):
+    """
+    PVectors can be created from iterables even though they can't be len()
+    hinted.
+    """
+
+    assert pvector(iter("a")) == pvector(iter("a"))


Reply via email to