Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pynetbox for openSUSE:Factory checked in at 2021-12-29 21:10:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pynetbox (Old) and /work/SRC/openSUSE:Factory/.python-pynetbox.new.2520 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pynetbox" Wed Dec 29 21:10:57 2021 rev:27 rq:942995 version:6.4.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pynetbox/python-pynetbox.changes 2021-12-07 00:00:57.856228697 +0100 +++ /work/SRC/openSUSE:Factory/.python-pynetbox.new.2520/python-pynetbox.changes 2021-12-29 21:11:28.130310792 +0100 @@ -1,0 +2,12 @@ +Mon Dec 27 10:54:26 UTC 2021 - Martin Hauke <mar...@gmx.de> + +- Update to version 6.4.1 + * Adds support for HTTP 409 when allocation is unsuccessful. + * Set ObjectChanges.postchange_data and .prechange_data to + JsonField. +- Update to version 6.4.0 + * Use display field in Record.__str__() to support future models + * Update docstrings for DetailEndpoint and Prefixes.available_* + * Add wireless app (for NetBox 3.1+) + +------------------------------------------------------------------- Old: ---- pynetbox-6.3.0.tar.gz New: ---- pynetbox-6.4.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pynetbox.spec ++++++ --- /var/tmp/diff_new_pack.O2tGn6/_old 2021-12-29 21:11:28.590311170 +0100 +++ /var/tmp/diff_new_pack.O2tGn6/_new 2021-12-29 21:11:28.594311174 +0100 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-pynetbox -Version: 6.3.0 +Version: 6.4.1 Release: 0 Summary: NetBox API client library License: Apache-2.0 ++++++ pynetbox-6.3.0.tar.gz -> pynetbox-6.4.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/.gitignore new/pynetbox-6.4.1/.gitignore --- old/pynetbox-6.3.0/.gitignore 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/.gitignore 2021-12-22 03:07:03.000000000 +0100 @@ -101,3 +101,6 @@ # Other git repos checked out locally .netbox-docker-*/ .devicetype-library/ + +# Visual Studio Code settings +.vscode/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/PKG-INFO new/pynetbox-6.4.1/PKG-INFO --- old/pynetbox-6.3.0/PKG-INFO 2021-12-04 23:55:32.527155400 +0100 +++ new/pynetbox-6.4.1/PKG-INFO 2021-12-22 03:07:15.604708400 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pynetbox -Version: 6.3.0 +Version: 6.4.1 Summary: NetBox API client library Home-page: https://github.com/digitalocean/pynetbox Author: Zach Moody diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/docs/index.rst new/pynetbox-6.4.1/docs/index.rst --- old/pynetbox-6.3.0/docs/index.rst 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/docs/index.rst 2021-12-22 03:07:03.000000000 +0100 @@ -27,5 +27,3 @@ ================== * :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/core/api.py new/pynetbox-6.4.1/pynetbox/core/api.py --- old/pynetbox-6.3.0/pynetbox/core/api.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/core/api.py 2021-12-22 03:07:03.000000000 +0100 @@ -37,6 +37,7 @@ * extras * virtualization * users + * wireless (since NetBox 3.1) Calling any of these attributes will return :py:class:`.App` which exposes endpoints as attributes. @@ -103,6 +104,7 @@ self.extras = App(self, "extras") self.virtualization = App(self, "virtualization") self.users = App(self, "users") + self.wireless = App(self, "wireless") self.plugins = PluginsApp(self) @property diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/core/app.py new/pynetbox-6.4.1/pynetbox/core/app.py --- old/pynetbox-6.3.0/pynetbox/core/app.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/core/app.py 2021-12-22 03:07:03.000000000 +0100 @@ -15,7 +15,15 @@ """ from pynetbox.core.endpoint import Endpoint from pynetbox.core.query import Request -from pynetbox.models import dcim, ipam, virtualization, circuits, extras, users +from pynetbox.models import ( + dcim, + ipam, + virtualization, + circuits, + extras, + users, + wireless, +) class App(object): @@ -41,6 +49,7 @@ "virtualization": virtualization, "extras": extras, "users": users, + "wireless": wireless, } def _setmodel(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/core/endpoint.py new/pynetbox-6.4.1/pynetbox/core/endpoint.py --- old/pynetbox-6.3.0/pynetbox/core/endpoint.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/core/endpoint.py 2021-12-22 03:07:03.000000000 +0100 @@ -545,7 +545,7 @@ class DetailEndpoint(object): - """Enables read/write Operations on detail endpoints. + """Enables read/write operations on detail endpoints. Endpoints like ``available-ips`` that are detail routes off traditional endpoints are handled with this class. @@ -572,8 +572,8 @@ E.g. ``.list(method='get_facts')`` would be converted to ``.../?method=get_facts``. - :returns: A dictionary or list of dictionaries retrieved from - NetBox. + :returns: A :py:class:`.Record` object or list of :py:class:`.Record` objects created + from data retrieved from NetBox. """ req = Request(**self.request_kwargs).get(add_params=kwargs) @@ -596,8 +596,8 @@ object. Defaults to empty dict which will create a single item with default values. - :returns: A dictionary or list of dictionaries its created in - NetBox. + :returns: A :py:class:`.Record` object or list of :py:class:`.Record` objects created + from data created in NetBox. """ data = data or {} req = Request(**self.request_kwargs).post(data) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/core/query.py new/pynetbox-6.4.1/pynetbox/core/query.py --- old/pynetbox-6.3.0/pynetbox/core/query.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/core/query.py 2021-12-22 03:07:03.000000000 +0100 @@ -73,7 +73,8 @@ """Allocation Exception Used with available-ips/available-prefixes when there is no - room for allocation and NetBox returns 204 No Content. + room for allocation and NetBox returns 204 No Content (before + NetBox 3.1.1) or 409 Conflict (since NetBox 3.1.1+). """ def __init__(self, message): @@ -268,7 +269,7 @@ url_override or self.url, headers=headers, params=params, json=data ) - if req.status_code == 204 and verb == "post": + if req.status_code in [204, 409] and verb == "post": raise AllocationError(req) if verb == "delete": if req.ok: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/core/response.py new/pynetbox-6.4.1/pynetbox/core/response.py --- old/pynetbox-6.3.0/pynetbox/core/response.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/core/response.py 2021-12-22 03:07:03.000000000 +0100 @@ -79,14 +79,14 @@ :Examples: - To see how many results are in a query by calling ``len()``. + To see how many results are in a query by calling ``len()``: >>> x = nb.dcim.devices.all() >>> len(x) 123 >>> - Simple iteration of the results. + Simple iteration of the results: >>> devices = nb.dcim.devices.all() >>> for device in devices: @@ -173,40 +173,40 @@ class Record(object): - """Create python objects from netbox API responses. + """Create Python objects from NetBox API responses. - Creates an object from a NetBox response passed as `values`. + Creates an object from a NetBox response passed as ``values``. Nested dicts that represent other endpoints are also turned - into Record objects. All fields are then assigned to the + into ``Record`` objects. All fields are then assigned to the object's attributes. If a missing attr is requested (e.g. requesting a field that's only present on a full response on - a Record made from a nested response) the pynetbox will make a - request for the full object and return the requsted value. + a ``Record`` made from a nested response) then pynetbox will make a + request for the full object and return the requested value. :examples: - Default representation of the object is usually its name + Default representation of the object is usually its name: >>> x = nb.dcim.devices.get(1) >>> x test1-switch1 >>> - Querying a string field. + Querying a string field: >>> x = nb.dcim.devices.get(1) >>> x.serial 'ABC123' >>> - Querying a field on a nested object. + Querying a field on a nested object: >>> x = nb.dcim.devices.get(1) >>> x.device_type.model 'QFX5100-24Q' >>> - Casting the object as a dictionary. + Casting the object as a dictionary: >>> from pprint import pprint >>> pprint(dict(x)) @@ -251,7 +251,7 @@ 'virtual_chassis': None} >>> - Iterating over a Record object. + Iterating over a ``Record`` object: >>> for i in x: ... print(i) @@ -313,7 +313,12 @@ return dict(self)[k] def __str__(self): - return getattr(self, "name", None) or getattr(self, "label", None) or "" + return ( + getattr(self, "name", None) + or getattr(self, "label", None) + or getattr(self, "display", None) + or "" + ) def __repr__(self): return str(self) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/models/extras.py new/pynetbox-6.4.1/pynetbox/models/extras.py --- old/pynetbox-6.3.0/pynetbox/models/extras.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/models/extras.py 2021-12-22 03:07:03.000000000 +0100 @@ -22,6 +22,8 @@ class ObjectChanges(Record): object_data = JsonField + postchange_data = JsonField + prechange_data = JsonField def __str__(self): return self.request_id diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/models/ipam.py new/pynetbox-6.4.1/pynetbox/models/ipam.py --- old/pynetbox-6.3.0/pynetbox/models/ipam.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/models/ipam.py 2021-12-22 03:07:03.000000000 +0100 @@ -39,21 +39,21 @@ >>> prefix = nb.ipam.prefixes.get(24) >>> prefix.available_ips.list() - [{u'vrf': None, u'family': 4, u'address': u'10.1.1.49/30'}...] + [10.0.0.1/24, 10.0.0.2/24, 10.0.0.3/24, 10.0.0.4/24, 10.0.0.5/24, ...] To create a single IP: >>> prefix = nb.ipam.prefixes.get(24) >>> prefix.available_ips.create() - {u'status': 1, u'description': u'', u'nat_inside': None...} + 10.0.0.1/24 To create multiple IPs: >>> prefix = nb.ipam.prefixes.get(24) >>> create = prefix.available_ips.create([{} for i in range(2)]) - >>> len(create) - 2 + >>> create + [10.0.0.2/24, 10.0.0.3/24] """ return DetailEndpoint(self, "available-ips", custom_return=IpAddresses) @@ -72,18 +72,23 @@ :Examples: + >>> prefix = nb.ipam.prefixes.get(3) + >>> prefix + 10.0.0.0/16 >>> prefix.available_prefixes.list() - [{u'prefix': u'10.1.1.44/30', u'vrf': None, u'family': 4}] + [10.0.1.0/24, 10.0.2.0/23, 10.0.4.0/22, 10.0.8.0/21, 10.0.16.0/20, 10.0.32.0/19, 10.0.64.0/18, 10.0.128.0/17] Creating a single child prefix: >>> prefix = nb.ipam.prefixes.get(1) + >>> prefix + 10.0.0.0/24 >>> new_prefix = prefix.available_prefixes.create( - ... {'prefix_length': 29} - ...) - >>> new_prefix['prefix'] - u'10.1.1.56/29' + ... {"prefix_length": 29} + ... ) + >>> new_prefix + 10.0.0.16/29 """ return DetailEndpoint(self, "available-prefixes", custom_return=Prefixes) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox/models/wireless.py new/pynetbox-6.4.1/pynetbox/models/wireless.py --- old/pynetbox-6.3.0/pynetbox/models/wireless.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox/models/wireless.py 2021-12-22 03:07:03.000000000 +0100 @@ -0,0 +1,21 @@ +""" +(c) 2017 DigitalOcean + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" +from pynetbox.core.response import Record + + +class WirelessLans(Record): + def __str__(self): + return self.ssid diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox.egg-info/PKG-INFO new/pynetbox-6.4.1/pynetbox.egg-info/PKG-INFO --- old/pynetbox-6.3.0/pynetbox.egg-info/PKG-INFO 2021-12-04 23:55:32.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox.egg-info/PKG-INFO 2021-12-22 03:07:15.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pynetbox -Version: 6.3.0 +Version: 6.4.1 Summary: NetBox API client library Home-page: https://github.com/digitalocean/pynetbox Author: Zach Moody diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/pynetbox.egg-info/SOURCES.txt new/pynetbox-6.4.1/pynetbox.egg-info/SOURCES.txt --- old/pynetbox-6.3.0/pynetbox.egg-info/SOURCES.txt 2021-12-04 23:55:32.000000000 +0100 +++ new/pynetbox-6.4.1/pynetbox.egg-info/SOURCES.txt 2021-12-22 03:07:15.000000000 +0100 @@ -36,6 +36,7 @@ pynetbox/models/ipam.py pynetbox/models/users.py pynetbox/models/virtualization.py +pynetbox/models/wireless.py tests/__init__.py tests/conftest.py tests/test_api.py @@ -44,6 +45,7 @@ tests/test_tenancy.py tests/test_users.py tests/test_virtualization.py +tests/test_wireless.py tests/util.py tests/fixtures/api/get_session_key.json tests/fixtures/api/token_provision.json @@ -144,6 +146,7 @@ tests/fixtures/users/groups.json tests/fixtures/users/permission.json tests/fixtures/users/permissions.json +tests/fixtures/users/unknown_model.json tests/fixtures/users/user.json tests/fixtures/users/users.json tests/fixtures/virtualization/cluster.json @@ -156,6 +159,8 @@ tests/fixtures/virtualization/interfaces.json tests/fixtures/virtualization/virtual_machine.json tests/fixtures/virtualization/virtual_machines.json +tests/fixtures/wireless/wireless_lan.json +tests/fixtures/wireless/wireless_lans.json tests/integration/conftest.py tests/integration/test_dcim.py tests/integration/test_ipam.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/tests/fixtures/users/unknown_model.json new/pynetbox-6.4.1/tests/fixtures/users/unknown_model.json --- old/pynetbox-6.3.0/tests/fixtures/users/unknown_model.json 1970-01-01 01:00:00.000000000 +0100 +++ new/pynetbox-6.4.1/tests/fixtures/users/unknown_model.json 2021-12-22 03:07:03.000000000 +0100 @@ -0,0 +1,4 @@ +{ + "id": 1, + "display": "Unknown object" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/tests/fixtures/wireless/wireless_lan.json new/pynetbox-6.4.1/tests/fixtures/wireless/wireless_lan.json --- old/pynetbox-6.3.0/tests/fixtures/wireless/wireless_lan.json 1970-01-01 01:00:00.000000000 +0100 +++ new/pynetbox-6.4.1/tests/fixtures/wireless/wireless_lan.json 2021-12-22 03:07:03.000000000 +0100 @@ -0,0 +1,4 @@ +{ + "id": 1, + "ssid": "SSID 1" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/tests/fixtures/wireless/wireless_lans.json new/pynetbox-6.4.1/tests/fixtures/wireless/wireless_lans.json --- old/pynetbox-6.3.0/tests/fixtures/wireless/wireless_lans.json 1970-01-01 01:00:00.000000000 +0100 +++ new/pynetbox-6.4.1/tests/fixtures/wireless/wireless_lans.json 2021-12-22 03:07:03.000000000 +0100 @@ -0,0 +1,15 @@ +{ + "count": 2, + "next": null, + "previous": null, + "results": [ + { + "id": 1, + "ssid": "SSID 1" + }, + { + "id": 2, + "ssid": "SSID 2" + } + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/tests/test_users.py new/pynetbox-6.4.1/tests/test_users.py --- old/pynetbox-6.3.0/tests/test_users.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/tests/test_users.py 2021-12-22 03:07:03.000000000 +0100 @@ -86,6 +86,7 @@ ) def test_repr(self, _): test = nb.users.get(1) + self.assertEqual(type(test), pynetbox.models.users.Users) self.assertEqual(str(test), "user1") @@ -105,3 +106,19 @@ self.assertEqual(len(permission.users), 1) user = permission.users[0] self.assertEqual(str(user), "user1") + + +class UnknownModelTestCase(unittest.TestCase): + """ This test validates that an unknown model is returned as Record object + and that the __str__() method correctly uses the 'display' field of the + object (introduced as a standard field in NetBox 2.11.0). + """ + + @patch( + "requests.sessions.Session.get", + return_value=Response(fixture="users/unknown_model.json"), + ) + def test_unknown_model(self, _): + unknown_obj = nb.unknown_model.get(1) + self.assertEqual(type(unknown_obj), pynetbox.core.response.Record) + self.assertEqual(str(unknown_obj), "Unknown object") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/tests/test_wireless.py new/pynetbox-6.4.1/tests/test_wireless.py --- old/pynetbox-6.3.0/tests/test_wireless.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pynetbox-6.4.1/tests/test_wireless.py 2021-12-22 03:07:03.000000000 +0100 @@ -0,0 +1,90 @@ +import unittest +import six + +import pynetbox +from .util import Response + +if six.PY3: + from unittest.mock import patch +else: + from mock import patch + + +api = pynetbox.api("http://localhost:8000") + +nb_app = api.wireless + +HEADERS = {"accept": "application/json;"} + + +class Generic(object): + class Tests(unittest.TestCase): + name = "" + ret = pynetbox.core.response.Record + app = "wireless" + + def test_get_all(self): + with patch( + "requests.sessions.Session.get", + return_value=Response(fixture="{}/{}.json".format(self.app, self.name)), + ) as mock: + ret = list(getattr(nb_app, self.name).all()) + self.assertTrue(ret) + self.assertTrue(isinstance(ret[0], self.ret)) + mock.assert_called_with( + "http://localhost:8000/api/{}/{}/".format( + self.app, self.name.replace("_", "-") + ), + params={"limit": 0}, + json=None, + headers=HEADERS, + ) + + def test_filter(self): + with patch( + "requests.sessions.Session.get", + return_value=Response(fixture="{}/{}.json".format(self.app, self.name)), + ) as mock: + ret = list(getattr(nb_app, self.name).filter(name="test")) + self.assertTrue(ret) + self.assertTrue(isinstance(ret[0], self.ret)) + mock.assert_called_with( + "http://localhost:8000/api/{}/{}/".format( + self.app, self.name.replace("_", "-") + ), + params={"name": "test", "limit": 0}, + json=None, + headers=HEADERS, + ) + + def test_get(self): + with patch( + "requests.sessions.Session.get", + return_value=Response( + fixture="{}/{}.json".format(self.app, self.name[:-1]) + ), + ) as mock: + ret = getattr(nb_app, self.name).get(1) + self.assertTrue(ret) + self.assertTrue(isinstance(ret, self.ret)) + mock.assert_called_with( + "http://localhost:8000/api/{}/{}/1/".format( + self.app, self.name.replace("_", "-") + ), + params={}, + json=None, + headers=HEADERS, + ) + + +class WirelessLansTestCase(Generic.Tests): + name = "wireless_lans" + + @patch( + "requests.sessions.Session.get", + return_value=Response(fixture="wireless/wireless_lan.json"), + ) + def test_repr(self, _): + wireless_lan_obj = nb_app.wireless_lans.get(1) + self.assertEqual(type(wireless_lan_obj), pynetbox.models.wireless.WirelessLans) + self.assertEqual(str(wireless_lan_obj), "SSID 1") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pynetbox-6.3.0/tests/unit/test_query.py new/pynetbox-6.4.1/tests/unit/test_query.py --- old/pynetbox-6.3.0/tests/unit/test_query.py 2021-12-04 23:55:21.000000000 +0100 +++ new/pynetbox-6.4.1/tests/unit/test_query.py 2021-12-22 03:07:03.000000000 +0100 @@ -5,9 +5,9 @@ from pynetbox.core.query import Request if six.PY3: - from unittest.mock import patch, Mock, call + from unittest.mock import Mock, call else: - from mock import patch, Mock, call + from mock import Mock, call class RequestTestCase(unittest.TestCase):