Hello community,

here is the log from the commit of package python-param for openSUSE:Factory 
checked in at 2018-04-19 15:31:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-param (Old)
 and      /work/SRC/openSUSE:Factory/.python-param.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-param"

Thu Apr 19 15:31:22 2018 rev:3 rq:597608 version:1.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-param/python-param.changes        
2017-08-18 15:06:06.751716657 +0200
+++ /work/SRC/openSUSE:Factory/.python-param.new/python-param.changes   
2018-04-19 15:31:24.946311598 +0200
@@ -1,0 +2,6 @@
+Wed Apr 18 02:07:38 UTC 2018 - toddrme2...@gmail.com
+
+- Update to version 1.6.0
+  * Drop Cython build
+
+-------------------------------------------------------------------

Old:
----
  param-1.5.1.tar.gz

New:
----
  param-1.6.0.tar.gz

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

Other differences:
------------------
++++++ python-param.spec ++++++
--- /var/tmp/diff_new_pack.2m6d1r/_old  2018-04-19 15:31:25.490289239 +0200
+++ /var/tmp/diff_new_pack.2m6d1r/_new  2018-04-19 15:31:25.490289239 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-param
 #
-# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-param
-Version:        1.5.1
+Version:        1.6.0
 Release:        0
 Summary:        Declarative Python programming using Parameters
 License:        BSD-3-Clause
@@ -27,10 +27,10 @@
 Source:         
https://files.pythonhosted.org/packages/source/p/param/param-%{version}.tar.gz
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-BuildRequires:  %{python_module Cython}
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module setuptools}
-Recommends:     python-jupyter_ipython
+Recommends:     python-numpy
+BuildArch:      noarch
 %python_subpackages
 
 %description
@@ -52,13 +52,13 @@
 
 %install
 %python_install
-%python_expand %fdupes %{buildroot}%{$python_sitearch}
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %files %{python_files}
 %defattr(-,root,root,-)
 %doc LICENSE.txt README.rst
-%{python_sitearch}/param/
-%{python_sitearch}/numbergen/
-%{python_sitearch}/param-%{version}-py*.egg-info
+%{python_sitelib}/param/
+%{python_sitelib}/numbergen/
+%{python_sitelib}/param-%{version}-py*.egg-info
 
 %changelog

++++++ param-1.5.1.tar.gz -> param-1.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/LICENSE.txt new/param-1.6.0/LICENSE.txt
--- old/param-1.5.1/LICENSE.txt 2015-10-27 04:15:07.000000000 +0100
+++ new/param-1.6.0/LICENSE.txt 2018-04-05 12:24:35.000000000 +0200
@@ -1,4 +1,4 @@
-Copyright (c) 2005-2015, IOAM (ioam.github.com)
+Copyright (c) 2005-2018, IOAM (ioam.github.com)
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/MANIFEST.in new/param-1.6.0/MANIFEST.in
--- old/param-1.5.1/MANIFEST.in 2015-10-27 04:15:07.000000000 +0100
+++ new/param-1.6.0/MANIFEST.in 2018-04-05 12:24:35.000000000 +0200
@@ -1,5 +1,6 @@
 include README.rst
 include LICENSE.txt
 include setup.py
+include param/.version
 recursive-include param *.py
 recursive-include numbergen *.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/PKG-INFO new/param-1.6.0/PKG-INFO
--- old/param-1.5.1/PKG-INFO    2017-04-26 15:48:48.000000000 +0200
+++ new/param-1.6.0/PKG-INFO    2018-04-05 12:25:08.000000000 +0200
@@ -1,12 +1,14 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: param
-Version: 1.5.1
+Version: 1.6.0
 Summary: Declarative Python programming using Parameters.
 Home-page: http://ioam.github.com/param/
 Author: IOAM
 Author-email: develop...@topographica.org
+Maintainer: IOAM
+Maintainer-email: develop...@topographica.org
 License: BSD
-Description: |BuildStatus|_ |PyPIVersion|_ |PyVersion|_ |License|_
+Description: |LinuxTests|_ |WinTests|_ |Coverage|_ |PyPIVersion|_ |PyVersion|_ 
|License|_
         
         Param
         =====
@@ -24,8 +26,14 @@
         Please see `param's website <http://ioam.github.com/param/>`_ for
         official releases, installation instructions, documentation, and 
examples.
         
-        .. |BuildStatus| image:: 
https://travis-ci.org/ioam/param.svg?branch=master
-        .. _BuildStatus: https://travis-ci.org/ioam/param
+        .. |LinuxTests| image:: 
https://travis-ci.org/ioam/param.svg?branch=master
+        .. _LinuxTests: https://travis-ci.org/ioam/param
+        
+        .. |WinTests| image:: 
https://ci.appveyor.com/api/projects/status/huoiwwamso2or7xw/branch/master?svg=true
+        .. _WinTests: https://ci.appveyor.com/project/Ioam/param/branch/master
+        
+        .. |Coverage| image:: https://img.shields.io/coveralls/ioam/param.svg
+        .. _Coverage: https://coveralls.io/r/ioam/param?branch=master
         
         .. |PyPIVersion| image:: http://img.shields.io/pypi/v/param.svg
         .. _PyPIVersion: https://pypi.python.org/pypi/param
@@ -42,12 +50,12 @@
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Operating System :: OS Independent
 Classifier: Intended Audience :: Science/Research
 Classifier: Intended Audience :: Developers
@@ -56,3 +64,6 @@
 Classifier: Topic :: Software Development :: Libraries
 Provides: param
 Provides: numbergen
+Requires-Python: >=2.7
+Provides-Extra: tests
+Provides-Extra: all
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/README.rst new/param-1.6.0/README.rst
--- old/param-1.5.1/README.rst  2016-04-07 01:28:09.000000000 +0200
+++ new/param-1.6.0/README.rst  2018-04-05 12:24:35.000000000 +0200
@@ -1,4 +1,4 @@
-|BuildStatus|_ |PyPIVersion|_ |PyVersion|_ |License|_
+|LinuxTests|_ |WinTests|_ |Coverage|_ |PyPIVersion|_ |PyVersion|_ |License|_
 
 Param
 =====
@@ -16,8 +16,14 @@
 Please see `param's website <http://ioam.github.com/param/>`_ for
 official releases, installation instructions, documentation, and examples.
 
-.. |BuildStatus| image:: https://travis-ci.org/ioam/param.svg?branch=master
-.. _BuildStatus: https://travis-ci.org/ioam/param
+.. |LinuxTests| image:: https://travis-ci.org/ioam/param.svg?branch=master
+.. _LinuxTests: https://travis-ci.org/ioam/param
+
+.. |WinTests| image:: 
https://ci.appveyor.com/api/projects/status/huoiwwamso2or7xw/branch/master?svg=true
+.. _WinTests: https://ci.appveyor.com/project/Ioam/param/branch/master
+
+.. |Coverage| image:: https://img.shields.io/coveralls/ioam/param.svg
+.. _Coverage: https://coveralls.io/r/ioam/param?branch=master
 
 .. |PyPIVersion| image:: http://img.shields.io/pypi/v/param.svg
 .. _PyPIVersion: https://pypi.python.org/pypi/param
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/numbergen/__init__.py 
new/param-1.6.0/numbergen/__init__.py
--- old/param-1.5.1/numbergen/__init__.py       2017-04-26 15:16:31.000000000 
+0200
+++ new/param-1.6.0/numbergen/__init__.py       2018-04-05 12:24:35.000000000 
+0200
@@ -13,10 +13,7 @@
 import param
 
 
-from param.version import Version
-__version__ = Version(release=(1,5,1), fpath=__file__,
-                      commit="$Format:%h$", reponame="param")
-
+from param import __version__  # noqa: API import
 
 class TimeAware(param.Parameterized):
     """
@@ -727,8 +724,8 @@
     def __call__(self):
         val = self.generator()
         min_, max_ = self.bounds
-        if   min_ != None and val < min_: return min_
-        elif max_ != None and val > max_: return max_
+        if   min_ is not None and val < min_: return min_
+        elif max_ is not None and val > max_: return max_
         else: return val
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/param/.version 
new/param-1.6.0/param/.version
--- old/param-1.5.1/param/.version      1970-01-01 01:00:00.000000000 +0100
+++ new/param-1.6.0/param/.version      2018-04-05 12:25:07.000000000 +0200
@@ -0,0 +1 @@
+{"git_describe": "v1.6.0-0-g445d051", "version_string": "1.6.0"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/param/__init__.py 
new/param-1.6.0/param/__init__.py
--- old/param-1.5.1/param/__init__.py   2017-04-26 12:39:28.000000000 +0200
+++ new/param-1.6.0/param/__init__.py   2018-04-05 12:24:35.000000000 +0200
@@ -25,15 +25,10 @@
 from .parameterized import Parameterized, Parameter, String, \
      descendents, ParameterizedFunction, ParamOverrides
 
-from .parameterized import logging_level # pyflakes:ignore (needed for eval)
-from .parameterized import shared_parameters # pyflakes:ignore (needed for 
eval)
+from .parameterized import logging_level     # noqa: api import
+from .parameterized import shared_parameters # noqa: api import
 
-try:
-   from collections import OrderedDict
-except ImportError:
-    from ordereddict import OrderedDict
-except ImportError as e:
-    raise ImportError("Requires ordereddict package on Python 2.6")
+from collections import OrderedDict
 
 
 # Determine up-to-date version information, if possible, but with a
@@ -41,10 +36,9 @@
 # only two required files.
 try:
     from .version import Version
-    __version__ = Version(release=(1,5,1), fpath=__file__,
-                          commit="$Format:%h$", reponame="param")
+    __version__ = str(Version(fpath=__file__, archive_commit="$Format:%h$", 
reponame="param"))
 except:
-    __version__ = '1.5.1-unknown'
+    __version__ = "0.0.0+unknown"
 
 
 dt_types = (dt.datetime,)
@@ -449,7 +443,7 @@
 
         dynamic = callable(val)
         if dynamic: self._initialize_generator(val,obj)
-        if not obj: self._set_instantiate(dynamic)
+        if obj is None: self._set_instantiate(dynamic)
 
 
     def _produce_value(self,gen,force=False):
@@ -744,6 +738,9 @@
 class Integer(Number):
     """Numeric Parameter required to be an Integer"""
 
+    def __init__(self,default=0,**params):
+       Number.__init__(self,default=default,**params)
+
     def _check_value(self,val):
         if self.allow_None and val is None:
             return
@@ -927,7 +924,7 @@
         """
         Return the values of all the attribs, as a list.
         """
-        if not obj:
+        if obj is None:
             return [getattr(objtype,a) for a in self.attribs]
         else:
             return [getattr(obj,a) for a in self.attribs]
@@ -938,7 +935,7 @@
         """
         assert len(val) == len(self.attribs),"Compound parameter '%s' got the 
wrong number of values (needed %d, but got %d)." % 
(self._attrib_name,len(self.attribs),len(val))
 
-        if not obj:
+        if obj is None:
             for a,v in zip(self.attribs,val):
                 setattr(self.objtype,a,v)
         else:
@@ -1478,8 +1475,8 @@
         if self.default is None and callable(self.compute_default_fn):
             self.default = self.compute_default_fn()
             for o in self.default:
-                if self.default not in self.objects:
-                    self.objects.append(self.default)
+                if o not in self.objects:
+                    self.objects.append(o)
 
     def _check_value(self, val, obj=None):
         for o in val:
@@ -1627,3 +1624,28 @@
                 if too_low or too_high:
                     raise ValueError("Parameter '%s' %s bound must be in range 
%s"
                                      % (self._attrib_name, bound, 
self.rangestr()))
+
+
+class DateRange(Range):
+    """
+    A date range specified as (start_date, end_date).
+
+    Dates must be specified as datetime-like types (see
+    param.dt_types).
+    """
+    def _check(self,val):
+        if self.allow_None and val is None:
+            return
+
+        for n in val:
+            if not isinstance(n, dt_types):
+                raise ValueError("DateRange '%s' only takes datetime types: 
%s"%(self._attrib_name,val))
+
+        start, end = val
+        if not end >= start:
+           raise ValueError("DateRange '%s': end date %s is before start date 
%s."%(self._attrib_name,val[1],val[0]))
+
+        # Calling super(DateRange, self)._check(val) would also check
+        # values are numeric, which is redundant, so just call
+        # _checkBounds().
+        self._checkBounds(val)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/param/parameterized.py 
new/param-1.6.0/param/parameterized.py
--- old/param-1.5.1/param/parameterized.py      2017-04-26 14:38:21.000000000 
+0200
+++ new/param-1.6.0/param/parameterized.py      2018-04-05 12:24:35.000000000 
+0200
@@ -522,12 +522,12 @@
     A simple String parameter.
     """
 
-    basestring = basestring if sys.version_info[0]==2 else str
+    basestring = basestring if sys.version_info[0]==2 else str # noqa: it is 
defined
 
     def __init__(self, default="", allow_None=False, **kwargs):
         super(String, self).__init__(default=default, allow_None=allow_None, 
**kwargs)
         self._check_value(default)
-        self.allow_None = allow_None
+        self.allow_None = (default is None or allow_None)
 
     def _check_value(self,val):
         if not isinstance(val, self.basestring) and not (self.allow_None and 
val is None):
@@ -1441,21 +1441,24 @@
             setattr(self,name,val)
 
 
-    def get_param_values(self,onlychanged=False):
+    @bothmethod
+    def get_param_values(self_or_cls,onlychanged=False):
         """
         Return a list of name,value pairs for all Parameters of this
         object.
 
-        If onlychanged is True, will only return values that are not
-        equal to the default value.
+        When called on an instance with onlychanged set to True, will
+        only return values that are not equal to the default value
+        (onlychanged has no effect when called on a class).
         """
         # CEB: we'd actually like to know whether a value has been
         # explicitly set on the instance, but I'm not sure that's easy
         # (would need to distinguish instantiation of default from
         # user setting of value).
         vals = []
-        for name,val in self.params().items():
-            value = self.get_value_generator(name)
+        for name,val in self_or_cls.params().items():
+            value = self_or_cls.get_value_generator(name)
+            # (this is pointless for cls)
             if not onlychanged or not all_equal(value,val.default):
                 vals.append((name,value))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/param/version.py 
new/param-1.6.0/param/version.py
--- old/param-1.5.1/param/version.py    2017-04-26 15:41:31.000000000 +0200
+++ new/param-1.6.0/param/version.py    2018-04-05 12:24:35.000000000 +0200
@@ -1,4 +1,14 @@
-"""
+"""Apart from this first paragraph, this version.py file is an exact
+copy of 
https://github.com/ioam/autover/blob/59c207db70da6f41b689e8be5c5f6abb1e062c8e/autover/version.py.
+Autover's version.py is included inside the param package only to make
+version.py available to various other projects that use version.py and
+already depend on param, thus saving them from bundling version.py or
+dependending on autover. Otherwise, version.py would only be in the
+root of param's git repository, and would not be part of the param
+package.
+
+-----
+
 Provide consistent and up-to-date ``__version__`` strings for Python
 packages.
 
@@ -8,14 +18,14 @@
 especially if releases are infrequent.
 
 This file provides a Version class that addresses both problems.
-Version is meant to be a simple, bare-bones approach that focuses on
-(a) ensuring that all declared version information matches for a
-release, and (b) providing fine-grained version information via a
-version control system (VCS) in between releases.  Other approaches
-like versioneer.py can automate more of the process of making
-releases, but they require more complex self-modifying code and code
-generation techniques than the simple Python class declaration used
-here.
+Version is meant to be a simple, bare-bones approach that focuses on (a)
+ensuring that all declared version information matches for a release if
+supplied, and (b) providing fine-grained version information via a
+version control system (VCS) in between releases (c) allowing versions
+to be specified with tags alone.  Other approaches like versioneer.py
+can automate more of the process of making releases, but they require
+more complex self-modifying code and code generation techniques than the
+simple Python class declaration used here.
 
 Currently, the only VCS supported is git, but others could be added
 easily.
@@ -24,24 +34,36 @@
 ``package`` maintained in a git repository named ``packagegit``:
 
 1. Make the Version class available for import from your package,
-   either by adding the PyPI package "param" as a dependency for your
-   package, or by simply copying this file into ``package/version.py``.
+   either by adding the PyPI package "autover" as a dependency for your
+   package, or by simply copying this file into ``package/autover.py``.
 
-2. Assuming that the current version of your package is 1.0.0, add the
-   following lines to your ``package/__init__.py``::
+2. Assuming that the current version of your package is 1.0.0 (and you
+   want to enforce this), add the following lines to your
+   ``package/__init__.py``::
 
-     from param import Version
+     from autover import Version
      __version__ = Version(release=(1,0,0), fpath=__file__,
                            commit="$Format:%h$", reponame="packagegit")
 
    (or ``from .version import Version`` if you copied the file directly.)
 
+   You can supply release=None if you want to set the version purely via a tag.
+
 3. Declare the version as a string in your package's setup.py file, e.g.::
 
      setup_args["version"]="1.0.0"
 
-4. In your package's setup.py script code for making a release, add a
-   call to the Version.verify method. E.g.::
+  This acts as an explicit check you can verify against. You can also set this
+  up against the tag using:
+
+      setup_args["version"]=get_setup_version("autover") # Your package name 
here
+
+  To use this, adapt the get_setup_version function in autover/setup.py for use
+  in your package's setup.py.
+
+
+4. (Optional) In your package's setup.py script code for making a
+   release, you can add a call to the Version.verify method. E.g.::
 
      setup_args = dict(name='package', version="1.0.0", ...)
 
@@ -51,36 +73,54 @@
               package.__version__.verify(setup_args['version'])
           setup(**setup_args)
 
+  This can help make sure the repository is in a good state before
+  building a package (e.g not dirty).
+
 4. Tag the version of the repository to be released with a string of
-   the form v*.*, i.e. ``v1.0.0`` in this example.  E.g. for git::
+   the form v*.*.*, i.e. ``v1.0.0`` in this example.  E.g. for git::
 
      git tag -a v1.0.0 -m 'Release version 1.0.0' ; git push
 
-
-Now when you run ``setup.py`` to make a release via something like
-``python setup.py register sdist upload``, Python will verify that the
-version last tagged in the VCS is the same as what is declared in the
-package and also in setup.py, aborting the release until either the
-tag is corrected or the declared version is made to match the tag.
-Releases installed without VCS information will then report the
-declared release version.  If VCS information is available and matches
-the specified repository name, then the version reported from
-e.g. ``str(package.__version__)`` will provide more detailed
-information about the precise VCS revision changes since the release.
-See the docstring for the Version class for more detailed information.
+  You need to use an annotated tag (i.e the -a flag) and you can use
+  PEP440 compliant strings as long as they start with a 'v' e.g
+  v1.0.1a1 v2.3rc5 etc.
+
+If you chose to specify explicit version strings in setup.py and
+__init__.py and used the verify method, running ``setup.py`` to make a
+release via something like ``python setup.py register sdist upload``,
+Python will verify that the version last tagged in the VCS is the same
+as what is declared in the package and the setup.py, aborting the
+release until either the tag is corrected or the declared version is
+made to match the tag.
+
+Releases installed without VCS information will then report the declared
+release version if specified, otherwise it will read the .version file
+containing the VSC information when the package was build . If live VCS
+information is available and matches the specified repository name, then
+the version reported from e.g. ``str(package.__version__)`` will provide
+more detailed information about the precise VCS revision changes since
+the release.  See the docstring for the Version class for more detailed
+information.
+
+If you used release=None in __init__.py and the get_setup_version
+function in setup.py, all you need to get a live version string is set
+an appropriate VCS tag. Note that to ensure this is always correct,
+autover is required as a build dependency, otherwise the information
+available in the .version file is used.
 
 This file is in the public domain, provided as-is, with no warranty of
 any kind expressed or implied.  Anyone is free to copy, modify,
 publish, use, compile, sell, or distribute it under any license, for
 any purpose, commercial or non-commercial, and by any means.  The
 original file is maintained at:
-https://github.com/ioam/param/blob/master/param/version.py
+https://github.com/ioam/autover/blob/master/autover/__init__.py
+
 """
 
 
 __author__ = 'Jean-Luc Stevens'
 
-import os, subprocess
+import os, subprocess, json
 
 def run_cmd(args, cwd=None):
     proc = subprocess.Popen(args, stdout=subprocess.PIPE,
@@ -92,6 +132,8 @@
         raise Exception(proc.returncode, error)
     return output
 
+
+
 class Version(object):
     """
     A simple approach to Python package versioning that supports PyPI
@@ -104,45 +146,72 @@
     two or three numeric versioning levels typical.
 
     During development, a command like ``git describe`` will be used to
-    compute the number of commits since the last version tag, the
-    short commit hash, and whether the commit is dirty (has changes
-    not yet committed). Version tags must start with a lowercase 'v'
-    and have a period in them, e.g. v2.0, v0.9.8, v0.1a, or v0.2beta.
-    Note that any non-numeric portion of the version ("a", "beta",
-    etc.)  will currently be discarded for the purposes of numeric
-    comparisons.
+    compute the number of commits since the last version tag, the short
+    commit hash, and whether the commit is dirty (has changes not yet
+    committed). Version tags must start with a lowercase 'v' and have a
+    period in them, e.g. v2.0, v0.9.8 or v0.1 and may include the PEP440
+    prerelease identifiers of 'a' (alpha) 'b' (beta) or 'rc' (release
+    candidate) allowing tags such as v2.0.a3, v0.9.8.b3 or v0.1.rc5.
 
     Also note that when version control system (VCS) information is
-    used, the comparison operators take into account the number of
-    commits since the last version tag. This approach is often useful
-    in practice to decide which version is newer for a single
-    developer, but will not necessarily be reliable when comparing
-    against a different fork or branch in a distributed VCS.
+    used, the number of commits since the last version tag is
+    determined. This approach is often useful in practice to decide
+    which version is newer for a single developer, but will not
+    necessarily be reliable when comparing against a different fork or
+    branch in a distributed VCS.
 
     For git, if you want version control information available even in
     an exported archive (e.g. a .zip file from GitHub), you can set
     the following line in the .gitattributes file of your project::
 
       __init__.py export-subst
-    """
 
-    def __init__(self, release=None, fpath=None, commit=None, reponame=None, 
commit_count=0):
+    Note that to support pip installation directly from GitHub via git
+    archive, a .version file must be tracked by the repo to supply the
+    release number (otherwise only the short SHA is available).
+
+    The PEP440 format returned is [N!]N(.N)*[{a|b|rc}N][.postN+SHA]
+    where everything before .postN is obtained from the tag, the N in
+    .postN is the number of commits since the last tag and the SHA is
+    obtained via git describe. This later portion is only shown if the
+    commit count since the last tag is non zero. Instead of '.post', an
+    alternate valid prefix such as '.rev', '_rev', '_r' or '.r' may be
+    supplied."""
+
+    def __init__(self, release=None, fpath=None, commit=None, reponame=None,
+                 commit_count_prefix='.post', archive_commit=None, **kwargs):
         """
         :release:      Release tuple (corresponding to the current VCS tag)
         :commit        Short SHA. Set to '$Format:%h$' for git archive support.
         :fpath:        Set to ``__file__`` to access version control 
information
         :reponame:     Used to verify VCS repository name.
-        :commit_count  Commits since last release. Set for dev releases.
         """
         self.fpath = fpath
         self._expected_commit = commit
+
+        if release is not None or 'commit_count' in kwargs:
+            print('WARNING: param.Version now supports PEP440 and a new tag 
based workflow. See param/version.py for more details')
+
         self.expected_release = release
 
-        self._commit = None if commit in [None, "$Format:%h$"] else commit
-        self._commit_count = commit_count
+        self._commit = None if (commit is None or 
commit.startswith("$Format")) else commit
+        self._commit_count = None
         self._release = None
         self._dirty = False
+        self._prerelease = None
+
+        self.archive_commit= archive_commit
+
         self.reponame = reponame
+        self.commit_count_prefix = commit_count_prefix
+
+    @property
+    def prerelease(self):
+        """
+        Either None or one of 'aN' (alpha), 'bN' (beta) or 'rcN'
+        (release candidate) where N is an integer.
+        """
+        return self.fetch()._prerelease
 
     @property
     def release(self):
@@ -188,37 +257,103 @@
         return self
 
 
-    def git_fetch(self, cmd='git'):
+    def git_fetch(self, cmd='git', as_string=False):
+        commit_argument = self._commit
+        output = None
         try:
             if self.reponame is not None:
                 # Verify this is the correct repository (since fpath could
-                # be an unrelated git repository, and param could just have
+                # be an unrelated git repository, and autover could just have
                 # been copied/installed into it).
                 output = run_cmd([cmd, 'remote', '-v'],
                                  cwd=os.path.dirname(self.fpath))
-                repo_matches = ['/' + self.reponame + '.git' ,
+                repo_matches = ['', # No remote set
+                                '/' + self.reponame + '.git' ,
                                 # A remote 'server:reponame.git' can also be 
referred
                                 # to (i.e. cloned) as `server:reponame`.
                                 '/' + self.reponame + ' ']
                 if not any(m in output for m in repo_matches):
                     return self
 
-            output = run_cmd([cmd, 'describe', '--long', '--match', 'v*.*', 
'--dirty'],
+            output = run_cmd([cmd, 'describe', '--long', '--match',
+                              "v[0-9]*.[0-9]*.[0-9]*", '--dirty'],
                              cwd=os.path.dirname(self.fpath))
-        except Exception as e:
-            if e.args[1] == 'fatal: No names found, cannot describe anything.':
-                raise Exception("Cannot find any git version tags of format 
v*.*")
-            # If there is any other error, return (release value still useful)
-            return self
+            if as_string: return output
+        except Exception as e1:
+            try:
+                output = self._output_from_file()
+                if output is not None:
+                    self._update_from_vcs(output)
+                if self._known_stale():
+                    self._commit_count = None
+                if as_string: return output
+
+                # If an explicit commit was supplied (e.g from git
+                # archive), it should take precedence over the file.
+                if commit_argument:
+                    self._commit = commit_argument
+                return
+
+            except IOError:
+                if e1.args[1] == 'fatal: No names found, cannot describe 
anything.':
+                    raise Exception("Cannot find any git version tags of 
format v*.*")
+                # If there is any other error, return (release value still 
useful)
+                return self
+
+        self._update_from_vcs(output)
+
+
+    def _known_stale(self):
+        """
+        The commit is known to be from a file (and therefore stale) if a
+        SHA is supplied by git archive and doesn't match the parsed commit.
+        """
+        if self._output_from_file() is None:
+            commit = None
+        else:
+            commit = self.commit
 
+        known_stale = (self.archive_commit is not None
+                       and not self.archive_commit.startswith('$Format')
+                       and self.archive_commit != commit)
+        if known_stale: self._commit_count = None
+        return known_stale
+
+    def _output_from_file(self, entry='git_describe'):
+        """
+        Read the version from a .version file that may exist alongside 
__init__.py.
+
+        This file can be generated by piping the following output to file:
+
+        git describe --long --match v*.*
+        """
+        try:
+            vfile = os.path.join(os.path.dirname(self.fpath), '.version')
+            with open(vfile, 'r') as f:
+                return json.loads(f.read()).get(entry, None)
+        except: # File may be missing if using pip + git archive
+            return None
+
+
+    def _update_from_vcs(self, output):
+        "Update state based on the VCS state e.g the output of git describe"
         split = output[1:].split('-')
-        self._release = tuple(int(el) for el in split[0].split('.'))
+        dot_split = split[0].split('.')
+        for prefix in ['a','b','rc']:
+            if prefix in dot_split[-1]:
+                prefix_split = dot_split[-1].split(prefix)
+                self._prerelease = prefix + prefix_split[-1]
+                dot_split[-1] = prefix_split[0]
+
+
+        self._release = tuple(int(el) for el in dot_split)
         self._commit_count = int(split[1])
+
         self._commit = str(split[2][1:]) # Strip out 'g' prefix ('g'=>'git')
+
         self._dirty = (split[-1]=='dirty')
         return self
 
-
     def __str__(self):
         """
         Version in x.y.z string format. Does not include the "v"
@@ -231,48 +366,49 @@
 
         (with "v" prefix removed).
         """
-        if self.release is None: return 'None'
+        known_stale = self._known_stale()
+        if self.release is None and not known_stale:
+            extracted_directory_tag = 
self._output_from_file(entry='extracted_directory_tag')
+            return 'None' if extracted_directory_tag is None else 
extracted_directory_tag
+        elif self.release is None and known_stale:
+            extracted_directory_tag = 
self._output_from_file(entry='extracted_directory_tag')
+            if extracted_directory_tag is not None:
+                return extracted_directory_tag
+            return '0.0.0+g{SHA}-gitarchive'.format(SHA=self.archive_commit)
+
         release = '.'.join(str(el) for el in self.release)
+        prerelease = '' if self.prerelease is None else self.prerelease
 
-        if (self._expected_commit is not None) and  ("$Format" not in 
self._expected_commit):
-            pass  # Concrete commit supplied - print full version string
-        elif (self.commit_count == 0 and not self.dirty):
-            return release
-
-        dirty_status = '-dirty' if self.dirty else ''
-        return '%s-%s-g%s%s' % (release, self.commit_count if 
self.commit_count else 'x',
-                                self.commit, dirty_status)
+        if self.commit_count == 0:
+            return release + prerelease
+
+        commit = self.commit
+        dirty = '-dirty' if self.dirty else ''
+        archive_commit = ''
+        if known_stale:
+            archive_commit = '-gitarchive'
+            commit = self.archive_commit
+
+        if archive_commit != '':
+            postcount = self.commit_count_prefix + '0'
+        elif self.commit_count not in [0, None]:
+            postcount = self.commit_count_prefix + str(self.commit_count)
+        else:
+            postcount = ''
+
+        components = [release, prerelease, postcount,
+                      '' if commit is None else '+g' + commit, dirty,
+                      archive_commit]
+        return ''.join(components)
 
     def __repr__(self):
         return str(self)
 
-    def abbrev(self,dev_suffix=""):
-        """
-        Abbreviated string representation, optionally declaring whether it is
-        a development version.
-        """
-        return '.'.join(str(el) for el in self.release) + \
-            (dev_suffix if self.commit_count > 0 or self.dirty else "")
-
-
-
-    def __eq__(self, other):
+    def abbrev(self):
         """
-        Two versions are considered equivalent if and only if they are
-        from the same release, with the same commit count, and are not
-        dirty.  Any dirty version is considered different from any
-        other version, since it could potentially have any arbitrary
-        changes even for the same release and commit count.
+        Abbreviated string representation of just the release number.
         """
-        if self.dirty or other.dirty: return False
-        return (self.release, self.commit_count) == (other.release, 
other.commit_count)
-
-    def __gt__(self, other):
-        return (self.release, self.commit_count) > (other.release, 
other.commit_count)
-
-    def __lt__(self, other):
-        return (self.release, self.commit_count) < (other.release, 
other.commit_count)
-
+        return '.'.join(str(el) for el in self.release)
 
     def verify(self, string_version=None):
         """
@@ -288,11 +424,106 @@
         if self.dirty:
             raise Exception("Current working directory is dirty.")
 
-        if self.release != self.expected_release:
+        if self.expected_release is not None and self.release != 
self.expected_release:
             raise Exception("Declared release does not match current release 
tag.")
 
         if self.commit_count !=0:
             raise Exception("Please update the VCS version tag before 
release.")
 
-        if self._expected_commit not in [None, "$Format:%h$"]:
+        if (self._expected_commit is not None
+            and not self._expected_commit.startswith( "$Format")):
             raise Exception("Declared release does not match the VCS version 
tag")
+
+
+
+    @classmethod
+    def get_setup_version(cls, setup_path, reponame, describe=False,
+                          dirty='raise', archive_commit=None):
+        """
+        Helper for use in setup.py to get the version from the .version file 
(if available)
+        or more up-to-date information from git describe (if available).
+
+        Assumes the __init__.py will be found in the directory
+        {reponame}/__init__.py relative to setup.py.
+
+        If describe is True, the raw string obtained from git described is
+        returned which is useful for updating the .version file.
+
+        The dirty policy can be one of 'report', 'strip', 'raise'. If it is
+        'report' the version string may end in '-dirty' if the repository is
+        in a dirty state.  If the policy is 'strip', the '-dirty' suffix
+        will be stripped out if present. If the policy is 'raise', an
+        exception is raised if the repository is in a dirty state. This can
+        be useful if you want to make sure packages are not built from a
+        dirty repository state.
+        """
+        policies = ['raise','report', 'strip']
+        if dirty not in policies:
+            raise AssertionError("get_setup_version dirty policy must be in 
%r" % policies)
+
+        fpath = os.path.join(setup_path, reponame, "__init__.py")
+        version = Version(fpath=fpath, reponame=reponame, 
archive_commit=archive_commit)
+        if describe:
+            vstring = version.git_fetch(as_string=True)
+        else:
+            vstring = str(version)
+
+        if version.dirty and dirty == 'raise':
+            raise AssertionError('Repository is in a dirty state.')
+        elif version.dirty and dirty=='strip':
+            return vstring.replace('-dirty', '')
+        else:
+            return vstring
+
+
+    @classmethod
+    def extract_directory_tag(cls, setup_path, reponame):
+        setup_dir = os.path.split(setup_path)[-1] # Directory containing 
setup.py
+        prefix = reponame + '-' # Prefix to match
+        if setup_dir.startswith(prefix):
+            tag = setup_dir[len(prefix):]
+            # Assuming the tag is a version if it isn't empty, 'master' and 
has a dot in it
+            if tag not in ['', 'master'] and ('.' in tag):
+                return tag
+        return None
+
+
+    @classmethod
+    def setup_version(cls, setup_path, reponame, archive_commit=None, 
dirty='raise'):
+        info = {}
+        git_describe = None
+        try:
+            # Will only work if in a git repo and git is available
+            git_describe  = Version.get_setup_version(setup_path,
+                                                      reponame,
+                                                      describe=True,
+                                                      dirty=dirty,
+                                                      
archive_commit=archive_commit)
+
+            if git_describe is not None:
+                info['git_describe'] = git_describe
+        except: pass
+
+        if git_describe is None:
+            extracted_directory_tag = 
Version.extract_directory_tag(setup_path, reponame)
+            if extracted_directory_tag is not None:
+                info['extracted_directory_tag'] = extracted_directory_tag
+            try:
+                with open(os.path.join(setup_path, reponame, '.version'), 'w') 
as f:
+                    
f.write(json.dumps({'extracted_directory_tag':extracted_directory_tag}))
+            except:
+                print('Error in setup_version: could not write .version file.')
+
+
+        info['version_string'] =  Version.get_setup_version(setup_path,
+                                                            reponame,
+                                                            describe=False,
+                                                            dirty=dirty,
+                                                            
archive_commit=archive_commit)
+        try:
+            with open(os.path.join(setup_path, reponame, '.version'), 'w') as 
f:
+                f.write(json.dumps(info))
+        except:
+            print('Error in setup_version: could not write .version file.')
+
+        return info['version_string']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/param.egg-info/PKG-INFO 
new/param-1.6.0/param.egg-info/PKG-INFO
--- old/param-1.5.1/param.egg-info/PKG-INFO     2017-04-26 15:48:47.000000000 
+0200
+++ new/param-1.6.0/param.egg-info/PKG-INFO     2018-04-05 12:25:08.000000000 
+0200
@@ -1,12 +1,14 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: param
-Version: 1.5.1
+Version: 1.6.0
 Summary: Declarative Python programming using Parameters.
 Home-page: http://ioam.github.com/param/
 Author: IOAM
 Author-email: develop...@topographica.org
+Maintainer: IOAM
+Maintainer-email: develop...@topographica.org
 License: BSD
-Description: |BuildStatus|_ |PyPIVersion|_ |PyVersion|_ |License|_
+Description: |LinuxTests|_ |WinTests|_ |Coverage|_ |PyPIVersion|_ |PyVersion|_ 
|License|_
         
         Param
         =====
@@ -24,8 +26,14 @@
         Please see `param's website <http://ioam.github.com/param/>`_ for
         official releases, installation instructions, documentation, and 
examples.
         
-        .. |BuildStatus| image:: 
https://travis-ci.org/ioam/param.svg?branch=master
-        .. _BuildStatus: https://travis-ci.org/ioam/param
+        .. |LinuxTests| image:: 
https://travis-ci.org/ioam/param.svg?branch=master
+        .. _LinuxTests: https://travis-ci.org/ioam/param
+        
+        .. |WinTests| image:: 
https://ci.appveyor.com/api/projects/status/huoiwwamso2or7xw/branch/master?svg=true
+        .. _WinTests: https://ci.appveyor.com/project/Ioam/param/branch/master
+        
+        .. |Coverage| image:: https://img.shields.io/coveralls/ioam/param.svg
+        .. _Coverage: https://coveralls.io/r/ioam/param?branch=master
         
         .. |PyPIVersion| image:: http://img.shields.io/pypi/v/param.svg
         .. _PyPIVersion: https://pypi.python.org/pypi/param
@@ -42,12 +50,12 @@
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Operating System :: OS Independent
 Classifier: Intended Audience :: Science/Research
 Classifier: Intended Audience :: Developers
@@ -56,3 +64,6 @@
 Classifier: Topic :: Software Development :: Libraries
 Provides: param
 Provides: numbergen
+Requires-Python: >=2.7
+Provides-Extra: tests
+Provides-Extra: all
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/param.egg-info/SOURCES.txt 
new/param-1.6.0/param.egg-info/SOURCES.txt
--- old/param-1.5.1/param.egg-info/SOURCES.txt  2017-04-26 15:48:48.000000000 
+0200
+++ new/param-1.6.0/param.egg-info/SOURCES.txt  2018-04-05 12:25:08.000000000 
+0200
@@ -4,6 +4,7 @@
 setup.cfg
 setup.py
 numbergen/__init__.py
+param/.version
 param/__init__.py
 param/ipython.py
 param/parameterized.py
@@ -11,4 +12,5 @@
 param.egg-info/PKG-INFO
 param.egg-info/SOURCES.txt
 param.egg-info/dependency_links.txt
+param.egg-info/requires.txt
 param.egg-info/top_level.txt
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/param.egg-info/requires.txt 
new/param-1.6.0/param.egg-info/requires.txt
--- old/param-1.5.1/param.egg-info/requires.txt 1970-01-01 01:00:00.000000000 
+0100
+++ new/param-1.6.0/param.egg-info/requires.txt 2018-04-05 12:25:08.000000000 
+0200
@@ -0,0 +1,8 @@
+
+[all]
+flake8
+nose
+
+[tests]
+nose
+flake8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/setup.cfg new/param-1.6.0/setup.cfg
--- old/param-1.5.1/setup.cfg   2017-04-26 15:48:48.000000000 +0200
+++ new/param-1.6.0/setup.cfg   2018-04-05 12:25:08.000000000 +0200
@@ -1,5 +1,28 @@
-[build_ext]
-inplace = 1
+[wheel]
+universal = 1
+
+[flake8]
+include = setup.py param numbergen
+exclude = .git,__pycache__,.tox,.eggs,*.egg,doc,dist,build,_build,tests
+ignore = E1,
+       E2,
+       E3,
+       E4,
+       E5,
+       E701,
+       E702,
+       E703,
+       E704,
+       E722,
+       E741,
+       E742,
+       E743,
+       W503
+
+[nosetests]
+verbosity = 2
+with-doctest = 1
+nologcapture = 1
 
 [egg_info]
 tag_build = 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/param-1.5.1/setup.py new/param-1.6.0/setup.py
--- old/param-1.5.1/setup.py    2017-04-26 15:28:11.000000000 +0200
+++ new/param-1.6.0/setup.py    2018-04-05 12:24:35.000000000 +0200
@@ -1,63 +1,71 @@
-#!/usr/bin/env python
 import os
-import sys
 
-try:
-    from setuptools import setup
-except ImportError:
-    from distutils.core import setup
-
-try:
-    # check we can compile on this machine
-    import cython; cython.inline("return 1;")
-    
-    from Cython.Build import cythonize
-    ext_modules = cythonize("param/*.py", exclude=['param/ipython.py'])
-except:
-    ext_modules = []
+from setuptools import setup
 
-setup_args = {}
 
-setup_args.update(dict(
+########## autover ##########
+
+def get_setup_version(reponame):
+    """Use autover to get up to date version."""
+    # importing self into setup.py is unorthodox, but param has no
+    # required dependencies outside of python
+    from param.version import Version
+    return 
Version.setup_version(os.path.dirname(__file__),reponame,archive_commit="$Format:%h$")
+
+
+########## dependencies ##########
+
+extras_require = {
+    # pip doesn't support tests_require
+    # (https://github.com/pypa/pip/issues/1197)
+    'tests': [
+        'nose',
+        'flake8',
+    ]
+}
+
+extras_require['all'] = sorted(set(sum(extras_require.values(), [])))
+
+
+########## metadata for setuptools ##########
+
+setup_args = dict(
     name='param',
-    version="1.5.1",
+    version=get_setup_version("param"),
     description='Declarative Python programming using Parameters.',
     long_description=open('README.rst').read() if os.path.isfile('README.rst') 
else 'Consult README.rst',
-    author= "IOAM",
-    author_email= "develop...@topographica.org",
-    ext_modules=ext_modules,
+    author="IOAM",
+    author_email="develop...@topographica.org",
     maintainer="IOAM",
     maintainer_email="develop...@topographica.org",
     platforms=['Windows', 'Mac OS X', 'Linux'],
     license='BSD',
     url='http://ioam.github.com/param/',
-    packages = ["param","numbergen"],
-    provides = ["param","numbergen"],
-    classifiers = [
+    packages=["param","numbergen"],
+    provides=["param","numbergen"],
+    include_package_data = True,
+    python_requires=">=2.7",
+    install_requires=[],
+    extras_require=extras_require,
+    tests_require=extras_require['tests'],
+    classifiers=[
         "License :: OSI Approved :: BSD License",
         "Development Status :: 5 - Production/Stable",
         "Programming Language :: Python :: 2",
-        "Programming Language :: Python :: 2.6",
         "Programming Language :: Python :: 2.7",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.2",
         "Programming Language :: Python :: 3.3",
         "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
+        "Programming Language :: Python :: 3.6",
         "Operating System :: OS Independent",
         "Intended Audience :: Science/Research",
         "Intended Audience :: Developers",
         "Natural Language :: English",
         "Topic :: Scientific/Engineering",
         "Topic :: Software Development :: Libraries"]
-))
-
+)
 
 
 if __name__=="__main__":
-
-    if ('upload' in sys.argv) or ('sdist' in sys.argv):
-        import param, numbergen
-        param.__version__.verify(setup_args['version'])
-        numbergen.__version__.verify(setup_args['version'])
-
     setup(**setup_args)


Reply via email to