openSUSE Commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
May 2019
- 1 participants
- 2232 discussions
Hello community,
here is the log from the commit of package python-django-nine for openSUSE:Factory checked in at 2019-05-22 15:41:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-nine (Old)
and /work/SRC/openSUSE:Factory/.python-django-nine.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-nine"
Wed May 22 15:41:19 2019 rev:2 rq:704708 version:0.2.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-django-nine/python-django-nine.changes 2019-05-22 11:03:49.646612957 +0200
+++ /work/SRC/openSUSE:Factory/.python-django-nine.new.5148/python-django-nine.changes 2019-05-22 15:42:06.850427035 +0200
@@ -1,0 +2,19 @@
+Wed May 22 10:47:49 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 0.2.2:
+ * Fixes in backwards compatibility
+ * Bring back the user compatibility module. However, it's deprecated and
+ will be removed in version 0.3
+ * Show deprecation warnings
+
+-------------------------------------------------------------------
+Fri May 17 10:34:46 UTC 2019 - John Vandenberg <jayvdb(a)gmail.com>
+
+- Removed Conflicts with python-nine
+- Update to v0.2
+ * Drop Python 2.6 support.
+ * Change namespace from `nine` to `django_nine`.
+ * Removed `user` compatibility module.
+ * Add travis.
+
+-------------------------------------------------------------------
Old:
----
django-nine-0.1.13.tar.gz
New:
----
django-nine-0.2.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-django-nine.spec ++++++
--- /var/tmp/diff_new_pack.ZGylVV/_old 2019-05-22 15:42:08.134427029 +0200
+++ /var/tmp/diff_new_pack.ZGylVV/_new 2019-05-22 15:42:08.134427029 +0200
@@ -12,26 +12,25 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
+#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-django-nine
-Version: 0.1.13
+Version: 0.2.2
Release: 0
-License: GPL-2.0 or LGPL-2.1-or-later
Summary: Compatibility library for Django
-Url: https://github.com/barseghyanartur/django-nine/
+License: GPL-2.0-only OR LGPL-2.1-or-later
Group: Development/Languages/Python
+Url: https://github.com/barseghyanartur/django-nine/
Source: https://files.pythonhosted.org/packages/source/d/django-nine/django-nine-%{…
-BuildRequires: python-rpm-macros
BuildRequires: %{python_module setuptools}
+BuildRequires: python-rpm-macros
# SECTION test requirements
BuildRequires: %{python_module Django}
BuildRequires: %{python_module mock}
BuildRequires: %{python_module pytest-django}
-# https://github.com/barseghyanartur/django-nine/issues/2
-Conflicts: python-nine
# /SECTION
BuildRequires: fdupes
BuildArch: noarch
@@ -39,23 +38,26 @@
%python_subpackages
%description
-Compatibility library for Django.
+Version checking library for Django.
%prep
%setup -q -n django-nine-%{version}
chmod a-x LICENSE_* CHANGELOG.rst README.rst
+# Remove backwards compatibility layer
+rm src/nine/__init__.py
+
%build
%python_build
%install
%python_install
-%{python_expand rm -r %{buildroot}%{$python_sitelib}/nine/tests/
+%{python_expand rm -r %{buildroot}%{$python_sitelib}/django_nine/tests/
%fdupes %{buildroot}%{$python_sitelib}
}
%check
-%pytest src/nine/tests/
+%pytest src/django_nine/tests/
%files %{python_files}
%doc CHANGELOG.rst README.rst
++++++ django-nine-0.1.13.tar.gz -> django-nine-0.2.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/CHANGELOG.rst new/django-nine-0.2.2/CHANGELOG.rst
--- old/django-nine-0.1.13/CHANGELOG.rst 2017-05-16 22:25:32.000000000 +0200
+++ new/django-nine-0.2.2/CHANGELOG.rst 2019-05-19 19:15:10.000000000 +0200
@@ -15,6 +15,34 @@
0.3.2 to 0.4).
- All backwards incompatible changes are mentioned in this document.
+0.2.2
+---
+2019-05-18
+
+- Bring back the `user` compatibility module. However, it's deprecated and
+ will be removed in version 0.3.
+- Show deprecation warnings.
+
+0.2.1
+---
+2019-05-18
+
+- Fixes in backwards compatibility.
+
+0.2
+---
+2019-05-17
+
+.. note::
+
+ This release is still backwards-compatible with previous versions (0.1.x),
+ but next versions (0.3.x) would not be.
+
+- Drop Python 2.6 support.
+- Change namespace from `nine` to `django_nine`.
+- Removed `user` compatibility module. Implement your own if you need.
+- Add travis.
+
0.1.13
------
2017-05-16
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/LICENSE_GPL2.0.txt new/django-nine-0.2.2/LICENSE_GPL2.0.txt
--- old/django-nine-0.1.13/LICENSE_GPL2.0.txt 2017-02-09 22:54:43.000000000 +0100
+++ new/django-nine-0.2.2/LICENSE_GPL2.0.txt 2019-05-16 23:10:20.000000000 +0200
@@ -291,7 +291,7 @@
the "copyright" line and a pointer to where the full notice is found.
django-nine - compatibility library for Django.
- Copyright (C) 2015-2017 Artur Barseghyan
+ Copyright (C) 2015-2019 Artur Barseghyan
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/LICENSE_LGPL_2.1.txt new/django-nine-0.2.2/LICENSE_LGPL_2.1.txt
--- old/django-nine-0.1.13/LICENSE_LGPL_2.1.txt 2017-02-09 22:54:43.000000000 +0100
+++ new/django-nine-0.2.2/LICENSE_LGPL_2.1.txt 2019-05-16 23:10:20.000000000 +0200
@@ -471,7 +471,7 @@
"copyright" line and a pointer to where the full notice is found.
django-nine - compatibility library for Django.
- Copyright (C) 2015-2017 Artur Barseghyan
+ Copyright (C) 2015-2019 Artur Barseghyan
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/PKG-INFO new/django-nine-0.2.2/PKG-INFO
--- old/django-nine-0.1.13/PKG-INFO 2017-05-16 22:28:17.000000000 +0200
+++ new/django-nine-0.2.2/PKG-INFO 2019-05-19 19:16:50.000000000 +0200
@@ -1,20 +1,32 @@
Metadata-Version: 1.1
Name: django-nine
-Version: 0.1.13
-Summary: Compatibility library for Django.
+Version: 0.2.2
+Summary: Version checking library.
Home-page: https://github.com/barseghyanartur/django-nine/
Author: Artur Barseghyan
Author-email: artur.barseghyan(a)gmail.com
-License: GPL 2.0/LGPL 2.1
+License: GPL-2.0-only OR LGPL-2.1-or-later
Description: ===========
django-nine
===========
- `django-nine` - compatibility library for Django.
+ `django-nine` - version checking library for Django.
+
+ .. image:: https://img.shields.io/pypi/v/django-nine.svg
+ :target: https://pypi.python.org/pypi/django-nine
+ :alt: PyPI Version
+
+ .. image:: https://img.shields.io/travis/barseghyanartur/django-nine/master.svg
+ :target: http://travis-ci.org/barseghyanartur/django-nine
+ :alt: Build Status
+
+ .. image:: https://img.shields.io/badge/license-GPL--2.0--only%20OR%20LGPL--2.1--or--l…
+ :target: https://github.com/barseghyanartur/django-nine/#License
+ :alt: GPL-2.0-only OR LGPL-2.1-or-later
Prerequisites
=============
- - Python 2.6, 2.7, 3.4, 3.5 and 3.6.
- - Django 1.5, 1.6, 1.7, 1.8, 1.9, 1.10 and 1.11.
+ - Python 2.6, 2.7, 3.4, 3.5, 3.6 and 3.7.
+ - Django 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 2.0, 2.1 and 2.2.
Installation
============
@@ -47,7 +59,7 @@
.. code-block:: python
- from nine import versions
+ from django_nine import versions
versions.DJANGO_1_7 # True
versions.DJANGO_LTE_1_7 # True
@@ -65,21 +77,13 @@
.. code-block:: python
TEMPLATES[0]['OPTIONS']['context_processors'] += \
- ['nine.context_processors.versions']
+ ['django_nine.context_processors.versions']
Or if you are using an old version of Django:
.. code-block:: python
- TEMPLATE_CONTEXT_PROCESSORS += ['nine.context_processors.versions']
-
- Import User model
- -----------------
- Or you could safely import the user model as follows:
-
- .. code-block:: python
-
- from nine.user import User
+ TEMPLATE_CONTEXT_PROCESSORS += ['django_nine.context_processors.versions']
Testing
=======
@@ -99,7 +103,7 @@
.. code-block:: sh
- tox -e py35
+ tox -e py37
Or run Django tests:
@@ -109,7 +113,7 @@
License
=======
- GPL 2.0/LGPL 2.1
+ GPL-2.0-only OR LGPL-2.1-or-later
Support
=======
@@ -128,6 +132,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: Environment :: Web Environment
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/README.rst new/django-nine-0.2.2/README.rst
--- old/django-nine-0.1.13/README.rst 2017-05-16 22:24:55.000000000 +0200
+++ new/django-nine-0.2.2/README.rst 2019-05-16 23:10:20.000000000 +0200
@@ -1,12 +1,24 @@
===========
django-nine
===========
-`django-nine` - compatibility library for Django.
+`django-nine` - version checking library for Django.
+
+.. image:: https://img.shields.io/pypi/v/django-nine.svg
+ :target: https://pypi.python.org/pypi/django-nine
+ :alt: PyPI Version
+
+.. image:: https://img.shields.io/travis/barseghyanartur/django-nine/master.svg
+ :target: http://travis-ci.org/barseghyanartur/django-nine
+ :alt: Build Status
+
+.. image:: https://img.shields.io/badge/license-GPL--2.0--only%20OR%20LGPL--2.1--or--l…
+ :target: https://github.com/barseghyanartur/django-nine/#License
+ :alt: GPL-2.0-only OR LGPL-2.1-or-later
Prerequisites
=============
-- Python 2.6, 2.7, 3.4, 3.5 and 3.6.
-- Django 1.5, 1.6, 1.7, 1.8, 1.9, 1.10 and 1.11.
+- Python 2.6, 2.7, 3.4, 3.5, 3.6 and 3.7.
+- Django 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 2.0, 2.1 and 2.2.
Installation
============
@@ -39,7 +51,7 @@
.. code-block:: python
- from nine import versions
+ from django_nine import versions
versions.DJANGO_1_7 # True
versions.DJANGO_LTE_1_7 # True
@@ -57,21 +69,13 @@
.. code-block:: python
TEMPLATES[0]['OPTIONS']['context_processors'] += \
- ['nine.context_processors.versions']
+ ['django_nine.context_processors.versions']
Or if you are using an old version of Django:
.. code-block:: python
- TEMPLATE_CONTEXT_PROCESSORS += ['nine.context_processors.versions']
-
-Import User model
------------------
-Or you could safely import the user model as follows:
-
-.. code-block:: python
-
- from nine.user import User
+ TEMPLATE_CONTEXT_PROCESSORS += ['django_nine.context_processors.versions']
Testing
=======
@@ -91,7 +95,7 @@
.. code-block:: sh
- tox -e py35
+ tox -e py37
Or run Django tests:
@@ -101,7 +105,7 @@
License
=======
-GPL 2.0/LGPL 2.1
+GPL-2.0-only OR LGPL-2.1-or-later
Support
=======
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/setup.cfg new/django-nine-0.2.2/setup.cfg
--- old/django-nine-0.1.13/setup.cfg 2017-05-16 22:28:17.000000000 +0200
+++ new/django-nine-0.2.2/setup.cfg 2019-05-19 19:16:50.000000000 +0200
@@ -4,5 +4,4 @@
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/setup.py new/django-nine-0.2.2/setup.py
--- old/django-nine-0.1.13/setup.py 2017-05-16 22:25:40.000000000 +0200
+++ new/django-nine-0.2.2/setup.py 2019-05-19 19:15:17.000000000 +0200
@@ -7,7 +7,7 @@
except:
readme = ''
-version = '0.1.13'
+version = '0.2.2'
install_requires = [
#'Django',
@@ -32,7 +32,7 @@
setup(
name='django-nine',
version=version,
- description="Compatibility library for Django.",
+ description="Version checking library.",
long_description="{0}".format(readme),
classifiers=[
"Programming Language :: Python :: 2.6",
@@ -42,6 +42,7 @@
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
"Environment :: Web Environment",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
"License :: OSI Approved :: GNU Lesser General Public License v2 or "
@@ -57,7 +58,7 @@
url='https://github.com/barseghyanartur/django-nine/',
package_dir={'': 'src'},
packages=find_packages(where='./src'),
- license='GPL 2.0/LGPL 2.1',
+ license='GPL-2.0-only OR LGPL-2.1-or-later',
install_requires=install_requires,
tests_require=tests_require,
package_data={},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine/__init__.py new/django-nine-0.2.2/src/django_nine/__init__.py
--- old/django-nine-0.1.13/src/django_nine/__init__.py 1970-01-01 01:00:00.000000000 +0100
+++ new/django-nine-0.2.2/src/django_nine/__init__.py 2019-05-19 19:09:28.000000000 +0200
@@ -0,0 +1,5 @@
+__title__ = 'django_nine'
+__version__ = '0.2.2'
+__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
+__copyright__ = '2015-2019 Artur Barseghyan'
+__license__ = 'GPL-2.0-only OR LGPL-2.1-or-later'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine/context_processors.py new/django-nine-0.2.2/src/django_nine/context_processors.py
--- old/django-nine-0.1.13/src/django_nine/context_processors.py 1970-01-01 01:00:00.000000000 +0100
+++ new/django-nine-0.2.2/src/django_nine/context_processors.py 2019-05-16 23:10:20.000000000 +0200
@@ -0,0 +1,18 @@
+from django_nine import versions as nine_versions
+
+__title__ = 'django_nine.versions'
+__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
+__copyright__ = '2015-2019 Artur Barseghyan'
+__license__ = 'GPL-2.0-only OR LGPL-2.1-or-later'
+__all__ = [
+ 'versions',
+]
+
+
+def versions(request):
+ """Get active theme.
+
+ :param django.http.HttpRequest request:
+ :return dict:
+ """
+ return {'VERSIONS': nine_versions}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine/tests/__init__.py new/django-nine-0.2.2/src/django_nine/tests/__init__.py
--- old/django-nine-0.1.13/src/django_nine/tests/__init__.py 1970-01-01 01:00:00.000000000 +0100
+++ new/django-nine-0.2.2/src/django_nine/tests/__init__.py 2019-05-16 23:10:20.000000000 +0200
@@ -0,0 +1 @@
+from .test_versions import *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine/tests/base.py new/django-nine-0.2.2/src/django_nine/tests/base.py
--- old/django-nine-0.1.13/src/django_nine/tests/base.py 1970-01-01 01:00:00.000000000 +0100
+++ new/django-nine-0.2.2/src/django_nine/tests/base.py 2019-05-16 23:10:20.000000000 +0200
@@ -0,0 +1,36 @@
+import logging
+
+__title__ = 'django_nine.tests.base'
+__author__ = 'Artur Barseghyan'
+__copyright__ = '2015-2019 Artur Barseghyan'
+__license__ = 'GPL-2.0-only OR LGPL-2.1-or-later'
+__all__ = (
+ 'LOG_INFO',
+ 'log_info',
+)
+
+
+logger = logging.getLogger(__name__)
+
+LOG_INFO = True
+
+
+def log_info(func):
+ """Logs some useful info."""
+ if not LOG_INFO:
+ return func
+
+ def inner(self, *args, **kwargs):
+ result = func(self, *args, **kwargs)
+
+ logger.info('\n\n%s' % func.__name__)
+ logger.info('============================')
+ if func.__doc__:
+ logger.info('""" %s """' % func.__doc__.strip())
+ logger.info('----------------------------')
+ if result is not None:
+ logger.info(result)
+ logger.info('\n++++++++++++++++++++++++++++')
+
+ return result
+ return inner
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine/tests/test_versions.py new/django-nine-0.2.2/src/django_nine/tests/test_versions.py
--- old/django-nine-0.1.13/src/django_nine/tests/test_versions.py 1970-01-01 01:00:00.000000000 +0100
+++ new/django-nine-0.2.2/src/django_nine/tests/test_versions.py 2019-05-16 23:10:20.000000000 +0200
@@ -0,0 +1,233 @@
+import unittest
+import mock
+# For Python3 >= 3.4
+try:
+ from importlib import reload
+# For Python3 < 3.4
+except ImportError as err:
+ try:
+ from imp import reload
+ except ImportError as err:
+ pass
+
+import django
+
+from .base import log_info
+
+__title__ = 'django_nine.tests.test_versions'
+__author__ = 'Artur Barseghyan'
+__copyright__ = 'Copyright (c) 2015 Artur Barseghyan'
+__license__ = 'GPL-2.0-only OR LGPL-2.1-or-later'
+__all__ = ('VersionsTest',)
+
+
+class VersionsTest(unittest.TestCase):
+ """
+ Tests of ``django_nine.versions`` module.
+ """
+ def setUp(self):
+ pass
+
+ @log_info
+ @mock.patch('django.get_version', mock.MagicMock(return_value='1.4.21'))
+ def test_django_1_4_21(self):
+ """
+ Tests as if we were using Django==1.4.21.
+ """
+ from django_nine import versions
+ reload(versions)
+
+ # Exact version matching
+ self.assertTrue(versions.DJANGO_1_4)
+ self.assertTrue(not versions.DJANGO_1_5)
+ self.assertTrue(not versions.DJANGO_1_6)
+ self.assertTrue(not versions.DJANGO_1_7)
+ self.assertTrue(not versions.DJANGO_1_8)
+ self.assertTrue(not versions.DJANGO_1_9)
+
+ # Less than or equal matching
+ self.assertTrue(versions.DJANGO_LTE_1_4)
+ self.assertTrue(versions.DJANGO_LTE_1_5)
+ self.assertTrue(versions.DJANGO_LTE_1_6)
+ self.assertTrue(versions.DJANGO_LTE_1_7)
+ self.assertTrue(versions.DJANGO_LTE_1_8)
+ self.assertTrue(versions.DJANGO_LTE_1_9)
+
+ # Greater than or equal matching
+ self.assertTrue(versions.DJANGO_GTE_1_4)
+ self.assertTrue(not versions.DJANGO_GTE_1_5)
+ self.assertTrue(not versions.DJANGO_GTE_1_6)
+ self.assertTrue(not versions.DJANGO_GTE_1_7)
+ self.assertTrue(not versions.DJANGO_GTE_1_8)
+ self.assertTrue(not versions.DJANGO_GTE_1_9)
+
+ @log_info
+ @mock.patch('django.get_version', mock.MagicMock(return_value='1.5.5'))
+ def test_django_1_5_5(self):
+ """
+ Tests as if we were using Django==1.5.5.
+ """
+ from django_nine import versions
+ reload(versions)
+
+ # Exact version matching
+ self.assertTrue(not versions.DJANGO_1_4)
+ self.assertTrue(versions.DJANGO_1_5)
+ self.assertTrue(not versions.DJANGO_1_6)
+ self.assertTrue(not versions.DJANGO_1_7)
+ self.assertTrue(not versions.DJANGO_1_8)
+ self.assertTrue(not versions.DJANGO_1_9)
+
+ # Less than or equal matching
+ self.assertTrue(not versions.DJANGO_LTE_1_4)
+ self.assertTrue(versions.DJANGO_LTE_1_5)
+ self.assertTrue(versions.DJANGO_LTE_1_6)
+ self.assertTrue(versions.DJANGO_LTE_1_7)
+ self.assertTrue(versions.DJANGO_LTE_1_8)
+ self.assertTrue(versions.DJANGO_LTE_1_9)
+
+ # Greater than or equal matching
+ self.assertTrue(versions.DJANGO_GTE_1_4)
+ self.assertTrue(versions.DJANGO_GTE_1_5)
+ self.assertTrue(not versions.DJANGO_GTE_1_6)
+ self.assertTrue(not versions.DJANGO_GTE_1_7)
+ self.assertTrue(not versions.DJANGO_GTE_1_8)
+ self.assertTrue(not versions.DJANGO_GTE_1_9)
+
+ @log_info
+ @mock.patch('django.get_version', mock.MagicMock(return_value='1.6.5'))
+ def test_django_1_6_5(self):
+ """
+ Tests as if we were using Django==1.6.5.
+ """
+ from django_nine import versions
+ reload(versions)
+
+ # Exact version matching
+ self.assertTrue(not versions.DJANGO_1_4)
+ self.assertTrue(not versions.DJANGO_1_5)
+ self.assertTrue(versions.DJANGO_1_6)
+ self.assertTrue(not versions.DJANGO_1_7)
+ self.assertTrue(not versions.DJANGO_1_8)
+ self.assertTrue(not versions.DJANGO_1_9)
+
+ # Less than or equal matching
+ self.assertTrue(not versions.DJANGO_LTE_1_4)
+ self.assertTrue(not versions.DJANGO_LTE_1_5)
+ self.assertTrue(versions.DJANGO_LTE_1_6)
+ self.assertTrue(versions.DJANGO_LTE_1_7)
+ self.assertTrue(versions.DJANGO_LTE_1_8)
+ self.assertTrue(versions.DJANGO_LTE_1_9)
+
+ # Greater than or equal matching
+ self.assertTrue(versions.DJANGO_GTE_1_4)
+ self.assertTrue(versions.DJANGO_GTE_1_5)
+ self.assertTrue(versions.DJANGO_GTE_1_6)
+ self.assertTrue(not versions.DJANGO_GTE_1_7)
+ self.assertTrue(not versions.DJANGO_GTE_1_8)
+ self.assertTrue(not versions.DJANGO_GTE_1_9)
+
+ @log_info
+ @mock.patch('django.get_version', mock.MagicMock(return_value='1.7.5'))
+ def test_django_1_7_5(self):
+ """
+ Tests as if we were using Django==1.7.5.
+ """
+ from django_nine import versions
+ reload(versions)
+
+ # Exact version matching
+ self.assertTrue(not versions.DJANGO_1_4)
+ self.assertTrue(not versions.DJANGO_1_5)
+ self.assertTrue(not versions.DJANGO_1_6)
+ self.assertTrue(versions.DJANGO_1_7)
+ self.assertTrue(not versions.DJANGO_1_8)
+ self.assertTrue(not versions.DJANGO_1_9)
+
+ # Less than or equal matching
+ self.assertTrue(not versions.DJANGO_LTE_1_4)
+ self.assertTrue(not versions.DJANGO_LTE_1_5)
+ self.assertTrue(not versions.DJANGO_LTE_1_6)
+ self.assertTrue(versions.DJANGO_LTE_1_7)
+ self.assertTrue(versions.DJANGO_LTE_1_8)
+ self.assertTrue(versions.DJANGO_LTE_1_9)
+
+ # Greater than or equal matching
+ self.assertTrue(versions.DJANGO_GTE_1_4)
+ self.assertTrue(versions.DJANGO_GTE_1_5)
+ self.assertTrue(versions.DJANGO_GTE_1_6)
+ self.assertTrue(versions.DJANGO_GTE_1_7)
+ self.assertTrue(not versions.DJANGO_GTE_1_8)
+ self.assertTrue(not versions.DJANGO_GTE_1_9)
+
+ @log_info
+ @mock.patch('django.get_version', mock.MagicMock(return_value='1.8.a1'))
+ def test_django_1_8_a1(self):
+ """
+ Tests as if we were using Django==1.8.a1.
+ """
+ from django_nine import versions
+ reload(versions)
+
+ # Exact version matching
+ self.assertTrue(not versions.DJANGO_1_4)
+ self.assertTrue(not versions.DJANGO_1_5)
+ self.assertTrue(not versions.DJANGO_1_6)
+ self.assertTrue(not versions.DJANGO_1_7)
+ self.assertTrue(versions.DJANGO_1_8)
+ self.assertTrue(not versions.DJANGO_1_9)
+
+ # Less than or equal matching
+ self.assertTrue(not versions.DJANGO_LTE_1_4)
+ self.assertTrue(not versions.DJANGO_LTE_1_5)
+ self.assertTrue(not versions.DJANGO_LTE_1_6)
+ self.assertTrue(not versions.DJANGO_LTE_1_7)
+ self.assertTrue(versions.DJANGO_LTE_1_8)
+ self.assertTrue(versions.DJANGO_LTE_1_9)
+
+ # Greater than or equal matching
+ self.assertTrue(versions.DJANGO_GTE_1_4)
+ self.assertTrue(versions.DJANGO_GTE_1_5)
+ self.assertTrue(versions.DJANGO_GTE_1_6)
+ self.assertTrue(versions.DJANGO_GTE_1_7)
+ self.assertTrue(versions.DJANGO_GTE_1_8)
+ self.assertTrue(not versions.DJANGO_GTE_1_9)
+
+ @log_info
+ @mock.patch('django.get_version', mock.MagicMock(return_value='1.10'))
+ def test_django_1_10(self):
+ """
+ Tests as if we were using Django==1.10.
+ """
+ from django_nine import versions
+ reload(versions)
+
+ # Exact version matching
+ self.assertTrue(not versions.DJANGO_1_4)
+ self.assertTrue(not versions.DJANGO_1_5)
+ self.assertTrue(not versions.DJANGO_1_6)
+ self.assertTrue(not versions.DJANGO_1_7)
+ self.assertTrue(not versions.DJANGO_1_8)
+ self.assertTrue(not versions.DJANGO_1_9)
+ self.assertTrue(versions.DJANGO_1_10)
+
+ # Less than or equal matching
+ self.assertTrue(not versions.DJANGO_LTE_1_4)
+ self.assertTrue(not versions.DJANGO_LTE_1_5)
+ self.assertTrue(not versions.DJANGO_LTE_1_6)
+ self.assertTrue(not versions.DJANGO_LTE_1_7)
+ self.assertTrue(not versions.DJANGO_LTE_1_8)
+ self.assertTrue(not versions.DJANGO_LTE_1_9)
+
+ # Greater than or equal matching
+ self.assertTrue(versions.DJANGO_GTE_1_4)
+ self.assertTrue(versions.DJANGO_GTE_1_5)
+ self.assertTrue(versions.DJANGO_GTE_1_6)
+ self.assertTrue(versions.DJANGO_GTE_1_7)
+ self.assertTrue(versions.DJANGO_GTE_1_8)
+ self.assertTrue(versions.DJANGO_GTE_1_9)
+ self.assertTrue(versions.DJANGO_GTE_1_10)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine/user.py new/django-nine-0.2.2/src/django_nine/user.py
--- old/django-nine-0.1.13/src/django_nine/user.py 1970-01-01 01:00:00.000000000 +0100
+++ new/django-nine-0.2.2/src/django_nine/user.py 2019-05-19 19:13:56.000000000 +0200
@@ -0,0 +1,51 @@
+"""
+Compatibility module for safe and sane User model import.
+"""
+
+import importlib
+import warnings
+
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+
+from .versions import DJANGO_LTE_1_4, DJANGO_LTE_1_6, DJANGO_GTE_1_7
+
+if DJANGO_LTE_1_4:
+ from django.contrib.auth.models import User
+else:
+ # Cannot use contrib.auth.get_user_model() at compile time.
+ user_app_name, user_model_name = settings.AUTH_USER_MODEL.rsplit('.', 1)
+ User = None
+
+ if DJANGO_LTE_1_6:
+ for app in settings.INSTALLED_APPS:
+ if app.endswith(user_app_name):
+ user_app_models = importlib.import_module(app + ".models")
+ User = getattr(user_app_models, user_model_name)
+ break
+ elif DJANGO_GTE_1_7:
+ from django.apps import apps
+ try:
+ User = apps.get_registered_model(user_app_name, user_model_name)
+ except KeyError:
+ pass
+
+ if User is None:
+ raise ImproperlyConfigured(
+ "You have defined a custom user model {0}, but the app {1} is "
+ "not in ``settings.INSTALLED_APPS``"
+ "".format(settings.AUTH_USER_MODEL, user_app_name)
+ )
+
+__title__ = 'nine.user'
+__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
+__copyright__ = 'Copyright (c) 2015-2017 Artur Barseghyan'
+__license__ = 'GPL 2.0/LGPL 2.1'
+__all__ = ('User',)
+
+
+warnings.warn(
+ "The `django_nine.user` module is deprecated and will be removed in "
+ "version 0.3.",
+ DeprecationWarning
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine/versions.py new/django-nine-0.2.2/src/django_nine/versions.py
--- old/django-nine-0.1.13/src/django_nine/versions.py 1970-01-01 01:00:00.000000000 +0100
+++ new/django-nine-0.2.2/src/django_nine/versions.py 2019-05-16 23:10:20.000000000 +0200
@@ -0,0 +1,81 @@
+"""
+Contains information about the current Django version in use, including (LTE
+and GTE).
+"""
+
+from distutils.version import LooseVersion
+
+import django
+
+__title__ = 'django_nine.versions'
+__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
+__copyright__ = '2015-2019 Artur Barseghyan'
+__license__ = 'GPL-2.0-only OR LGPL-2.1-or-later'
+__all__ = [
+ 'LOOSE_DJANGO_VERSION', 'LOOSE_DJANGO_MINOR_VERSION',
+]
+
+LOOSE_DJANGO_VERSION = LooseVersion(django.get_version())
+LOOSE_DJANGO_MINOR_VERSION = LooseVersion(
+ '.'.join([str(i) for i in LOOSE_DJANGO_VERSION.version[0:2]])
+)
+
+# Loose versions
+LOOSE_VERSIONS = (
+ '1.4', '1.5', '1.6', '1.7', '1.8', '1.9', '1.10', '1.11', '2.0', '2.1',
+ '2.2', '3.0'
+)
+
+for v in LOOSE_VERSIONS:
+ var_name = 'LOOSE_VERSION_{0}'.format(v.replace('.', '_'))
+ globals()[var_name] = LooseVersion(v)
+ __all__.append(var_name)
+
+# Exact versions
+EXACT_VERSIONS = LOOSE_VERSIONS[:-1]
+
+for i, v in enumerate(EXACT_VERSIONS):
+ l_cur = globals()['LOOSE_VERSION_{0}'
+ ''.format(LOOSE_VERSIONS[i].replace('.', '_'))]
+ l_nxt = globals()['LOOSE_VERSION_{0}'
+ ''.format(LOOSE_VERSIONS[i+1].replace('.', '_'))]
+ var_name = 'DJANGO_{0}'.format(v.replace('.', '_'))
+ globals()[var_name] = (l_cur <= LOOSE_DJANGO_VERSION < l_nxt)
+ __all__.append(var_name)
+
+# LTE list
+LTE_VERSIONS = LOOSE_VERSIONS[:-1]
+
+for i, v in enumerate(EXACT_VERSIONS):
+ l_cur = globals()['LOOSE_VERSION_{0}'
+ ''.format(LOOSE_VERSIONS[i].replace('.', '_'))]
+ var_name = 'DJANGO_LTE_{0}'.format(v.replace('.', '_'))
+ globals()[var_name] = (LOOSE_DJANGO_MINOR_VERSION <= l_cur)
+ __all__.append(var_name)
+
+# GTE list
+GTE_VERSIONS = LOOSE_VERSIONS[:-1]
+
+for i, v in enumerate(EXACT_VERSIONS):
+ l_cur = globals()['LOOSE_VERSION_{0}'
+ ''.format(LOOSE_VERSIONS[i].replace('.', '_'))]
+ var_name = 'DJANGO_GTE_{0}'.format(v.replace('.', '_'))
+ globals()[var_name] = (
+ LOOSE_DJANGO_MINOR_VERSION >= l_cur
+ )
+ __all__.append(var_name)
+
+__all__ = tuple(__all__)
+
+# Clean up
+try:
+ del l_cur
+ del l_nxt
+ del var_name
+ del i
+ del v
+except NameError:
+ pass
+
+del LooseVersion
+del django
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine.egg-info/PKG-INFO new/django-nine-0.2.2/src/django_nine.egg-info/PKG-INFO
--- old/django-nine-0.1.13/src/django_nine.egg-info/PKG-INFO 2017-05-16 22:28:17.000000000 +0200
+++ new/django-nine-0.2.2/src/django_nine.egg-info/PKG-INFO 2019-05-19 19:16:50.000000000 +0200
@@ -1,20 +1,32 @@
Metadata-Version: 1.1
Name: django-nine
-Version: 0.1.13
-Summary: Compatibility library for Django.
+Version: 0.2.2
+Summary: Version checking library.
Home-page: https://github.com/barseghyanartur/django-nine/
Author: Artur Barseghyan
Author-email: artur.barseghyan(a)gmail.com
-License: GPL 2.0/LGPL 2.1
+License: GPL-2.0-only OR LGPL-2.1-or-later
Description: ===========
django-nine
===========
- `django-nine` - compatibility library for Django.
+ `django-nine` - version checking library for Django.
+
+ .. image:: https://img.shields.io/pypi/v/django-nine.svg
+ :target: https://pypi.python.org/pypi/django-nine
+ :alt: PyPI Version
+
+ .. image:: https://img.shields.io/travis/barseghyanartur/django-nine/master.svg
+ :target: http://travis-ci.org/barseghyanartur/django-nine
+ :alt: Build Status
+
+ .. image:: https://img.shields.io/badge/license-GPL--2.0--only%20OR%20LGPL--2.1--or--l…
+ :target: https://github.com/barseghyanartur/django-nine/#License
+ :alt: GPL-2.0-only OR LGPL-2.1-or-later
Prerequisites
=============
- - Python 2.6, 2.7, 3.4, 3.5 and 3.6.
- - Django 1.5, 1.6, 1.7, 1.8, 1.9, 1.10 and 1.11.
+ - Python 2.6, 2.7, 3.4, 3.5, 3.6 and 3.7.
+ - Django 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 2.0, 2.1 and 2.2.
Installation
============
@@ -47,7 +59,7 @@
.. code-block:: python
- from nine import versions
+ from django_nine import versions
versions.DJANGO_1_7 # True
versions.DJANGO_LTE_1_7 # True
@@ -65,21 +77,13 @@
.. code-block:: python
TEMPLATES[0]['OPTIONS']['context_processors'] += \
- ['nine.context_processors.versions']
+ ['django_nine.context_processors.versions']
Or if you are using an old version of Django:
.. code-block:: python
- TEMPLATE_CONTEXT_PROCESSORS += ['nine.context_processors.versions']
-
- Import User model
- -----------------
- Or you could safely import the user model as follows:
-
- .. code-block:: python
-
- from nine.user import User
+ TEMPLATE_CONTEXT_PROCESSORS += ['django_nine.context_processors.versions']
Testing
=======
@@ -99,7 +103,7 @@
.. code-block:: sh
- tox -e py35
+ tox -e py37
Or run Django tests:
@@ -109,7 +113,7 @@
License
=======
- GPL 2.0/LGPL 2.1
+ GPL-2.0-only OR LGPL-2.1-or-later
Support
=======
@@ -128,6 +132,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: Environment :: Web Environment
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine.egg-info/SOURCES.txt new/django-nine-0.2.2/src/django_nine.egg-info/SOURCES.txt
--- old/django-nine-0.1.13/src/django_nine.egg-info/SOURCES.txt 2017-05-16 22:28:17.000000000 +0200
+++ new/django-nine-0.2.2/src/django_nine.egg-info/SOURCES.txt 2019-05-19 19:16:50.000000000 +0200
@@ -5,15 +5,18 @@
README.rst
setup.cfg
setup.py
+src/django_nine/__init__.py
+src/django_nine/context_processors.py
+src/django_nine/models.py
+src/django_nine/user.py
+src/django_nine/versions.py
src/django_nine.egg-info/PKG-INFO
src/django_nine.egg-info/SOURCES.txt
src/django_nine.egg-info/dependency_links.txt
src/django_nine.egg-info/top_level.txt
+src/django_nine/tests/__init__.py
+src/django_nine/tests/base.py
+src/django_nine/tests/test_versions.py
src/nine/__init__.py
-src/nine/context_processors.py
-src/nine/models.py
src/nine/user.py
-src/nine/versions.py
-src/nine/tests/__init__.py
-src/nine/tests/base.py
-src/nine/tests/test_versions.py
\ No newline at end of file
+src/nine/versions.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/django_nine.egg-info/top_level.txt new/django-nine-0.2.2/src/django_nine.egg-info/top_level.txt
--- old/django-nine-0.1.13/src/django_nine.egg-info/top_level.txt 2017-05-16 22:28:17.000000000 +0200
+++ new/django-nine-0.2.2/src/django_nine.egg-info/top_level.txt 2019-05-19 19:16:50.000000000 +0200
@@ -1 +1,2 @@
+django_nine
nine
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/nine/__init__.py new/django-nine-0.2.2/src/nine/__init__.py
--- old/django-nine-0.1.13/src/nine/__init__.py 2017-05-16 22:25:52.000000000 +0200
+++ new/django-nine-0.2.2/src/nine/__init__.py 2019-05-19 19:14:57.000000000 +0200
@@ -1,6 +1,9 @@
-__title__ = 'django-nine'
-__version__ = '0.1.13'
-__build__ = 0x00000e
-__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
-__copyright__ = '2015-2017 Artur Barseghyan'
-__license__ = 'GPL 2.0/LGPL 2.1'
+import warnings
+
+from django_nine import versions # NOQA
+from django_nine import context_processors # NOQA
+
+warnings.warn(
+ "The `nine` namespace is deprecated, use `django_nine` instead.",
+ DeprecationWarning
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/nine/context_processors.py new/django-nine-0.2.2/src/nine/context_processors.py
--- old/django-nine-0.1.13/src/nine/context_processors.py 2017-05-16 22:20:35.000000000 +0200
+++ new/django-nine-0.2.2/src/nine/context_processors.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,18 +0,0 @@
-from nine import versions as nine_versions
-
-__title__ = 'nine.versions'
-__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
-__copyright__ = 'Copyright (c) 2015-2017 Artur Barseghyan'
-__license__ = 'GPL 2.0/LGPL 2.1'
-__all__ = [
- 'versions',
-]
-
-
-def versions(request):
- """Get active theme.
-
- :param django.http.HttpRequest request:
- :return dict:
- """
- return {'VERSIONS': nine_versions}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/nine/tests/__init__.py new/django-nine-0.2.2/src/nine/tests/__init__.py
--- old/django-nine-0.1.13/src/nine/tests/__init__.py 2015-08-24 23:18:14.000000000 +0200
+++ new/django-nine-0.2.2/src/nine/tests/__init__.py 1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-from .test_versions import *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/nine/tests/base.py new/django-nine-0.2.2/src/nine/tests/base.py
--- old/django-nine-0.1.13/src/nine/tests/base.py 2017-02-09 22:54:43.000000000 +0100
+++ new/django-nine-0.2.2/src/nine/tests/base.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,36 +0,0 @@
-import logging
-
-__title__ = 'nine.tests.base'
-__author__ = 'Artur Barseghyan'
-__copyright__ = 'Copyright (c) 2015-2017 Artur Barseghyan'
-__license__ = 'GPL 2.0/LGPL 2.1'
-__all__ = (
- 'LOG_INFO',
- 'log_info',
-)
-
-
-logger = logging.getLogger(__name__)
-
-LOG_INFO = True
-
-
-def log_info(func):
- """Logs some useful info."""
- if not LOG_INFO:
- return func
-
- def inner(self, *args, **kwargs):
- result = func(self, *args, **kwargs)
-
- logger.info('\n\n%s' % func.__name__)
- logger.info('============================')
- if func.__doc__:
- logger.info('""" %s """' % func.__doc__.strip())
- logger.info('----------------------------')
- if result is not None:
- logger.info(result)
- logger.info('\n++++++++++++++++++++++++++++')
-
- return result
- return inner
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/nine/tests/test_versions.py new/django-nine-0.2.2/src/nine/tests/test_versions.py
--- old/django-nine-0.1.13/src/nine/tests/test_versions.py 2016-11-30 23:12:59.000000000 +0100
+++ new/django-nine-0.2.2/src/nine/tests/test_versions.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,233 +0,0 @@
-import unittest
-import mock
-# For Python3 >= 3.4
-try:
- from importlib import reload
-# For Python3 < 3.4
-except ImportError as err:
- try:
- from imp import reload
- except ImportError as err:
- pass
-
-import django
-
-from .base import log_info
-
-__title__ = 'nine.tests.test_versions'
-__author__ = 'Artur Barseghyan'
-__copyright__ = 'Copyright (c) 2015 Artur Barseghyan'
-__license__ = 'GPL 2.0/LGPL 2.1'
-__all__ = ('VersionsTest',)
-
-
-class VersionsTest(unittest.TestCase):
- """
- Tests of ``nine.versions`` module.
- """
- def setUp(self):
- pass
-
- @log_info
- @mock.patch('django.get_version', mock.MagicMock(return_value='1.4.21'))
- def test_django_1_4_21(self):
- """
- Tests as if we were using Django==1.4.21.
- """
- from nine import versions
- reload(versions)
-
- # Exact version matching
- self.assertTrue(versions.DJANGO_1_4)
- self.assertTrue(not versions.DJANGO_1_5)
- self.assertTrue(not versions.DJANGO_1_6)
- self.assertTrue(not versions.DJANGO_1_7)
- self.assertTrue(not versions.DJANGO_1_8)
- self.assertTrue(not versions.DJANGO_1_9)
-
- # Less than or equal matching
- self.assertTrue(versions.DJANGO_LTE_1_4)
- self.assertTrue(versions.DJANGO_LTE_1_5)
- self.assertTrue(versions.DJANGO_LTE_1_6)
- self.assertTrue(versions.DJANGO_LTE_1_7)
- self.assertTrue(versions.DJANGO_LTE_1_8)
- self.assertTrue(versions.DJANGO_LTE_1_9)
-
- # Greater than or equal matching
- self.assertTrue(versions.DJANGO_GTE_1_4)
- self.assertTrue(not versions.DJANGO_GTE_1_5)
- self.assertTrue(not versions.DJANGO_GTE_1_6)
- self.assertTrue(not versions.DJANGO_GTE_1_7)
- self.assertTrue(not versions.DJANGO_GTE_1_8)
- self.assertTrue(not versions.DJANGO_GTE_1_9)
-
- @log_info
- @mock.patch('django.get_version', mock.MagicMock(return_value='1.5.5'))
- def test_django_1_5_5(self):
- """
- Tests as if we were using Django==1.5.5.
- """
- from nine import versions
- reload(versions)
-
- # Exact version matching
- self.assertTrue(not versions.DJANGO_1_4)
- self.assertTrue(versions.DJANGO_1_5)
- self.assertTrue(not versions.DJANGO_1_6)
- self.assertTrue(not versions.DJANGO_1_7)
- self.assertTrue(not versions.DJANGO_1_8)
- self.assertTrue(not versions.DJANGO_1_9)
-
- # Less than or equal matching
- self.assertTrue(not versions.DJANGO_LTE_1_4)
- self.assertTrue(versions.DJANGO_LTE_1_5)
- self.assertTrue(versions.DJANGO_LTE_1_6)
- self.assertTrue(versions.DJANGO_LTE_1_7)
- self.assertTrue(versions.DJANGO_LTE_1_8)
- self.assertTrue(versions.DJANGO_LTE_1_9)
-
- # Greater than or equal matching
- self.assertTrue(versions.DJANGO_GTE_1_4)
- self.assertTrue(versions.DJANGO_GTE_1_5)
- self.assertTrue(not versions.DJANGO_GTE_1_6)
- self.assertTrue(not versions.DJANGO_GTE_1_7)
- self.assertTrue(not versions.DJANGO_GTE_1_8)
- self.assertTrue(not versions.DJANGO_GTE_1_9)
-
- @log_info
- @mock.patch('django.get_version', mock.MagicMock(return_value='1.6.5'))
- def test_django_1_6_5(self):
- """
- Tests as if we were using Django==1.6.5.
- """
- from nine import versions
- reload(versions)
-
- # Exact version matching
- self.assertTrue(not versions.DJANGO_1_4)
- self.assertTrue(not versions.DJANGO_1_5)
- self.assertTrue(versions.DJANGO_1_6)
- self.assertTrue(not versions.DJANGO_1_7)
- self.assertTrue(not versions.DJANGO_1_8)
- self.assertTrue(not versions.DJANGO_1_9)
-
- # Less than or equal matching
- self.assertTrue(not versions.DJANGO_LTE_1_4)
- self.assertTrue(not versions.DJANGO_LTE_1_5)
- self.assertTrue(versions.DJANGO_LTE_1_6)
- self.assertTrue(versions.DJANGO_LTE_1_7)
- self.assertTrue(versions.DJANGO_LTE_1_8)
- self.assertTrue(versions.DJANGO_LTE_1_9)
-
- # Greater than or equal matching
- self.assertTrue(versions.DJANGO_GTE_1_4)
- self.assertTrue(versions.DJANGO_GTE_1_5)
- self.assertTrue(versions.DJANGO_GTE_1_6)
- self.assertTrue(not versions.DJANGO_GTE_1_7)
- self.assertTrue(not versions.DJANGO_GTE_1_8)
- self.assertTrue(not versions.DJANGO_GTE_1_9)
-
- @log_info
- @mock.patch('django.get_version', mock.MagicMock(return_value='1.7.5'))
- def test_django_1_7_5(self):
- """
- Tests as if we were using Django==1.7.5.
- """
- from nine import versions
- reload(versions)
-
- # Exact version matching
- self.assertTrue(not versions.DJANGO_1_4)
- self.assertTrue(not versions.DJANGO_1_5)
- self.assertTrue(not versions.DJANGO_1_6)
- self.assertTrue(versions.DJANGO_1_7)
- self.assertTrue(not versions.DJANGO_1_8)
- self.assertTrue(not versions.DJANGO_1_9)
-
- # Less than or equal matching
- self.assertTrue(not versions.DJANGO_LTE_1_4)
- self.assertTrue(not versions.DJANGO_LTE_1_5)
- self.assertTrue(not versions.DJANGO_LTE_1_6)
- self.assertTrue(versions.DJANGO_LTE_1_7)
- self.assertTrue(versions.DJANGO_LTE_1_8)
- self.assertTrue(versions.DJANGO_LTE_1_9)
-
- # Greater than or equal matching
- self.assertTrue(versions.DJANGO_GTE_1_4)
- self.assertTrue(versions.DJANGO_GTE_1_5)
- self.assertTrue(versions.DJANGO_GTE_1_6)
- self.assertTrue(versions.DJANGO_GTE_1_7)
- self.assertTrue(not versions.DJANGO_GTE_1_8)
- self.assertTrue(not versions.DJANGO_GTE_1_9)
-
- @log_info
- @mock.patch('django.get_version', mock.MagicMock(return_value='1.8.a1'))
- def test_django_1_8_a1(self):
- """
- Tests as if we were using Django==1.8.a1.
- """
- from nine import versions
- reload(versions)
-
- # Exact version matching
- self.assertTrue(not versions.DJANGO_1_4)
- self.assertTrue(not versions.DJANGO_1_5)
- self.assertTrue(not versions.DJANGO_1_6)
- self.assertTrue(not versions.DJANGO_1_7)
- self.assertTrue(versions.DJANGO_1_8)
- self.assertTrue(not versions.DJANGO_1_9)
-
- # Less than or equal matching
- self.assertTrue(not versions.DJANGO_LTE_1_4)
- self.assertTrue(not versions.DJANGO_LTE_1_5)
- self.assertTrue(not versions.DJANGO_LTE_1_6)
- self.assertTrue(not versions.DJANGO_LTE_1_7)
- self.assertTrue(versions.DJANGO_LTE_1_8)
- self.assertTrue(versions.DJANGO_LTE_1_9)
-
- # Greater than or equal matching
- self.assertTrue(versions.DJANGO_GTE_1_4)
- self.assertTrue(versions.DJANGO_GTE_1_5)
- self.assertTrue(versions.DJANGO_GTE_1_6)
- self.assertTrue(versions.DJANGO_GTE_1_7)
- self.assertTrue(versions.DJANGO_GTE_1_8)
- self.assertTrue(not versions.DJANGO_GTE_1_9)
-
- @log_info
- @mock.patch('django.get_version', mock.MagicMock(return_value='1.10'))
- def test_django_1_10(self):
- """
- Tests as if we were using Django==1.10.
- """
- from nine import versions
- reload(versions)
-
- # Exact version matching
- self.assertTrue(not versions.DJANGO_1_4)
- self.assertTrue(not versions.DJANGO_1_5)
- self.assertTrue(not versions.DJANGO_1_6)
- self.assertTrue(not versions.DJANGO_1_7)
- self.assertTrue(not versions.DJANGO_1_8)
- self.assertTrue(not versions.DJANGO_1_9)
- self.assertTrue(versions.DJANGO_1_10)
-
- # Less than or equal matching
- self.assertTrue(not versions.DJANGO_LTE_1_4)
- self.assertTrue(not versions.DJANGO_LTE_1_5)
- self.assertTrue(not versions.DJANGO_LTE_1_6)
- self.assertTrue(not versions.DJANGO_LTE_1_7)
- self.assertTrue(not versions.DJANGO_LTE_1_8)
- self.assertTrue(not versions.DJANGO_LTE_1_9)
-
- # Greater than or equal matching
- self.assertTrue(versions.DJANGO_GTE_1_4)
- self.assertTrue(versions.DJANGO_GTE_1_5)
- self.assertTrue(versions.DJANGO_GTE_1_6)
- self.assertTrue(versions.DJANGO_GTE_1_7)
- self.assertTrue(versions.DJANGO_GTE_1_8)
- self.assertTrue(versions.DJANGO_GTE_1_9)
- self.assertTrue(versions.DJANGO_GTE_1_10)
-
-
-if __name__ == "__main__":
- unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/nine/user.py new/django-nine-0.2.2/src/nine/user.py
--- old/django-nine-0.1.13/src/nine/user.py 2017-02-09 22:54:43.000000000 +0100
+++ new/django-nine-0.2.2/src/nine/user.py 2019-05-19 19:14:45.000000000 +0200
@@ -1,43 +1,15 @@
-"""
-Compatibility module for safe and sane User model import.
-"""
+import warnings
-import importlib
+from django_nine.user import * # NOQA
-from django.conf import settings
-from django.core.exceptions import ImproperlyConfigured
-from .versions import DJANGO_LTE_1_4, DJANGO_LTE_1_6, DJANGO_GTE_1_7
+warnings.warn(
+ "The `nine` namespace is deprecated, use `django_nine` instead.",
+ DeprecationWarning
+)
-if DJANGO_LTE_1_4:
- from django.contrib.auth.models import User
-else:
- # Cannot use contrib.auth.get_user_model() at compile time.
- user_app_name, user_model_name = settings.AUTH_USER_MODEL.rsplit('.', 1)
- User = None
-
- if DJANGO_LTE_1_6:
- for app in settings.INSTALLED_APPS:
- if app.endswith(user_app_name):
- user_app_models = importlib.import_module(app + ".models")
- User = getattr(user_app_models, user_model_name)
- break
- elif DJANGO_GTE_1_7:
- from django.apps import apps
- try:
- User = apps.get_registered_model(user_app_name, user_model_name)
- except KeyError:
- pass
-
- if User is None:
- raise ImproperlyConfigured(
- "You have defined a custom user model {0}, but the app {1} is "
- "not in ``settings.INSTALLED_APPS``"
- "".format(settings.AUTH_USER_MODEL, user_app_name)
- )
-
-__title__ = 'nine.user'
-__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
-__copyright__ = 'Copyright (c) 2015-2017 Artur Barseghyan'
-__license__ = 'GPL 2.0/LGPL 2.1'
-__all__ = ('User',)
+warnings.warn(
+ "The `django_nine.user` module is deprecated and will be removed in "
+ "version 0.3.",
+ DeprecationWarning
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-nine-0.1.13/src/nine/versions.py new/django-nine-0.2.2/src/nine/versions.py
--- old/django-nine-0.1.13/src/nine/versions.py 2017-02-09 22:54:43.000000000 +0100
+++ new/django-nine-0.2.2/src/nine/versions.py 2019-05-19 19:14:37.000000000 +0200
@@ -1,81 +1,8 @@
-"""
-Contains information about the current Django version in use, including (LTE
-and GTE).
-"""
+import warnings
-from distutils.version import LooseVersion
+from django_nine.versions import * # NOQA
-import django
-
-__title__ = 'nine.versions'
-__author__ = 'Artur Barseghyan <artur.barseghyan(a)gmail.com>'
-__copyright__ = 'Copyright (c) 2015-2017 Artur Barseghyan'
-__license__ = 'GPL 2.0/LGPL 2.1'
-__all__ = [
- 'LOOSE_DJANGO_VERSION', 'LOOSE_DJANGO_MINOR_VERSION',
-]
-
-LOOSE_DJANGO_VERSION = LooseVersion(django.get_version())
-LOOSE_DJANGO_MINOR_VERSION = LooseVersion(
- '.'.join([str(i) for i in LOOSE_DJANGO_VERSION.version[0:2]])
-)
-
-# Loose versions
-LOOSE_VERSIONS = (
- '1.4', '1.5', '1.6', '1.7', '1.8', '1.9', '1.10', '1.11', '2.0', '2.1',
- '2.2', '3.0'
+warnings.warn(
+ "The `nine` namespace is deprecated, use `django_nine` instead.",
+ DeprecationWarning
)
-
-for v in LOOSE_VERSIONS:
- var_name = 'LOOSE_VERSION_{0}'.format(v.replace('.', '_'))
- globals()[var_name] = LooseVersion(v)
- __all__.append(var_name)
-
-# Exact versions
-EXACT_VERSIONS = LOOSE_VERSIONS[:-1]
-
-for i, v in enumerate(EXACT_VERSIONS):
- l_cur = globals()['LOOSE_VERSION_{0}'
- ''.format(LOOSE_VERSIONS[i].replace('.', '_'))]
- l_nxt = globals()['LOOSE_VERSION_{0}'
- ''.format(LOOSE_VERSIONS[i+1].replace('.', '_'))]
- var_name = 'DJANGO_{0}'.format(v.replace('.', '_'))
- globals()[var_name] = (l_cur <= LOOSE_DJANGO_VERSION < l_nxt)
- __all__.append(var_name)
-
-# LTE list
-LTE_VERSIONS = LOOSE_VERSIONS[:-1]
-
-for i, v in enumerate(EXACT_VERSIONS):
- l_cur = globals()['LOOSE_VERSION_{0}'
- ''.format(LOOSE_VERSIONS[i].replace('.', '_'))]
- var_name = 'DJANGO_LTE_{0}'.format(v.replace('.', '_'))
- globals()[var_name] = (LOOSE_DJANGO_MINOR_VERSION <= l_cur)
- __all__.append(var_name)
-
-# GTE list
-GTE_VERSIONS = LOOSE_VERSIONS[:-1]
-
-for i, v in enumerate(EXACT_VERSIONS):
- l_cur = globals()['LOOSE_VERSION_{0}'
- ''.format(LOOSE_VERSIONS[i].replace('.', '_'))]
- var_name = 'DJANGO_GTE_{0}'.format(v.replace('.', '_'))
- globals()[var_name] = (
- LOOSE_DJANGO_MINOR_VERSION >= l_cur
- )
- __all__.append(var_name)
-
-__all__ = tuple(__all__)
-
-# Clean up
-try:
- del l_cur
- del l_nxt
- del var_name
- del i
- del v
-except NameError:
- pass
-
-del LooseVersion
-del django
1
0
Hello community,
here is the log from the commit of package python-moksha-hub for openSUSE:Factory checked in at 2019-05-22 15:41:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-moksha-hub (Old)
and /work/SRC/openSUSE:Factory/.python-moksha-hub.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-moksha-hub"
Wed May 22 15:41:16 2019 rev:3 rq:704706 version:1.5.17
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-moksha-hub/python-moksha-hub.changes 2018-12-24 11:39:52.801532605 +0100
+++ /work/SRC/openSUSE:Factory/.python-moksha-hub.new.5148/python-moksha-hub.changes 2019-05-22 15:42:04.978427044 +0200
@@ -1,0 +2,7 @@
+Wed May 22 05:37:00 UTC 2019 - pgajdos(a)suse.com
+
+- version update to 1.5.17
+ * no upstream changelog
+- run tests
+
+-------------------------------------------------------------------
Old:
----
moksha.hub-1.5.3.tar.gz
New:
----
moksha.hub-1.5.17.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-moksha-hub.spec ++++++
--- /var/tmp/diff_new_pack.RVlACr/_old 2019-05-22 15:42:06.646427036 +0200
+++ /var/tmp/diff_new_pack.RVlACr/_new 2019-05-22 15:42:06.650427036 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-moksha-hub
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 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
@@ -17,16 +17,23 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
-%bcond_with test
Name: python-moksha-hub
-Version: 1.5.3
+Version: 1.5.17
Release: 0
Summary: Hub components for Moksha
License: Apache-2.0
Group: Development/Languages/Python
URL: https://mokshaproject.net
Source: https://files.pythonhosted.org/packages/source/m/moksha.hub/moksha.hub-%{ve…
+BuildRequires: %{python_module Twisted}
+BuildRequires: %{python_module mock}
+BuildRequires: %{python_module moksha-common >= 1.0.6}
+BuildRequires: %{python_module nose}
+BuildRequires: %{python_module pyzmq}
BuildRequires: %{python_module setuptools}
+BuildRequires: %{python_module txWS}
+BuildRequires: %{python_module txZMQ}
+BuildRequires: %{python_module websocket-client}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-Twisted
@@ -35,16 +42,6 @@
Requires: python-txWS
Requires: python-txZMQ
BuildArch: noarch
-%if %{with test}
-BuildRequires: %{python_module Twisted}
-BuildRequires: %{python_module mock}
-BuildRequires: %{python_module moksha-common >= 1.0.6}
-BuildRequires: %{python_module nose}
-BuildRequires: %{python_module pyzmq}
-BuildRequires: %{python_module txWS}
-BuildRequires: %{python_module txZMQ}
-BuildRequires: %{python_module websocket-client}
-%endif
%python_subpackages
%description
@@ -59,10 +56,9 @@
%install
%python_install
%python_expand %fdupes %{buildroot}%{$python_sitelib}
-%if %{with test}
+
%check
%python_exec setup.py test
-%endif
%files %{python_files}
%license COPYING
++++++ moksha.hub-1.5.3.tar.gz -> moksha.hub-1.5.17.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/PKG-INFO new/moksha.hub-1.5.17/PKG-INFO
--- old/moksha.hub-1.5.3/PKG-INFO 2017-07-11 17:08:34.000000000 +0200
+++ new/moksha.hub-1.5.17/PKG-INFO 2019-02-12 06:20:18.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: moksha.hub
-Version: 1.5.3
+Version: 1.5.17
Summary: Hub components for Moksha.
Home-page: https://mokshaproject.net
Author: Luke Macken, John (J5) Palmieri, Mairin Duffy, and Ralph Bean
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha/hub/api/consumer.py new/moksha.hub-1.5.17/moksha/hub/api/consumer.py
--- old/moksha.hub-1.5.3/moksha/hub/api/consumer.py 2017-07-11 17:08:16.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha/hub/api/consumer.py 2018-09-24 18:14:16.000000000 +0200
@@ -33,6 +33,7 @@
log = logging.getLogger('moksha.hub')
import six.moves.queue as queue
+from collections import deque
from kitchen.iterutils import iterate
from moksha.common.lib.helpers import create_app_engine
@@ -60,7 +61,7 @@
# the queue to do "consume" work.
self.incoming = queue.Queue()
self.headcount_in = self.headcount_out = 0
- self._times = []
+ self._times = deque(maxlen=1024)
callback = self._consume
if self.jsonify:
@@ -99,7 +100,7 @@
backlog = self.incoming.qsize()
headcount_out = self.headcount_out
headcount_in = self.headcount_in
- times = self._times
+ times = list(self._times)
else:
backlog = None
headcount_out = headcount_in = 0
@@ -120,7 +121,7 @@
# Reset these counters before returning.
self.headcount_out = self.headcount_in = 0
self._exception_count = 0
- self._times = []
+ self._times.clear()
return results
def debug(self, message):
@@ -218,7 +219,7 @@
# Record how long it took to process this message (for stats)
self._times.append(time.time() - start)
- self.debug("Going back to waiting on the incoming queue.")
+ self.debug("Going back to waiting on the incoming queue. Message handled: %r" % handled)
return handled
def validate(self, message):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha/hub/api/producer.py new/moksha.hub-1.5.17/moksha/hub/api/producer.py
--- old/moksha.hub-1.5.3/moksha/hub/api/producer.py 2014-10-20 18:51:21.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha/hub/api/producer.py 2019-01-10 19:15:08.000000000 +0100
@@ -92,6 +92,10 @@
(self.frequency.microseconds / 1000000.0)
self._last_ran = None
+ # This is used to determine if the configured frequency has been meet,
+ # and the poller should run. This allows the poller to check if
+ # self.die is True more frequently.
+ self._until_next_poll = self.frequency
log.debug("Setting a %s second timer" % self.frequency)
moksha.hub.reactor.reactor.callInThread(self._work)
@@ -125,8 +129,27 @@
self._poll()
while not self.die:
- time.sleep(self.frequency)
- self._poll()
+ if not self.frequency:
+ # If no frequency is set, just continuously poll
+ self._poll()
+ continue
+
+ # If _until_next_poll is less than or equal to 0, that means
+ # the frequency has been met and the poller needs to run again
+ if self._until_next_poll <= 0:
+ self._poll()
+ # Reset _until_next_poll so that polling doesn't happen
+ # until the frequency is met again
+ self._until_next_poll = self.frequency
+ else:
+ # Only sleep 5 seconds (or _until_next_poll if it's shorter) at
+ # a time since we want to check if the poller should die
+ # frequently. Otherwise, you'll end up with Moksha Hub in a
+ # state where the hub is stopped but the poller is still
+ # sleeping until the frequency is met
+ sleep_time = min((5, self._until_next_poll))
+ time.sleep(sleep_time)
+ self._until_next_poll -= sleep_time
def stop(self):
super(PollingProducer, self).stop()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha/hub/hub.py new/moksha.hub-1.5.17/moksha/hub/hub.py
--- old/moksha.hub-1.5.3/moksha/hub/hub.py 2017-06-26 18:02:14.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha/hub/hub.py 2018-09-24 18:14:16.000000000 +0200
@@ -223,9 +223,12 @@
# FIXME: only do this if the consumer wants it `jsonified`
try:
- body = JSON.loads(message['body'])
+ if message['body']:
+ body = JSON.loads(message['body'])
+ else:
+ body = {}
except Exception as e:
- log.warning('Cannot decode message from JSON: %s' % e)
+ log.warning('Cannot decode body from JSON: %s -> %r' % (e, message))
#body = {}
body = message['body']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha/hub/monitoring.py new/moksha.hub-1.5.17/moksha/hub/monitoring.py
--- old/moksha.hub-1.5.3/moksha/hub/monitoring.py 2014-10-20 18:51:21.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha/hub/monitoring.py 2018-09-24 18:14:16.000000000 +0200
@@ -51,7 +51,7 @@
# to us.
mode = hub.config.get('moksha.monitoring.socket.mode')
if endpoint.startswith("ipc://") and mode:
- mode = string.atoi(mode, base=8)
+ mode = int(mode, base=8)
path = endpoint.split("ipc://")[-1]
os.chmod(path, mode)
@@ -72,7 +72,7 @@
"producers": self.serialize(self.hub.producers),
}
if self.socket:
- self.socket.send(json.dumps(data))
+ self.socket.send_string(json.dumps(data))
def stop(self):
super(MonitoringProducer, self).stop()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha/hub/stomp/protocol.py new/moksha.hub-1.5.17/moksha/hub/stomp/protocol.py
--- old/moksha.hub-1.5.3/moksha/hub/stomp/protocol.py 2017-06-26 17:56:51.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha/hub/stomp/protocol.py 2019-02-12 06:19:48.000000000 +0100
@@ -21,6 +21,10 @@
import logging
+from distutils.version import LooseVersion
+
+from moksha.common.lib.converters import asbool
+from moksha.hub.reactor import reactor
try:
# stomper is not ready for py3
@@ -78,7 +82,7 @@
f.headers.update(headers)
cmd = f.pack()
log.debug(cmd)
- self.transport.write(cmd)
+ self.transport.write(cmd.encode('utf-8'))
def connectionMade(self):
""" Register with stomp server """
@@ -91,8 +95,14 @@
else:
cmd = stomper.connect(self.username, self.password)
log.debug(cmd)
- self.transport.write(cmd)
+ self.transport.write(cmd.encode('utf-8'))
+ def error(self, msg):
+ """ Extend stomper's own error method to kill the hub. """
+ super(StompProtocol, self).error(msg)
+ log.error("Requesting shutdown of hub for STOMP error.")
+ reactor.callLater(0, self.client.hub.close)
+ reactor.callLater(0, reactor.stop)
def ack(self, msg):
""" Override stomper's own ack to be smarter, based on mode. """
@@ -108,7 +118,7 @@
def dataReceived(self, data):
"""Data received, react to it and respond if needed """
- self.buffer.appendData(data)
+ self.buffer.appendData(data.decode('utf-8', errors='replace'))
while True:
msg = self.buffer.getOneMessage()
if msg is None:
@@ -127,7 +137,15 @@
# Otherwise, see if we need to turn a naive 'ack' from stomper into
# a 'nack' if our consumers failed to do their jobs.
if handled is False and response.startswith("ACK\n"):
- if stomper.STOMP_VERSION != '1.1':
+
+ send_nacks = asbool(self.client.hub.config.get('stomp_send_explicit_nacks', True))
+ if not send_nacks:
+ log.warn("Message handling failed. stomp_send_explicit_nacks=%r. "
+ "Sending no reply to the broker.", send_nacks)
+ # Return, so as not to send an erroneous ack.
+ return
+
+ if LooseVersion(stomper.STOMP_VERSION) < LooseVersion('1.1'):
log.error("Unable to NACK stomp %r" % stomper.STOMP_VERSION)
# Also, not sending an erroneous ack.
return
@@ -135,8 +153,11 @@
message_id = msg['headers']['message-id']
subscription = msg['headers']['subscription']
transaction_id = msg['headers'].get('transaction-id')
- response = stomper.stomp_11.nack(message_id, subscription, transaction_id)
+ response = stomper.nack(message_id, subscription, transaction_id)
# Finally, send our response (ACK or NACK) back to the broker.
- log.debug(response)
- self.transport.write(response)
+ if not handled:
+ log.warn("handled=%r. Responding with %s" % (handled, response))
+ else:
+ log.debug("handled=%r. Responding with %s" % (handled, response))
+ self.transport.write(response.encode('utf-8'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha/hub/stomp/stomp.py new/moksha.hub-1.5.17/moksha/hub/stomp/stomp.py
--- old/moksha.hub-1.5.3/moksha/hub/stomp/stomp.py 2016-11-10 15:43:34.000000000 +0100
+++ new/moksha.hub-1.5.17/moksha/hub/stomp/stomp.py 2019-02-06 23:08:37.000000000 +0100
@@ -28,6 +28,7 @@
import logging
+import six
from twisted.internet.protocol import ClientFactory
from moksha.hub.stomp.protocol import StompProtocol
@@ -46,7 +47,7 @@
def __init__(self, hub, config):
self.config = config
self.hub = hub
- self._topics = hub.topics.keys()
+ self._topics = list(hub.topics.keys())
self._frames = []
uri = self.config.get('stomp_uri', None)
@@ -55,16 +56,6 @@
host = self.config.get('stomp_broker')
uri = "%s:%i" % (host, port)
- # Sometimes, a stomp consumer may wish to be subscribed to a queue
- # which is composed of messages from many different topics. In this
- # case, the hub hands dispatching messages to the right consumers.
- # This extension is only concerned with the queue, and negotiating that
- # with the broker.
- stomp_queue = self.config.get('stomp_queue', None)
- if stomp_queue:
- # Overwrite the declarations of all of our consumers.
- self._topics = [stomp_queue]
-
# A list of addresses over which we emulate failover()
self.addresses = [pair.split(":") for pair in uri.split(',')]
self.address_index = 0
@@ -96,7 +87,15 @@
client_cert = ssl.PrivateCertificate.loadPEM(
key_file.read() + cert_file.read())
- ssl_context = client_cert.options()
+ try:
+ import service_identity
+ # connect SSL/TLS with SNI support (https://twistedmatrix.com/trac/ticket/5190)
+ # This requires service_identity module: https://pypi.python.org/pypi/service_identity
+ ssl_context = ssl.optionsForClientTLS(six.text_type(host), clientCertificate=client_cert)
+ except ImportError:
+ log.warn("Connecting without SNI support due to absence of service_identity module.")
+ ssl_context = client_cert.options()
+
reactor.connectSSL(host, int(port), self, ssl_context)
else:
log.info("connecting unencrypted to %r %r %r" % (
@@ -114,17 +113,35 @@
interval = max(self.client_heartbeat, server_heartbeat)
log.debug("Heartbeat of %ims negotiated from (%i,%i); starting." % (
interval, self.client_heartbeat, server_heartbeat))
- self.start_heartbeat(interval)
+ # According to STOMP documentation, we have negotiated a heartbeat
+ # of `interval` milliseconds and heartbeats must be sent *at least*
+ # that often. Here, we'll send them twice as often to give plenty
+ # of room for latency.
+ # https://stomp.github.io/stomp-specification-1.2.html#Heart-beating
+ fudge_factor = 0.5
+ self.start_heartbeat(interval=(interval * fudge_factor))
else:
log.debug("Skipping heartbeat initialization")
+ # Sometimes, a stomp consumer may wish to be subscribed to a queue
+ # which is composed of messages from many different topics. In this
+ # case, the hub hands dispatching messages to the right consumers.
+ # This extension is only concerned with the queue, and negotiating that
+ # with the broker.
+ stomp_queue = self.config.get('stomp_queue', None)
+ if stomp_queue and self._topics and self._topics != [stomp_queue]:
+ log.info('Discarding consumer-specified topics in favor of '
+ 'stomp_queue=%s: %r' % (stomp_queue, self._topics))
+ # Overwrite the declarations of all of our consumers.
+ self._topics = [stomp_queue]
+
for topic in self._topics:
log.info('Subscribing to %s topic' % topic)
self.subscribe(topic, callback=lambda msg: None)
for frame in self._frames:
log.debug('Flushing queued frame')
- self.proto.transport.write(frame.pack())
+ self.proto.transport.write(frame.pack().encode('utf-8'))
self._frames = []
def clientConnectionLost(self, connector, reason):
@@ -140,7 +157,7 @@
def failover(self):
self.address_index = (self.address_index + 1) % len(self.addresses)
args = (self.addresses[self.address_index], self.key, self.crt,)
- self._delay = self._delay * (1 + (2.0 / len(self.addresses)))
+ self._delay = min(60.0, self._delay * (1 + (2.0 / len(self.addresses))))
log.info('(failover) reconnecting in %f seconds.' % self._delay)
reactor.callLater(self._delay, self.connect, *args)
@@ -150,7 +167,7 @@
def heartbeat(self, interval):
if self._heartbeat_enabled:
- self.proto.transport.write(chr(0x0A)) # Lub-dub
+ self.proto.transport.write(chr(0x0A).encode('utf-8')) # Lub-dub
reactor.callLater(interval / 1000.0, self.heartbeat, interval)
else:
log.debug("(heartbeat stopped)")
@@ -160,13 +177,16 @@
self._heartbeat_enabled = False
def send_message(self, topic, message, **headers):
+ # Convert any utf-8 encoded payloads back to unicode. stomper can't handle bytestrings
+ topic = topic.decode('utf-8') if isinstance(topic, six.binary_type) else topic
+ message = message.decode('utf-8') if isinstance(message, six.binary_type) else message
f = stomper.Frame()
f.unpack(stomper.send(topic, message))
if not self.proto:
log.info("Queueing stomp frame for later delivery")
self._frames.append(f)
else:
- self.proto.transport.write(f.pack())
+ self.proto.transport.write(f.pack().encode('utf-8'))
super(StompHubExtension, self).send_message(topic, message, **headers)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha/hub/tests/test_hub.py new/moksha.hub-1.5.17/moksha/hub/tests/test_hub.py
--- old/moksha.hub-1.5.3/moksha/hub/tests/test_hub.py 2014-10-22 15:57:40.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha/hub/tests/test_hub.py 2018-09-24 18:14:16.000000000 +0200
@@ -26,12 +26,19 @@
from time import sleep, time
from uuid import uuid4
from kitchen.iterutils import iterate
+import tempfile
+import shutil
+import os
+import stat
+import zmq
+import json
import moksha.common.testtools.utils as testutils
import moksha.hub.api
from moksha.hub.hub import MokshaHub, CentralMokshaHub
from moksha.hub.reactor import reactor as _reactor
+from moksha.hub.monitoring import MonitoringProducer
from nose.tools import (eq_, assert_true, assert_false)
@@ -49,7 +56,7 @@
_reactor.runUntilCurrent()
-class TestHub(unittest.TestCase):
+class TestHub:
def _setUp(self):
def kernel(config):
@@ -124,13 +131,15 @@
I'm not sure how to do that, so we're going to fake it and manually
add this consumer to the list of consumers of which the Hub is aware.
"""
- consume = cons(self.hub).consume
+ consumer = cons(self.hub)
+ consume = consumer.consume
for topic in iterate(cons.topic):
self.hub.topics[topic] = self.hub.topics.get(topic, [])
if consume not in self.hub.topics[topic]:
print('registering fake topic %r' % topic)
self.hub.topics[topic].append(consume)
sleep(sleep_duration)
+ return consumer
@testutils.crosstest
def test_abstract(self):
@@ -388,6 +397,102 @@
central = CentralMokshaHub(config, [TestConsumer], [])
central.close()
+ @testutils.crosstest
+ def test_consumer_stats_queued(self):
+ """ Verify that message processing stats are set for queued messages. """
+
+ class TestConsumer(moksha.hub.api.consumer.Consumer):
+ topic = self.a_topic
+
+ def consume(self, message):
+ pass
+
+ cons = self.fake_register_consumer(TestConsumer)
+
+ for i in range(5):
+ self.hub.send_message(topic=self.a_topic, message=secret)
+
+ simulate_reactor(sleep_duration)
+ sleep(sleep_duration)
+
+ eq_(cons.headcount_in, 5)
+ eq_(cons.headcount_out, 0)
+ eq_(cons._exception_count, 0)
+ eq_(len(cons._times), 0)
+
+ @testutils.crosstest
+ def test_consumer_stats_processed(self):
+ """ Verify that message processing stats are set for processed messages. """
+
+ class TestConsumer(moksha.hub.api.consumer.Consumer):
+ topic = self.a_topic
+
+ def consume(self, message):
+ pass
+
+ self.hub.config['moksha.blocking_mode'] = True
+ cons = self.fake_register_consumer(TestConsumer)
+
+ for i in range(5):
+ self.hub.send_message(topic=self.a_topic, message=secret)
+
+ simulate_reactor(sleep_duration)
+ sleep(sleep_duration)
+
+ eq_(cons.headcount_in, 5)
+ eq_(cons.headcount_out, 5)
+ eq_(cons._exception_count, 0)
+ eq_(len(cons._times), 5)
+
+ @testutils.crosstest
+ def test_consumer_stats_exceptions(self):
+ """ Verify that message processing stats are set for messages that generate exceptions. """
+
+ class TestConsumer(moksha.hub.api.consumer.Consumer):
+ topic = self.a_topic
+
+ def consume(self, message):
+ if message['body'] % 2:
+ raise RuntimeError()
+
+ self.hub.config['moksha.blocking_mode'] = True
+ cons = self.fake_register_consumer(TestConsumer)
+
+ for i in range(5):
+ self.hub.send_message(topic=self.a_topic, message=i)
+
+ simulate_reactor(sleep_duration)
+ sleep(sleep_duration)
+
+ eq_(cons.headcount_in, 5)
+ eq_(cons.headcount_out, 5)
+ eq_(cons._exception_count, 2)
+ eq_(len(cons._times), 5)
+
+ @testutils.crosstest
+ def test_consumer_stats_overflow(self):
+ """ Verify that Consumer._times doesn't grow beyond a maximum size. """
+
+ class TestConsumer(moksha.hub.api.consumer.Consumer):
+ topic = self.a_topic
+
+ def consume(self, message):
+ pass
+
+ self.hub.config['moksha.blocking_mode'] = True
+ cons = self.fake_register_consumer(TestConsumer)
+
+ for i in range(1500):
+ self.hub.send_message(topic=self.a_topic, message=secret)
+
+ simulate_reactor(sleep_duration)
+ sleep(sleep_duration)
+
+ eq_(cons.headcount_in, 1500)
+ eq_(cons.headcount_out, 1500)
+ eq_(cons._exception_count, 0)
+ eq_(len(cons._times), 1024)
+
class TestProducer:
def _setUp(self):
@@ -443,3 +548,49 @@
def test_idempotence(self):
""" Test that running the same test twice still works. """
return self.test_produce_ten_strs()
+
+
+class TestMonitoring:
+ def _setUp(self):
+ def kernel(config):
+ self.hub = CentralMokshaHub(config=config)
+ self.a_topic = a_topic = str(uuid4())
+
+ for __setup, name in testutils.make_setup_functions(kernel):
+ yield __setup, name
+
+ def _tearDown(self):
+ self.hub.close()
+
+ @testutils.crosstest
+ def test_monitoring(self):
+ """ Test that the MonitoringProducer works as expected. """
+ tmpdir = tempfile.mkdtemp()
+ try:
+ zmq_file = tmpdir + '/socket'
+ zmq_socket = 'ipc://' + zmq_file
+ self.hub.config['moksha.monitoring.socket'] = zmq_socket
+ self.hub.config['moksha.monitoring.socket.mode'] = '777'
+ mon = MonitoringProducer(self.hub)
+ assert_true(os.path.exists(zmq_file))
+ assert_true(stat.S_IMODE(os.stat(zmq_file).st_mode) == 0o777)
+ ctx = zmq.Context()
+ sub = ctx.socket(zmq.SUB)
+ sub.setsockopt(zmq.RCVTIMEO, 10000)
+ sub.setsockopt_string(zmq.SUBSCRIBE, u'')
+ sub.connect(zmq_socket)
+ data = []
+ def recv():
+ data.append(sub.recv())
+ thread = threading.Thread(target=recv)
+ thread.start()
+ sleep(sleep_duration)
+ mon.poll()
+ thread.join()
+ eq_(len(data), 1)
+ d = json.loads(data[0])
+ eq_(len(d['consumers']), 0)
+ eq_(len(d['producers']), 1)
+ eq_(d['producers'][0]['name'], 'MonitoringProducer')
+ finally:
+ shutil.rmtree(tmpdir)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha.hub.egg-info/PKG-INFO new/moksha.hub-1.5.17/moksha.hub.egg-info/PKG-INFO
--- old/moksha.hub-1.5.3/moksha.hub.egg-info/PKG-INFO 2017-07-11 17:08:34.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha.hub.egg-info/PKG-INFO 2019-02-12 06:20:18.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: moksha.hub
-Version: 1.5.3
+Version: 1.5.17
Summary: Hub components for Moksha.
Home-page: https://mokshaproject.net
Author: Luke Macken, John (J5) Palmieri, Mairin Duffy, and Ralph Bean
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha.hub.egg-info/SOURCES.txt new/moksha.hub-1.5.17/moksha.hub.egg-info/SOURCES.txt
--- old/moksha.hub-1.5.3/moksha.hub.egg-info/SOURCES.txt 2017-07-11 17:08:34.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha.hub.egg-info/SOURCES.txt 2019-02-12 06:20:18.000000000 +0100
@@ -10,7 +10,6 @@
moksha.hub.egg-info/dependency_links.txt
moksha.hub.egg-info/entry_points.txt
moksha.hub.egg-info/namespace_packages.txt
-moksha.hub.egg-info/pbr.json
moksha.hub.egg-info/requires.txt
moksha.hub.egg-info/top_level.txt
moksha/hub/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/moksha.hub.egg-info/pbr.json new/moksha.hub-1.5.17/moksha.hub.egg-info/pbr.json
--- old/moksha.hub-1.5.3/moksha.hub.egg-info/pbr.json 2015-07-27 20:55:33.000000000 +0200
+++ new/moksha.hub-1.5.17/moksha.hub.egg-info/pbr.json 1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-{"is_release": false, "git_version": "9928086"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/setup.cfg new/moksha.hub-1.5.17/setup.cfg
--- old/moksha.hub-1.5.3/setup.cfg 2017-07-11 17:08:34.000000000 +0200
+++ new/moksha.hub-1.5.17/setup.cfg 2019-02-12 06:20:18.000000000 +0100
@@ -1,5 +1,4 @@
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moksha.hub-1.5.3/setup.py new/moksha.hub-1.5.17/setup.py
--- old/moksha.hub-1.5.3/setup.py 2017-07-11 17:08:29.000000000 +0200
+++ new/moksha.hub-1.5.17/setup.py 2019-02-12 06:20:04.000000000 +0100
@@ -31,6 +31,10 @@
"txZMQ",
"txWS",
#"python-daemon",
+
+ # Optional
+ #"service_identity",
+ #"pyasn1",
]
tests_require = [
@@ -49,7 +53,7 @@
setup(
name='moksha.hub',
- version='1.5.3',
+ version='1.5.17',
description='Hub components for Moksha.',
author='Luke Macken, John (J5) Palmieri, Mairin Duffy, and Ralph Bean',
author_email='',
1
0
Hello community,
here is the log from the commit of package python-portpicker for openSUSE:Factory checked in at 2019-05-22 15:41:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-portpicker (Old)
and /work/SRC/openSUSE:Factory/.python-portpicker.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-portpicker"
Wed May 22 15:41:09 2019 rev:2 rq:704702 version:1.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-portpicker/python-portpicker.changes 2015-12-09 22:31:35.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.python-portpicker.new.5148/python-portpicker.changes 2019-05-22 15:42:02.318427055 +0200
@@ -1,0 +2,18 @@
+Mon May 20 15:18:38 UTC 2019 - pgajdos(a)suse.com
+
+- version update to 1.3.1
+ * Fix a race condition in `pick_unused_port()` involving the free ports set.
+ * Adds an optional `portserver_address` parameter to `pick_unused_port()` so
+ that callers can specify their own regardless of `os.environ`.
+ * `pick_unused_port()` now raises `NoFreePortFoundError` when no available port
+ could be found rather than spinning in a loop trying forever.
+ * Fall back to `socket.AF_INET` when `socket.AF_UNIX` support is not available
+ to communicate with a portserver.
+ * Introduced `add_reserved_port()` and `return_port()` APIs to allow ports to
+ be recycled and allow users to bring ports of their own.
+ * Changed default port range to 15000-24999 to avoid ephemeral ports.
+ * Portserver bugfix.
+- convert to single spec
+- run test
+
+-------------------------------------------------------------------
Old:
----
portpicker-1.1.0.tar.gz
New:
----
portpicker-1.3.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-portpicker.spec ++++++
--- /var/tmp/diff_new_pack.gyRcto/_old 2019-05-22 15:42:04.218427047 +0200
+++ /var/tmp/diff_new_pack.gyRcto/_new 2019-05-22 15:42:04.234427047 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-portpicker
#
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 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
@@ -12,28 +12,26 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
-%define upstream_name portpicker
+%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-portpicker
-Version: 1.1.0
+Version: 1.3.1
Release: 0
Summary: A library to choose unique available network ports
License: Apache-2.0
Group: Development/Libraries/Python
-Url: https://github.com/google/python_portpicker
-Source0: %{upstream_name}-%{version}.tar.gz
-Requires: python
-BuildRequires: python-setuptools
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
-
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
+URL: https://github.com/google/python_portpicker
+Source0: https://files.pythonhosted.org/packages/source/p/portpicker/portpicker-%{ve…
+BuildRequires: %{python_module setuptools}
+BuildRequires: fdupes
BuildArch: noarch
-%endif
+# SECTION test requirements
+BuildRequires: %{python_module mock}
+# /SECTION
+%python_subpackages
%description
Portpicker provides an API to find and return an available network port for
@@ -41,17 +39,23 @@
harnesses that launch local servers.
%prep
-%setup -q -n %{upstream_name}-%{version}
+%setup -q -n portpicker-%{version}
%build
-python setup.py build
+%python_build
%install
-python setup.py install --prefix=%{_prefix} --root=%{buildroot}
+%python_install
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
-%files
-%defattr(-,root,root,-)
-%doc CONTRIBUTING.md LICENSE README.md
-%{python_sitelib}/%{upstream_name}*
+%check
+%python_expand PYTHONPATH=%{buildroot}%{$python_sitelib} $python src/tests/portpicker_test.py
+
+%files %{python_files}
+%license LICENSE
+%doc CONTRIBUTING.md README.md
+%{python_sitelib}/*
+# import asyncio
+%python3_only %{_bindir}/portserver.py
%changelog
++++++ portpicker-1.1.0.tar.gz -> portpicker-1.3.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/ChangeLog.md new/portpicker-1.3.1/ChangeLog.md
--- old/portpicker-1.1.0/ChangeLog.md 1970-01-01 01:00:00.000000000 +0100
+++ new/portpicker-1.3.1/ChangeLog.md 2019-03-05 17:20:26.000000000 +0100
@@ -0,0 +1,37 @@
+## 1.3.1
+
+ * Fix a race condition in `pick_unused_port()` involving the free ports set.
+
+## 1.3.0
+
+* Adds an optional `portserver_address` parameter to `pick_unused_port()` so
+ that callers can specify their own regardless of `os.environ`.
+* `pick_unused_port()` now raises `NoFreePortFoundError` when no available port
+ could be found rather than spinning in a loop trying forever.
+* Fall back to `socket.AF_INET` when `socket.AF_UNIX` support is not available
+ to communicate with a portserver.
+
+## 1.2.0
+
+* Introduced `add_reserved_port()` and `return_port()` APIs to allow ports to
+ be recycled and allow users to bring ports of their own.
+
+## 1.1.1
+
+* Changed default port range to 15000-24999 to avoid ephemeral ports.
+* Portserver bugfix.
+
+## 1.1.0
+
+* Renamed portpicker APIs to use PEP8 style function names in code and docs.
+* Legacy CapWords API name compatibility is maintained (and explicitly tested).
+
+## 1.0.1
+
+* Code reindented to use 4 space indents and run through
+ [YAPF](https://github.com/google/yapf) for consistent style.
+* Not packaged for release.
+
+## 1.0.0
+
+* Original open source release.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/MANIFEST.in new/portpicker-1.3.1/MANIFEST.in
--- old/portpicker-1.1.0/MANIFEST.in 1970-01-01 01:00:00.000000000 +0100
+++ new/portpicker-1.3.1/MANIFEST.in 2017-10-09 19:32:19.000000000 +0200
@@ -0,0 +1,8 @@
+include src/port*.py
+include src/tests/port*.py
+include README.md
+include LICENSE
+include CONTRIBUTING.md
+include ChangeLog.md
+include setup.py
+include test.sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/PKG-INFO new/portpicker-1.3.1/PKG-INFO
--- old/portpicker-1.1.0/PKG-INFO 2015-04-02 02:39:05.000000000 +0200
+++ new/portpicker-1.3.1/PKG-INFO 2019-03-05 17:54:53.000000000 +0100
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: portpicker
-Version: 1.1.0
+Version: 1.3.1
Summary: A library to choose unique available network ports.
Home-page: https://github.com/google/python_portpicker
Author: Google
Author-email: greg(a)krypto.org
License: Apache 2.0
+Description-Content-Type: UNKNOWN
Description: Portpicker provides an API to find and return an available network
port for an application to bind to. Ideally suited for use from
unittests or for test harnesses that launch local servers.
@@ -19,7 +20,8 @@
Classifier: Programming Language :: Python :: 3
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: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: Jython
Classifier: Programming Language :: Python :: Implementation :: PyPy
-Requires: mock(>=1.0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/README.md new/portpicker-1.3.1/README.md
--- old/portpicker-1.1.0/README.md 2015-04-02 02:20:41.000000000 +0200
+++ new/portpicker-1.3.1/README.md 2019-01-15 22:11:37.000000000 +0100
@@ -1,6 +1,6 @@
# Python portpicker module
-This module is useful finding unused network ports on a host.
+This module is useful for finding unused network ports on a host.
It supports both Python 2 and Python 3.
This module provides a pure Python `pick_unused_port()` function.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/setup.cfg new/portpicker-1.3.1/setup.cfg
--- old/portpicker-1.1.0/setup.cfg 1970-01-01 01:00:00.000000000 +0100
+++ new/portpicker-1.3.1/setup.cfg 2019-03-05 17:54:53.000000000 +0100
@@ -0,0 +1,4 @@
+[egg_info]
+tag_build =
+tag_date = 0
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/setup.py new/portpicker-1.3.1/setup.py
--- old/portpicker-1.1.0/setup.py 2015-04-02 02:30:48.000000000 +0200
+++ new/portpicker-1.3.1/setup.py 2019-03-05 17:23:51.000000000 +0100
@@ -14,11 +14,13 @@
#
"""Simple distutils setup for the pure Python portpicker."""
-import distutils.core
import sys
import textwrap
+import setuptools
+
+
def main():
requires = []
scripts = []
@@ -31,9 +33,9 @@
# The example portserver implementation requires Python 3 and asyncio.
scripts.append('src/portserver.py')
- distutils.core.setup(
+ setuptools.setup(
name='portpicker',
- version='1.1.0',
+ version='1.3.1',
description='A library to choose unique available network ports.',
long_description=textwrap.dedent("""\
Portpicker provides an API to find and return an available network
@@ -57,6 +59,8 @@
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: Jython',
'Programming Language :: Python :: Implementation :: PyPy'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/portpicker.egg-info/PKG-INFO new/portpicker-1.3.1/src/portpicker.egg-info/PKG-INFO
--- old/portpicker-1.1.0/src/portpicker.egg-info/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/portpicker-1.3.1/src/portpicker.egg-info/PKG-INFO 2019-03-05 17:54:53.000000000 +0100
@@ -0,0 +1,27 @@
+Metadata-Version: 1.1
+Name: portpicker
+Version: 1.3.1
+Summary: A library to choose unique available network ports.
+Home-page: https://github.com/google/python_portpicker
+Author: Google
+Author-email: greg(a)krypto.org
+License: Apache 2.0
+Description-Content-Type: UNKNOWN
+Description: Portpicker provides an API to find and return an available network
+ port for an application to bind to. Ideally suited for use from
+ unittests or for test harnesses that launch local servers.
+Platform: POSIX
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Intended Audience :: Developers
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+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: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: Jython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/portpicker.egg-info/SOURCES.txt new/portpicker-1.3.1/src/portpicker.egg-info/SOURCES.txt
--- old/portpicker-1.1.0/src/portpicker.egg-info/SOURCES.txt 1970-01-01 01:00:00.000000000 +0100
+++ new/portpicker-1.3.1/src/portpicker.egg-info/SOURCES.txt 2019-03-05 17:54:53.000000000 +0100
@@ -0,0 +1,15 @@
+CONTRIBUTING.md
+ChangeLog.md
+LICENSE
+MANIFEST.in
+README.md
+setup.py
+test.sh
+src/portpicker.py
+src/portserver.py
+src/portpicker.egg-info/PKG-INFO
+src/portpicker.egg-info/SOURCES.txt
+src/portpicker.egg-info/dependency_links.txt
+src/portpicker.egg-info/top_level.txt
+src/tests/portpicker_test.py
+src/tests/portserver_test.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/portpicker.egg-info/dependency_links.txt new/portpicker-1.3.1/src/portpicker.egg-info/dependency_links.txt
--- old/portpicker-1.1.0/src/portpicker.egg-info/dependency_links.txt 1970-01-01 01:00:00.000000000 +0100
+++ new/portpicker-1.3.1/src/portpicker.egg-info/dependency_links.txt 2019-03-05 17:54:53.000000000 +0100
@@ -0,0 +1 @@
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/portpicker.egg-info/top_level.txt new/portpicker-1.3.1/src/portpicker.egg-info/top_level.txt
--- old/portpicker-1.1.0/src/portpicker.egg-info/top_level.txt 1970-01-01 01:00:00.000000000 +0100
+++ new/portpicker-1.3.1/src/portpicker.egg-info/top_level.txt 2019-03-05 17:54:53.000000000 +0100
@@ -0,0 +1 @@
+portpicker
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/portpicker.py new/portpicker-1.3.1/src/portpicker.py
--- old/portpicker-1.1.0/src/portpicker.py 2015-04-02 02:20:57.000000000 +0200
+++ new/portpicker-1.3.1/src/portpicker.py 2019-03-05 17:20:26.000000000 +0100
@@ -36,25 +36,65 @@
"""
from __future__ import print_function
+
+import logging
import os
import random
import socket
import sys
# The legacy Bind, IsPortFree, etc. names are not exported.
-__all__ = ('bind', 'is_port_free', 'pick_unused_port',
- 'get_port_from_port_server')
+__all__ = ('bind', 'is_port_free', 'pick_unused_port', 'return_port',
+ 'add_reserved_port', 'get_port_from_port_server')
_PROTOS = [(socket.SOCK_STREAM, socket.IPPROTO_TCP),
(socket.SOCK_DGRAM, socket.IPPROTO_UDP)]
+# Ports that are currently available to be given out.
+_free_ports = set()
+
+# Ports that are reserved or from the portserver that may be returned.
+_owned_ports = set()
+
+# Ports that we chose randomly that may be returned.
+_random_ports = set()
+
+
+class NoFreePortFoundError(Exception):
+ """Exception indicating that no free port could be found."""
+ pass
+
+
+def add_reserved_port(port):
+ """Add a port that was acquired by means other than the port server."""
+ _free_ports.add(port)
+
+
+def return_port(port):
+ """Return a port that is no longer being used so it can be reused."""
+ if port in _random_ports:
+ _random_ports.remove(port)
+ elif port in _owned_ports:
+ _owned_ports.remove(port)
+ _free_ports.add(port)
+ elif port in _free_ports:
+ logging.info("Returning a port that was already returned: %s", port)
+ else:
+ logging.info("Returning a port that wasn't given by portpicker: %s",
+ port)
+
+
def bind(port, socket_type, socket_proto):
"""Try to bind to a socket of the specified type, protocol, and port.
This is primarily a helper function for PickUnusedPort, used to see
if a particular port number is available.
+ For the port to be considered available, the kernel must support at least
+ one of (IPv6, IPv4), and the port must be available on each supported
+ family.
+
Args:
port: The port number to bind to, or 0 to have the OS pick a free port.
socket_type: The type of the socket (ex: socket.SOCK_STREAM).
@@ -63,15 +103,24 @@
Returns:
The port number on success or None on failure.
"""
- sock = socket.socket(socket.AF_INET, socket_type, socket_proto)
- try:
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind(('', port))
- return sock.getsockname()[1]
- except socket.error:
- return None
- finally:
- sock.close()
+ got_socket = False
+ for family in (socket.AF_INET6, socket.AF_INET):
+ try:
+ sock = socket.socket(family, socket_type, socket_proto)
+ got_socket = True
+ except socket.error:
+ continue
+ try:
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ sock.bind(('', port))
+ if socket_type == socket.SOCK_STREAM:
+ sock.listen(1)
+ port = sock.getsockname()[1]
+ except socket.error:
+ return None
+ finally:
+ sock.close()
+ return port if got_socket else None
Bind = bind # legacy API. pylint: disable=invalid-name
@@ -84,31 +133,49 @@
Returns:
boolean, whether it is free to use for both TCP and UDP
"""
- return (bind(port, _PROTOS[0][0], _PROTOS[0][1]) and
- bind(port, _PROTOS[1][0], _PROTOS[1][1]))
+ return bind(port, *_PROTOS[0]) and bind(port, *_PROTOS[1])
IsPortFree = is_port_free # legacy API. pylint: disable=invalid-name
-def pick_unused_port(pid=None):
+def pick_unused_port(pid=None, portserver_address=None):
"""A pure python implementation of PickUnusedPort.
Args:
pid: PID to tell the portserver to associate the reservation with. If
- None,
- the current process's PID is used.
+ None, the current process's PID is used.
+ portserver_address: The address (path) of a unix domain socket
+ with which to connect to a portserver, a leading '@'
+ character indicates an address in the "abstract namespace". OR
+ On systems without socket.AF_UNIX, this is an AF_INET address.
+ If None, or no port is returned by the portserver at the provided
+ address, the environment will be checked for a PORTSERVER_ADDRESS
+ variable. If that is not set, no port server will be used.
Returns:
A port number that is unused on both TCP and UDP.
+
+ Raises:
+ NoFreePortFoundError: No free port could be found.
"""
- port = None
+ try: # Instead of `if _free_ports:` to handle the race condition.
+ port = _free_ports.pop()
+ except KeyError:
+ pass
+ else:
+ _owned_ports.add(port)
+ return port
# Provide access to the portserver on an opt-in basis.
+ if portserver_address:
+ port = get_port_from_port_server(portserver_address, pid=pid)
+ if port:
+ return port
if 'PORTSERVER_ADDRESS' in os.environ:
port = get_port_from_port_server(os.environ['PORTSERVER_ADDRESS'],
pid=pid)
- if not port:
- return _pick_unused_port_without_server()
- return port
+ if port:
+ return port
+ return _pick_unused_port_without_server()
PickUnusedPort = pick_unused_port # legacy API. pylint: disable=invalid-name
@@ -122,25 +189,33 @@
should not be called by code outside of this module.
Returns:
- A port number that is unused on both TCP and UDP. None on error.
+ A port number that is unused on both TCP and UDP.
+
+ Raises:
+ NoFreePortFoundError: No free port could be found.
"""
# Try random ports first.
rng = random.Random()
for _ in range(10):
- port = int(rng.randrange(32768, 60000))
+ port = int(rng.randrange(15000, 25000))
if is_port_free(port):
+ _random_ports.add(port)
return port
- # Try OS-assigned ports next.
+ # Next, try a few times to get an OS-assigned port.
# Ambrose discovered that on the 2.6 kernel, calling Bind() on UDP socket
# returns the same port over and over. So always try TCP first.
- while True:
+ for _ in range(10):
# Ask the OS for an unused port.
port = bind(0, _PROTOS[0][0], _PROTOS[0][1])
# Check if this port is unused on the other protocol.
if port and bind(port, _PROTOS[1][0], _PROTOS[1][1]):
+ _random_ports.add(port)
return port
+ # Give up.
+ raise NoFreePortFoundError()
+
def get_port_from_port_server(portserver_address, pid=None):
"""Request a free a port from a system-wide portserver.
@@ -156,6 +231,7 @@
portserver_address: The address (path) of a unix domain socket
with which to connect to the portserver. A leading '@'
character indicates an address in the "abstract namespace."
+ On systems without socket.AF_UNIX, this is an AF_INET address.
pid: The PID to tell the portserver to associate the reservation with.
If None, the current process's PID is used.
@@ -176,7 +252,11 @@
try:
# Create socket.
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ if hasattr(socket, 'AF_UNIX'):
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ else:
+ # fallback to AF_INET if this is not unix
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to portserver.
sock.connect(portserver_address)
@@ -189,15 +269,19 @@
buf = sock.recv(1024)
finally:
sock.close()
- except socket.error:
- print('Socket error when connecting to portserver.', file=sys.stderr)
+ except socket.error as e:
+ print('Socket error when connecting to portserver:', e,
+ file=sys.stderr)
return None
try:
- return int(buf.split(b'\n')[0])
+ port = int(buf.split(b'\n')[0])
except ValueError:
print('Portserver failed to find a port.', file=sys.stderr)
return None
+ _owned_ports.add(port)
+ return port
+
GetPortFromPortServer = get_port_from_port_server # legacy API. pylint: disable=invalid-name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/portserver.py new/portpicker-1.3.1/src/portserver.py
--- old/portpicker-1.1.0/src/portserver.py 2015-04-02 01:34:01.000000000 +0200
+++ new/portpicker-1.3.1/src/portserver.py 2017-10-09 19:32:19.000000000 +0200
@@ -38,6 +38,9 @@
log = None # Initialized to a logging.Logger by _configure_logging().
+_PROTOS = [(socket.SOCK_STREAM, socket.IPPROTO_TCP),
+ (socket.SOCK_DGRAM, socket.IPPROTO_UDP)]
+
def _get_process_command_line(pid):
try:
@@ -55,23 +58,51 @@
return 0
-def _port_is_available(port):
- """Return False if the given network port is currently in use."""
- for socket_type, proto in ((socket.SOCK_STREAM, socket.IPPROTO_TCP),
- (socket.SOCK_DGRAM, 0)):
- sock = None
+# TODO: Consider importing portpicker.bind() instead of duplicating the code.
+def _bind(port, socket_type, socket_proto):
+ """Try to bind to a socket of the specified type, protocol, and port.
+
+ For the port to be considered available, the kernel must support at least
+ one of (IPv6, IPv4), and the port must be available on each supported
+ family.
+
+ Args:
+ port: The port number to bind to, or 0 to have the OS pick a free port.
+ socket_type: The type of the socket (ex: socket.SOCK_STREAM).
+ socket_proto: The protocol of the socket (ex: socket.IPPROTO_TCP).
+
+ Returns:
+ The port number on success or None on failure.
+ """
+ got_socket = False
+ for family in (socket.AF_INET6, socket.AF_INET):
+ try:
+ sock = socket.socket(family, socket_type, socket_proto)
+ got_socket = True
+ except socket.error:
+ continue
try:
- sock = socket.socket(socket.AF_INET, socket_type, proto)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', port))
if socket_type == socket.SOCK_STREAM:
sock.listen(1)
+ port = sock.getsockname()[1]
except socket.error:
- return False
+ return None
finally:
- if sock:
- sock.close()
- return True
+ sock.close()
+ return port if got_socket else None
+
+
+def _is_port_free(port):
+ """Check if specified port is free.
+
+ Args:
+ port: integer, port to check
+ Returns:
+ boolean, whether it is free to use for both TCP and UDP
+ """
+ return _bind(port, *_PROTOS[0]) and _bind(port, *_PROTOS[1])
def _should_allocate_port(pid):
@@ -149,7 +180,7 @@
check_count += 1
if (candidate.start_time == 0 or
candidate.start_time != _get_process_start_time(candidate.pid)):
- if _port_is_available(candidate.pid):
+ if _is_port_free(candidate.port):
candidate.pid = pid
candidate.start_time = _get_process_start_time(pid)
if not candidate.start_time:
@@ -252,8 +283,8 @@
parser.add_argument(
'--portserver_static_pool',
type=str,
- default='32768-60000',
- help='Comma separated N-P Range(s) of ports to manage.')
+ default='15000-24999',
+ help='Comma separated N-P Range(s) of ports to manage (inclusive).')
parser.add_argument(
'--portserver_unix_socket_address',
type=str,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/tests/portpicker_test.py new/portpicker-1.3.1/src/tests/portpicker_test.py
--- old/portpicker-1.1.0/src/tests/portpicker_test.py 2015-04-02 02:16:51.000000000 +0200
+++ new/portpicker-1.3.1/src/tests/portpicker_test.py 2019-01-18 02:31:24.000000000 +0100
@@ -16,9 +16,11 @@
#
"""Unittests for the portpicker module."""
+from __future__ import print_function
import os
import random
import socket
+import sys
import unittest
try:
@@ -40,6 +42,9 @@
def setUp(self):
# So we can Bind even if portpicker.bind is stubbed out.
self._bind = portpicker.bind
+ portpicker._owned_ports.clear()
+ portpicker._free_ports.clear()
+ portpicker._random_ports.clear()
def testPickUnusedPortActuallyWorks(self):
"""This test can be flaky."""
@@ -65,6 +70,26 @@
@unittest.skipIf('PORTSERVER_ADDRESS' not in os.environ,
'no port server to test against')
+ def testPickUnusedCanSuccessfullyUsePortServerAddressKwarg(self):
+
+ with mock.patch.object(portpicker, '_pick_unused_port_without_server'):
+ portpicker._pick_unused_port_without_server.side_effect = (
+ Exception('eek!')
+ )
+
+ # Since _PickUnusedPortWithoutServer() raises an exception, and
+ # we've temporarily removed PORTSERVER_ADDRESS from os.environ, if
+ # we can successfully obtain a port, the portserver must be working.
+ addr = os.environ.pop('PORTSERVER_ADDRESS')
+ try:
+ port = portpicker.pick_unused_port(portserver_address=addr)
+ self.assertTrue(self.IsUnusedTCPPort(port))
+ self.assertTrue(self.IsUnusedUDPPort(port))
+ finally:
+ os.environ['PORTSERVER_ADDRESS'] = addr
+
+ @unittest.skipIf('PORTSERVER_ADDRESS' not in os.environ,
+ 'no port server to test against')
def testGetPortFromPortServer(self):
"""Exercise the get_port_from_port_server() helper function."""
for _ in range(10):
@@ -90,6 +115,50 @@
server.sendall.assert_called_once_with(b'9876\n')
self.assertEqual(port, 52768)
+ @mock.patch.dict(os.environ,{'PORTSERVER_ADDRESS': 'portserver'})
+ def testReusesPortServerPorts(self):
+ server = mock.Mock()
+ server.recv.side_effect = [b'12345\n', b'23456\n', b'34567\n']
+ with mock.patch.object(socket, 'socket', return_value=server):
+ self.assertEqual(portpicker.pick_unused_port(), 12345)
+ self.assertEqual(portpicker.pick_unused_port(), 23456)
+ portpicker.return_port(12345)
+ self.assertEqual(portpicker.pick_unused_port(), 12345)
+
+ @mock.patch.dict(os.environ,{'PORTSERVER_ADDRESS': ''})
+ def testDoesntReuseRandomPorts(self):
+ ports = set()
+ for _ in range(10):
+ port = portpicker.pick_unused_port()
+ ports.add(port)
+ portpicker.return_port(port)
+ self.assertGreater(len(ports), 5) # Allow some random reuse.
+
+ def testReturnsReservedPorts(self):
+ with mock.patch.object(portpicker, '_pick_unused_port_without_server'):
+ portpicker._pick_unused_port_without_server.side_effect = (
+ Exception('eek!'))
+ # Arbitrary port. In practice you should get this from somewhere
+ # that assigns ports.
+ reserved_port = 28465
+ portpicker.add_reserved_port(reserved_port)
+ ports = set()
+ for _ in range(10):
+ port = portpicker.pick_unused_port()
+ ports.add(port)
+ portpicker.return_port(port)
+ self.assertEqual(len(ports), 1)
+ self.assertEqual(ports.pop(), reserved_port)
+
+ @mock.patch.dict(os.environ,{'PORTSERVER_ADDRESS': ''})
+ def testFallsBackToRandomAfterRunningOutOfReservedPorts(self):
+ # Arbitrary port. In practice you should get this from somewhere
+ # that assigns ports.
+ reserved_port = 23456
+ portpicker.add_reserved_port(reserved_port)
+ self.assertEqual(portpicker.pick_unused_port(), reserved_port)
+ self.assertNotEqual(portpicker.pick_unused_port(), reserved_port)
+
def testRandomlyChosenPorts(self):
# Unless this box is under an overwhelming socket load, this test
# will heavily exercise the "pick a port randomly" part of the
@@ -132,10 +201,67 @@
return None
with mock.patch.object(portpicker, 'bind', bind_with_error):
+ got_at_least_one_port = False
for _ in range(100):
- port = portpicker._pick_unused_port_without_server()
- self.assertTrue(self.IsUnusedTCPPort(port))
- self.assertTrue(self.IsUnusedUDPPort(port))
+ try:
+ port = portpicker._pick_unused_port_without_server()
+ except portpicker.NoFreePortFoundError:
+ continue
+ else:
+ got_at_least_one_port = True
+ self.assertTrue(self.IsUnusedTCPPort(port))
+ self.assertTrue(self.IsUnusedUDPPort(port))
+ self.assertTrue(got_at_least_one_port)
+
+ def testIsPortFree(self):
+ """This might be flaky unless this test is run with a portserver."""
+ # The port should be free initially.
+ port = portpicker.pick_unused_port()
+ self.assertTrue(portpicker.is_port_free(port))
+
+ cases = [
+ (socket.AF_INET, socket.SOCK_STREAM, None),
+ (socket.AF_INET6, socket.SOCK_STREAM, 0),
+ (socket.AF_INET6, socket.SOCK_STREAM, 1),
+ (socket.AF_INET, socket.SOCK_DGRAM, None),
+ (socket.AF_INET6, socket.SOCK_DGRAM, 0),
+ (socket.AF_INET6, socket.SOCK_DGRAM, 1),
+ ]
+ for (sock_family, sock_type, v6only) in cases:
+ # Occupy the port on a subset of possible protocols.
+ try:
+ sock = socket.socket(sock_family, sock_type, 0)
+ except socket.error:
+ print('Kernel does not support sock_family=%d' % sock_family,
+ file=sys.stderr)
+ # Skip this case, since we cannot occupy a port.
+ continue
+
+ if not hasattr(socket, 'IPPROTO_IPV6'):
+ v6only = None
+
+ if v6only is not None:
+ try:
+ sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY,
+ v6only)
+ except socket.error:
+ print('Kernel does not support IPV6_V6ONLY=%d' % v6only,
+ file=sys.stderr)
+ # Don't care; just proceed with the default.
+ sock.bind(('', port))
+
+ # The port should be busy.
+ self.assertFalse(portpicker.is_port_free(port))
+ sock.close()
+
+ # Now it's free again.
+ self.assertTrue(portpicker.is_port_free(port))
+
+ def testIsPortFreeException(self):
+ port = portpicker.pick_unused_port()
+ with mock.patch.object(socket, 'socket') as mock_sock:
+ mock_sock.side_effect = socket.error('fake socket error', 0)
+ self.assertFalse(portpicker.is_port_free(port))
def testThatLegacyCapWordsAPIsExist(self):
"""The original APIs were CapWords style, 1.1 added PEP8 names."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/portpicker-1.1.0/src/tests/portserver_test.py new/portpicker-1.3.1/src/tests/portserver_test.py
--- old/portpicker-1.1.0/src/tests/portserver_test.py 2015-04-02 01:35:39.000000000 +0200
+++ new/portpicker-1.3.1/src/tests/portserver_test.py 2017-10-09 19:32:19.000000000 +0200
@@ -16,6 +16,7 @@
#
"""Tests for the example portserver."""
+from __future__ import print_function
import asyncio
import os
import socket
@@ -43,15 +44,49 @@
def test_get_process_start_time(self):
self.assertGreater(portserver._get_process_start_time(os.getpid()), 0)
- def test_port_is_available_true(self):
+ def test_is_port_free(self):
"""This might be flaky unless this test is run with a portserver."""
- # Insert Inception "we must go deeper" meme here.
- self.assertTrue(portserver._port_is_available(self.port))
+ # The port should be free initially.
+ self.assertTrue(portserver._is_port_free(self.port))
- def test_port_is_available_false(self):
+ cases = [
+ (socket.AF_INET, socket.SOCK_STREAM, None),
+ (socket.AF_INET6, socket.SOCK_STREAM, 0),
+ (socket.AF_INET6, socket.SOCK_STREAM, 1),
+ (socket.AF_INET, socket.SOCK_DGRAM, None),
+ (socket.AF_INET6, socket.SOCK_DGRAM, 0),
+ (socket.AF_INET6, socket.SOCK_DGRAM, 1),
+ ]
+ for (sock_family, sock_type, v6only) in cases:
+ # Occupy the port on a subset of possible protocols.
+ try:
+ sock = socket.socket(sock_family, sock_type, 0)
+ except socket.error:
+ print('Kernel does not support sock_family=%d' % sock_family,
+ file=sys.stderr)
+ # Skip this case, since we cannot occupy a port.
+ continue
+ if v6only is not None:
+ try:
+ sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY,
+ v6only)
+ except socket.error:
+ print('Kernel does not support IPV6_V6ONLY=%d' % v6only,
+ file=sys.stderr)
+ # Don't care; just proceed with the default.
+ sock.bind(('', self.port))
+
+ # The port should be busy.
+ self.assertFalse(portserver._is_port_free(self.port))
+ sock.close()
+
+ # Now it's free again.
+ self.assertTrue(portserver._is_port_free(self.port))
+
+ def test_is_port_free_exception(self):
with mock.patch.object(socket, 'socket') as mock_sock:
mock_sock.side_effect = socket.error('fake socket error', 0)
- self.assertFalse(portserver._port_is_available(self.port))
+ self.assertFalse(portserver._is_port_free(self.port))
def test_should_allocate_port(self):
self.assertFalse(portserver._should_allocate_port(0))
@@ -140,23 +175,45 @@
self.assertRaises(ValueError, self.pool.add_port_to_free_pool, 0)
self.assertRaises(ValueError, self.pool.add_port_to_free_pool, 65536)
- @mock.patch.object(portserver, '_port_is_available')
- def test_get_port_for_process_ok(self, mock_port_is_available):
+ @mock.patch.object(portserver, '_is_port_free')
+ def test_get_port_for_process_ok(self, mock_is_port_free):
self.pool.add_port_to_free_pool(self.port)
- mock_port_is_available.return_value = True
+ mock_is_port_free.return_value = True
self.assertEqual(self.port, self.pool.get_port_for_process(os.getpid()))
self.assertEqual(1, self.pool.ports_checked_for_last_request)
- @mock.patch.object(portserver, '_port_is_available')
- def test_get_port_for_process_none_left(self, mock_port_is_available):
+ @mock.patch.object(portserver, '_is_port_free')
+ def test_get_port_for_process_none_left(self, mock_is_port_free):
self.pool.add_port_to_free_pool(self.port)
self.pool.add_port_to_free_pool(22)
- mock_port_is_available.return_value = False
+ mock_is_port_free.return_value = False
self.assertEqual(2, self.pool.num_ports())
self.assertEqual(0, self.pool.get_port_for_process(os.getpid()))
self.assertEqual(2, self.pool.num_ports())
self.assertEqual(2, self.pool.ports_checked_for_last_request)
+ @mock.patch.object(portserver, '_is_port_free')
+ @mock.patch.object(os, 'getpid')
+ def test_get_port_for_process_pid_eq_port(self, mock_getpid, mock_is_port_free):
+ self.pool.add_port_to_free_pool(12345)
+ self.pool.add_port_to_free_pool(12344)
+ mock_is_port_free.side_effect = lambda port: port == os.getpid()
+ mock_getpid.return_value = 12345
+ self.assertEqual(2, self.pool.num_ports())
+ self.assertEqual(12345, self.pool.get_port_for_process(os.getpid()))
+ self.assertEqual(2, self.pool.ports_checked_for_last_request)
+
+ @mock.patch.object(portserver, '_is_port_free')
+ @mock.patch.object(os, 'getpid')
+ def test_get_port_for_process_pid_ne_port(self, mock_getpid, mock_is_port_free):
+ self.pool.add_port_to_free_pool(12344)
+ self.pool.add_port_to_free_pool(12345)
+ mock_is_port_free.side_effect = lambda port: port != os.getpid()
+ mock_getpid.return_value = 12345
+ self.assertEqual(2, self.pool.num_ports())
+ self.assertEqual(12344, self.pool.get_port_for_process(os.getpid()))
+ self.assertEqual(2, self.pool.ports_checked_for_last_request)
+
@mock.patch.object(portserver, '_get_process_command_line')
@mock.patch.object(portserver, '_should_allocate_port')
1
0
Hello community,
here is the log from the commit of package python-fastnumbers for openSUSE:Factory checked in at 2019-05-22 15:41:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-fastnumbers (Old)
and /work/SRC/openSUSE:Factory/.python-fastnumbers.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-fastnumbers"
Wed May 22 15:41:06 2019 rev:6 rq:704700 version:2.2.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-fastnumbers/python-fastnumbers.changes 2019-04-18 09:56:50.485357028 +0200
+++ /work/SRC/openSUSE:Factory/.python-fastnumbers.new.5148/python-fastnumbers.changes 2019-05-22 15:42:00.158427065 +0200
@@ -1,0 +2,5 @@
+Tue May 21 14:00:05 UTC 2019 - Andreas Schwab <schwab(a)suse.de>
+
+- Remove arch restriction
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-fastnumbers.spec ++++++
--- /var/tmp/diff_new_pack.RYNWlD/_old 2019-05-22 15:42:02.166427056 +0200
+++ /var/tmp/diff_new_pack.RYNWlD/_new 2019-05-22 15:42:02.166427056 +0200
@@ -29,7 +29,6 @@
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-ExclusiveArch: %{ix86} x86_64
# SECTION test requirements
BuildRequires: %{python_module hypothesis}
BuildRequires: %{python_module pytest-faulthandler}
1
0
Hello community,
here is the log from the commit of package python-yq for openSUSE:Factory checked in at 2019-05-22 15:41:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-yq (Old)
and /work/SRC/openSUSE:Factory/.python-yq.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-yq"
Wed May 22 15:41:03 2019 rev:4 rq:704699 version:2.7.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-yq/python-yq.changes 2019-03-29 20:42:42.494678168 +0100
+++ /work/SRC/openSUSE:Factory/.python-yq.new.5148/python-yq.changes 2019-05-22 15:41:59.322427068 +0200
@@ -1,0 +2,6 @@
+Tue May 21 10:24:07 UTC 2019 - John Vandenberg <jayvdb(a)gmail.com>
+
+- Add runtime dependency jq
+- Set LANG in %check to make tests pass on Leap builds
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-yq.spec ++++++
--- /var/tmp/diff_new_pack.LS2v6a/_old 2019-05-22 15:42:00.022427066 +0200
+++ /var/tmp/diff_new_pack.LS2v6a/_new 2019-05-22 15:42:00.026427066 +0200
@@ -23,17 +23,12 @@
Summary: Command-line YAML processor - jq wrapper for YAML documents
License: Apache-2.0
Group: Development/Languages/Python
-Url: https://github.com/kislyuk/yq
+URL: https://github.com/kislyuk/yq
Source: https://files.pythonhosted.org/packages/source/y/yq/yq-%{version}.tar.gz
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-# SECTION test requirements
-BuildRequires: %{python_module PyYAML >= 3.11}
-BuildRequires: %{python_module toml >= 0.9.4}
-BuildRequires: %{python_module xmltodict >= 0.11.0}
-BuildRequires: jq
-# /SECTION
+Requires: jq
Requires: python-PyYAML >= 3.11
Requires: python-setuptools
Requires: python-toml >= 0.9.4
@@ -41,7 +36,12 @@
Requires(post): update-alternatives
Requires(postun): update-alternatives
BuildArch: noarch
-
+# SECTION test requirements
+BuildRequires: %{python_module PyYAML >= 3.11}
+BuildRequires: %{python_module toml >= 0.9.4}
+BuildRequires: %{python_module xmltodict >= 0.11.0}
+BuildRequires: jq
+# /SECTION
%python_subpackages
%description
@@ -68,10 +68,10 @@
%python_uninstall_alternative xq
%check
+export LANG=en_US.UTF-8
PYTHONPATH=%{buildroot}%{python3_sitelib} python3 test/test.py -v
%files %{python_files}
-%defattr(-,root,root,-)
%license LICENSE
%doc README.rst
%python_alternative %{_bindir}/yq
1
0
Hello community,
here is the log from the commit of package python-dns-lexicon for openSUSE:Factory checked in at 2019-05-22 15:40:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-dns-lexicon (Old)
and /work/SRC/openSUSE:Factory/.python-dns-lexicon.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dns-lexicon"
Wed May 22 15:40:59 2019 rev:7 rq:704697 version:3.2.6
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-dns-lexicon/python-dns-lexicon.changes 2019-04-14 12:22:53.531794955 +0200
+++ /work/SRC/openSUSE:Factory/.python-dns-lexicon.new.5148/python-dns-lexicon.changes 2019-05-22 15:41:47.558427121 +0200
@@ -1,0 +2,6 @@
+Wed May 22 08:35:37 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 3.2.6:
+ * Varous pylint fixes
+
+-------------------------------------------------------------------
Old:
----
lexicon-3.2.1.tar.gz
New:
----
lexicon-3.2.6.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-dns-lexicon.spec ++++++
--- /var/tmp/diff_new_pack.oj6r0a/_old 2019-05-22 15:41:57.902427075 +0200
+++ /var/tmp/diff_new_pack.oj6r0a/_new 2019-05-22 15:41:57.906427075 +0200
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-dns-lexicon
-Version: 3.2.1
+Version: 3.2.6
Release: 0
Summary: DNS record manipulation utility
License: MIT
@@ -74,6 +74,7 @@
%prep
%setup -q -n lexicon-%{version}
# remove localzone test as this test requires an internet connection
+# will be fixed with next release
rm lexicon/tests/providers/test_localzone.py
# rpmlint
@@ -90,7 +91,7 @@
%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
-%python_expand PYTHONPATH=%{buildroot}%{$python_sitelib} py.test-%{$python_bin_suffix} -v lexicon/tests
+%pytest lexicon/tests
%files %{python_files}
%{python_sitelib}
++++++ lexicon-3.2.1.tar.gz -> lexicon-3.2.6.tar.gz ++++++
++++ 48665 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package featherpad for openSUSE:Factory checked in at 2019-05-22 15:40:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/featherpad (Old)
and /work/SRC/openSUSE:Factory/.featherpad.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "featherpad"
Wed May 22 15:40:56 2019 rev:7 rq:704689 version:0.10.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/featherpad/featherpad.changes 2019-02-25 17:58:52.966206296 +0100
+++ /work/SRC/openSUSE:Factory/.featherpad.new.5148/featherpad.changes 2019-05-22 15:41:41.218427149 +0200
@@ -1,0 +2,14 @@
+Wed May 22 09:09:19 UTC 2019 - mvetter(a)suse.com
+
+- Update to 0.10.0:
+ * Added support for searching/replacing regular expressions.
+ * Added cmake support.
+ * Replace triple periods and double hyphens with ellipses and em dashes respectively on typing (can be disabled in Preferences).
+ * The Preferences dialog has a better layout and its size is always remembered.
+ * Workaround for a Qt bug that gives non-plain text to clipboard on copying/cutting/selecting text.
+ * Fixed a crash under Wayland.
+ * Fixed a small issue in determining whether files should be opened in tabs or separate windows.
+ * Added lots of cmake patterns for syntax highlighting.
+ * Disabled tab DND without X11, mainly because Wayland still has a serious problem with QDrag.
+
+-------------------------------------------------------------------
Old:
----
V0.9.4.tar.gz
New:
----
V0.10.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ featherpad.spec ++++++
--- /var/tmp/diff_new_pack.5vSoaQ/_old 2019-05-22 15:41:45.822427129 +0200
+++ /var/tmp/diff_new_pack.5vSoaQ/_new 2019-05-22 15:41:45.826427129 +0200
@@ -17,7 +17,7 @@
Name: featherpad
-Version: 0.9.4
+Version: 0.10.0
Release: 0
Summary: Qt5-based plaintext editor
License: GPL-3.0-only
++++++ V0.9.4.tar.gz -> V0.10.0.tar.gz ++++++
++++ 33606 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package jgmenu for openSUSE:Factory checked in at 2019-05-22 15:40:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/jgmenu (Old)
and /work/SRC/openSUSE:Factory/.jgmenu.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "jgmenu"
Wed May 22 15:40:52 2019 rev:5 rq:704687 version:3.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/jgmenu/jgmenu.changes 2019-03-19 09:59:16.876081545 +0100
+++ /work/SRC/openSUSE:Factory/.jgmenu.new.5148/jgmenu.changes 2019-05-22 15:41:34.714427178 +0200
@@ -1,0 +2,38 @@
+Wed May 22 09:04:11 UTC 2019 - mvetter(a)suse.com
+
+- Update to 3.0:
+ * This release has a MAJOR bump as we have changed a few things in a
+ non-backward compatible way:
+ + The menu background colour is set to have no transparency by
+ default (alpha changed from 85% to 100%)
+ + tint2_look is set to 0 (false) by default. Although the alignment
+ with tint2's config file can be convenient, it has caused confusion
+ for a number of users.
+ + The config module has been re-written in C (previously python).
+ It has very similar functionality, but slighly different command
+ line options. It is predominantly an internal command used by
+ 'init', so most users should not notice a difference.
+ * Support scroll past top/bottom when using keyboard arrows (issue #90).
+ When scrolling past the last item, the selection moves to the top, and
+ vice versa. Suggested-by: @hhhorb
+ * Add lithium-rc1 theme
+ * Teach widgets module to accept keyword "auto" for fgcol. If "auto" is
+ specified instead of a "#rrggbb aa" value, the jgmenurc config file
+ color_norm_fg value will be used. This is useful if you want widget
+ text to take on the same colour as ordinary menu items.
+ * Give menu items higher Z-order priority than widgets
+ * Support movement betweeen widgets and items using keyboard. Simply
+ press the <tab> button to toggle between the two. The 'greeneye' theme
+ is a good place to try this out.
+ * Use apps module in greeneye theme rather than lx. This enables users
+ without the lx module to try it. The apps module will be a pmenu
+ successor. Although it is not quite ready yet, it is good enough for
+ this.
+ * In the pmenu module, respect override .desktop files (issue #86). We
+ now do not show .desktop files with the same filenames more than once.
+ We look for .desktop files in "~/.local/share" and "$XDG_DATA_DIRS"
+ before "/usr/share" and "/usr/local/share".
+ * Lots of minor improvements, tweaks and fixes. See git log for full
+ details.
+
+-------------------------------------------------------------------
Old:
----
v2.2.1.tar.gz
New:
----
v3.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ jgmenu.spec ++++++
--- /var/tmp/diff_new_pack.kfSSM7/_old 2019-05-22 15:41:40.938427151 +0200
+++ /var/tmp/diff_new_pack.kfSSM7/_new 2019-05-22 15:41:40.942427151 +0200
@@ -17,7 +17,7 @@
Name: jgmenu
-Version: 2.2.1
+Version: 3.0
Release: 0
Summary: Small X11 menu intended to be used with openbox and tint2
License: GPL-2.0-only
++++++ v2.2.1.tar.gz -> v3.0.tar.gz ++++++
++++ 25652 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package suse-prime for openSUSE:Factory checked in at 2019-05-22 15:40:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/suse-prime (Old)
and /work/SRC/openSUSE:Factory/.suse-prime.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "suse-prime"
Wed May 22 15:40:48 2019 rev:9 rq:704686 version:0.5
Changes:
--------
--- /work/SRC/openSUSE:Factory/suse-prime/suse-prime.changes 2019-04-08 20:54:15.082599858 +0200
+++ /work/SRC/openSUSE:Factory/.suse-prime.new.5148/suse-prime.changes 2019-05-22 15:41:23.478427228 +0200
@@ -1,0 +2,6 @@
+Mon Apr 1 13:49:26 UTC 2019 - Stefan Dirsch <sndirsch(a)suse.com>
+
+- U_Corrected-DPI-value-in-xorg-nvidia.conf.patch
+ * Corrected DPI value in xorg-nvidia.conf (boo#1130723)
+
+-------------------------------------------------------------------
New:
----
U_Corrected-DPI-value-in-xorg-nvidia.conf.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ suse-prime.spec ++++++
--- /var/tmp/diff_new_pack.WRKrbd/_old 2019-05-22 15:41:32.194427190 +0200
+++ /var/tmp/diff_new_pack.WRKrbd/_new 2019-05-22 15:41:32.206427190 +0200
@@ -24,6 +24,7 @@
Group: System/X11/Utilities
Url: https://github.com/openSUSE/SUSEPrime
Source0: https://github.com/openSUSE/SUSEPrime/archive/%{version}.tar.gz#/SUSEPrime-…
+Patch0: U_Corrected-DPI-value-in-xorg-nvidia.conf.patch
Recommends: nvidia_driver
Supplements: modalias(nvidia_driver:pci:v00008086d*sv*sd*bc03sc*i*)
Conflicts: suse-prime-alt
@@ -36,6 +37,7 @@
%prep
%setup -n SUSEPrime-%{version}
+%patch0 -p1
%build
:
++++++ U_Corrected-DPI-value-in-xorg-nvidia.conf.patch ++++++
>From 7c50a32840e54c2129fce583a6c808bcbe5d7b5f Mon Sep 17 00:00:00 2001
From: simopil <pilia.simone96(a)gmail.com>
Date: Fri, 29 Mar 2019 15:02:36 +0100
Subject: [PATCH] Corrected DPI value in xorg-nvidia.conf
---
xorg-nvidia.conf | 1 +
1 file changed, 1 insertion(+)
diff --git a/xorg-nvidia.conf b/xorg-nvidia.conf
index 26b5ea2..e37ccca 100644
--- a/xorg-nvidia.conf
+++ b/xorg-nvidia.conf
@@ -34,5 +34,6 @@ Section "Device"
Identifier "nvidia"
Driver "nvidia"
BusID "PCI:X:X:X"
+ Option "DPI" "96 x 96"
Option "AllowEmptyInitialConfiguration"
EndSection
--
2.16.4
1
0
Hello community,
here is the log from the commit of package tcpflow for openSUSE:Factory checked in at 2019-05-22 15:40:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/tcpflow (Old)
and /work/SRC/openSUSE:Factory/.tcpflow.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "tcpflow"
Wed May 22 15:40:39 2019 rev:9 rq:704680 version:1.5.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/tcpflow/tcpflow.changes 2018-10-11 12:01:18.897576315 +0200
+++ /work/SRC/openSUSE:Factory/.tcpflow.new.5148/tcpflow.changes 2019-05-22 15:41:20.898427240 +0200
@@ -1,0 +2,5 @@
+Mon May 20 12:49:31 UTC 2019 - Christophe Giboudeaux <christophe(a)krop.fr>
+
+- Add the missing zlib requirement.
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ tcpflow.spec ++++++
--- /var/tmp/diff_new_pack.0RCnc5/_old 2019-05-22 15:41:23.294427229 +0200
+++ /var/tmp/diff_new_pack.0RCnc5/_new 2019-05-22 15:41:23.298427229 +0200
@@ -1,7 +1,7 @@
#
# spec file for package tcpflow
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2011 Sebastien Braun.
#
# All modifications and additions to the file contributed by third parties
@@ -34,6 +34,7 @@
BuildRequires: gcc-c++
BuildRequires: libpcap-devel
BuildRequires: pkgconfig(openssl)
+BuildRequires: pkgconfig(zlib)
%description
tcpflow is a program that captures data transmitted as part of TCP connections
1
0