Repository: digitalocean/pynetbox
Pull request #238 (2020-05-14 14:50:55)

Rack Elevation Endpoint
Fixes issue #237 

However, not sure if a new endpoint is required or deleting the old one?

Potentially checking version for greater than 2.8?




Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f80ebf..1a94ab3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,78 @@
 
-For the list of changelog, please see the repository releases information in GitHub.
+v4.0.8 (2019-09-27)
 
+* [#165](https://github.com/digitalocean/pynetbox/issues/165) - Returns ContentError when 2XX response but not JSON.
+
+---
+
+v4.0.7 (2019-09-13)
+
+## Bug Fixes
+
+* [#156](https://github.com/digitalocean/pynetbox/issues/156) - Returns AllocationError when NetBox responds with a 204 to Allocation requests (Thanks @markkuleinio).
+* [#152](https://github.com/digitalocean/pynetbox/issues/152) - Makes App object pickleable (Thanks @xtelinco and @kartiksubbarao for testing).
+
+---
+
+v4.0.6 (2018-12-29)
+
+## Bug Fixes
+* [#137](https://github.com/digitalocean/pynetbox/issues/137) - Fixes behavior where appending an existing VLAN object id to tagged_vlans would cause .save() to still trigger a PATCH operation.
+
+---
+
+v4.0.5 (2018-12-14)
+
+## Bug Fixes
+* [#132](https://github.com/digitalocean/pynetbox/pull/132) - Fixes list comparison issue in `Record._diff`. 
+* [#134](https://github.com/digitalocean/pynetbox/issues/134) - Returns None from Endpoint.get() when no items are found instead of empty list from `.filter()`.
+
+---
+v4.0.4 (2018-12-07)
+
+## Bug Fixes
+* Fixes IndexError introduced by fix for #127 when field is empty list.
+
+---
+v4.0.3 (2018-12-07)
+
+## Bug Fixes
+* [#127](https://github.com/digitalocean/pynetbox/issues/127) - Fixes `__iter__` method on Record object so that it properly return lists record objects. Like tagged_vlans on for Interfaces.
+
+---
+
+v4.0.2 (2018-12-06)
+
+## Bug Fixes
+* [#126](https://github.com/digitalocean/pynetbox/issues/126) - Fixes TypeError when calling save on interfaces Record with tagged_vlans.
+
+---
+
+v4.0.1 (2018-12-06)
+
+## Bug Fixes
+* [#122](https://github.com/digitalocean/pynetbox/issues/122) - Adds missing authentication credentials for `.choices()`.
+
+
+---
+
+v4.0.0 (2018-12-04)
+
+## Enhancements
+
+* [#109](https://github.com/digitalocean/pynetbox/issues/109) - Clean up tests a bit.
+* Added cable endpoint support coming in NetBox 2.5.
+* Added some detail to the ValueError raised when `.get()` returns more than one object.
+* Added reserved kwargs to `.get()` and `.filter()` ("id", "pk", "limit", "offset").
+* Made RequestError more verbose when the NetBox API returns a json response. Also added more details when a 404 is returned (e.g. misspelled endpoints). 
+
+## API Changes
+
+* [#22](https://github.com/digitalocean/pynetbox/issues/22) - Switch to using PATCH instead of PUTs for updates. Also added an `.update()` method to Response objects that takes a dictionary to update multiple values on the object.
+* [#24](https://github.com/digitalocean/pynetbox/issues/24) - Add basic support for the `_choices` endpoint on each app by adding a `choices()` method to the App object.
+* [#108](https://github.com/digitalocean/pynetbox/issues/108) - Return `Record` objects from `.create()`.
+
+## Bug Fixes
+
+* [#88](https://github.com/digitalocean/pynetbox/issues/88) - Raise an exception now if `.filter()` is passed no kwargs.
+* [#90](https://github.com/digitalocean/pynetbox/issues/90) - Fixes some miscellaneous issues related to converting certain Record object's fields into netaddr.IPNetwork objects. That feature has been removed and it simply return strings now.
diff --git a/pynetbox/api.py b/pynetbox/api.py
index 32449d9..207b2a7 100644
--- a/pynetbox/api.py
+++ b/pynetbox/api.py
@@ -65,12 +65,6 @@ class App(object):
     def choices(self):
         """ Returns _choices response from App
 
-        .. note::
-
-            This method is deprecated and only works with NetBox version 2.7.x
-            or older. The ``choices()`` method in :py:class:`.Endpoint` is
-            compatible with all NetBox versions.
-
         :Returns: Raw response from NetBox's _choices endpoint.
         """
         if self._choices:
@@ -129,16 +123,14 @@ class Api(object):
     :py:class:`.App` which exposes endpoints as attributes.
 
     :type ssl_verify: bool or str
-    :param str url: The base URL to the instance of NetBox you
+    :param str url: The base url to the instance of Netbox you
         wish to connect to.
-    :param str token: Your NetBox token.
+    :param str token: Your netbox token.
     :param str,optional private_key_file: The path to your private
         key file.
     :param str,optional private_key: Your private key.
     :param bool/str,optional ssl_verify: Specify SSL verification behavior
         see: requests_.
-    :param bool,optional threading: Set to True to use threading in ``.all()``
-        and ``.filter()`` requests.
     :raises ValueError: If *private_key* and *private_key_file* are both
         specified.
     :raises AttributeError: If app doesn't exist.
diff --git a/pynetbox/models/dcim.py b/pynetbox/models/dcim.py
index 9ceade2..a057c16 100644
--- a/pynetbox/models/dcim.py
+++ b/pynetbox/models/dcim.py
@@ -119,6 +119,23 @@ class Racks(Record):
         """
         return RODetailEndpoint(self, "units", custom_return=RUs)
 
+    @property
+    def elevation(self):
+        """ Represents the ``elevation`` detail endpoint.
+
+        Returns a DetailEndpoint object that is the interface for
+        viewing response from the elevation endpoint updated in Netbox version 2.8.
+
+        :returns: :py:class:`.DetailEndpoint`
+
+        :Examples:
+
+        >>> rack = nb.dcim.racks.get(123)
+        >>> rack.elevation.list()
+        {"get_facts": {"interface_list": ["ge-0/0/0"]}}
+
+        """
+        return RODetailEndpoint(self, "elevation", custom_return=RUs)
 
 class Termination(Record):
     def __str__(self):


Test patch:
diff --git a/tests/test_dcim.py b/tests/test_dcim.py
index 7aed989..94001c9 100644
--- a/tests/test_dcim.py
+++ b/tests/test_dcim.py
@@ -401,6 +401,28 @@ class RackTestCase(Generic.Tests):
             isinstance(ret[0].device, pynetbox.models.dcim.Devices)
         )
 
+    @patch(
+        'pynetbox.core.query.requests.sessions.Session.get',
+        side_effect=[
+            Response(fixture='dcim/rack.json'),
+            Response(fixture='dcim/rack_u.json'),
+        ]
+    )
+    def test_get_elevation(self, mock):
+        test = nb.racks.get(1)
+        ret = test.elevation.list()
+        mock.assert_called_with(
+            'http://localhost:8000/api/dcim/racks/1/elevation/',
+            params={},
+            json=None,
+            headers=HEADERS,
+            verify=True,
+        )
+        self.assertTrue(ret)
+        self.assertTrue(
+            isinstance(ret[0].device, pynetbox.models.dcim.Devices)
+        )
+
 
 class RackRoleTestCase(Generic.Tests):
     name = 'rack_roles'