Skip to content

Commit 2cada45

Browse files
author
Zach Moody
authored
Merge pull request #121 from digitalocean/4-0-release
4.0 Release
2 parents 4270d62 + 31f20dd commit 2cada45

37 files changed

+1842
-1015
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
3+
v4.0.0 (2018-12-04)
4+
5+
## Enhancements
6+
7+
* [#109](https://github.com/digitalocean/pynetbox/issues/109) - Clean up tests a bit.
8+
* Added cable endpoint support coming in NetBox 2.5.
9+
* Added some detail to the ValueError raised when `.get()` returns more than one object.
10+
* Added reserved kwargs to `.get()` and `.filter()` ("id", "pk", "limit", "offset").
11+
* 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).
12+
13+
## API Changes
14+
15+
* [#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.
16+
* [#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.
17+
* [#108](https://github.com/digitalocean/pynetbox/issues/108) - Return `Record` objects from `.create()`.
18+
19+
## Bug Fixes
20+
21+
* [#88](https://github.com/digitalocean/pynetbox/issues/88) - Raise an exception now if `.filter()` is passed no kwargs.
22+
* [#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.

MANIFEST.in

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/IPAM.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
IPAM
22
========
33

4-
.. autoclass:: pynetbox.ipam.Prefixes
4+
.. autoclass:: pynetbox.models.ipam.Prefixes
55
:members:

docs/conf.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
#
1919
import os
2020
import sys
21+
from pkg_resources import get_distribution
2122
sys.path.insert(0, os.path.abspath('../'))
22-
import pynetbox
2323

2424

2525
# -- General configuration ------------------------------------------------
@@ -53,11 +53,11 @@
5353
# The version info for the project you're documenting, acts as replacement for
5454
# |version| and |release|, also used in various other places throughout the
5555
# built documents.
56+
# The full version, including alpha/beta/rc tags.
57+
release = get_distribution('pynetbox').version
5658
#
5759
# The short X.Y version.
58-
version = pynetbox.__version__
59-
# The full version, including alpha/beta/rc tags.
60-
release = pynetbox.__version__
60+
version = '.'.join(release.split('.')[:2])
6161

6262
# The language for content autogenerated by Sphinx. Refer to documentation
6363
# for a list of supported languages.

docs/endpoint.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Endpoint
22
========
33

4-
.. autoclass:: pynetbox.lib.endpoint.Endpoint
4+
.. autoclass:: pynetbox.core.endpoint.Endpoint
55
:members:
66

7-
.. autoclass:: pynetbox.lib.endpoint.DetailEndpoint
7+
.. autoclass:: pynetbox.core.endpoint.DetailEndpoint
88
:members:

docs/index.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
request
88
IPAM
99

10+
TL;DR
11+
=====
12+
Instantiate the :py:class:`.Api`. Use the methods available on :py:class:`.Endpoint` to return :py:class:`.Record` objects.
1013

1114
API
1215
===
@@ -18,7 +21,7 @@ App
1821
===
1922

2023
.. autoclass:: pynetbox.api.App
21-
24+
:members:
2225

2326
Indices and tables
2427
==================

docs/request.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Request
22
========
33

4-
.. autoclass:: pynetbox.lib.query.RequestError
4+
.. autoclass:: pynetbox.core.query.RequestError
55
:members:

docs/response.rst

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
Response
22
========
33

4-
.. autoclass:: pynetbox.lib.response.Record
5-
:members:
6-
7-
.. autoclass:: pynetbox.lib.response.IPRecord
4+
.. autoclass:: pynetbox.core.response.Record
85
:members:

pynetbox/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from pkg_resources import get_distribution, DistributionNotFound
22

3+
from pynetbox.core.query import RequestError
34
from pynetbox.api import Api as api
4-
from pynetbox.lib import RequestError
55

66
try:
77
__version__ = get_distribution(__name__).version

pynetbox/api.py

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
'''
1+
"""
22
(c) 2017 DigitalOcean
33
44
Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,9 +12,10 @@
1212
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
15-
'''
16-
from pynetbox.lib import Endpoint, Request
17-
from pynetbox import dcim, ipam, virtualization, circuits
15+
"""
16+
from pynetbox.core.endpoint import Endpoint
17+
from pynetbox.core.query import Request
18+
from pynetbox.models import dcim, ipam, virtualization, circuits
1819

1920

2021
class App(object):
@@ -26,16 +27,30 @@ class App(object):
2627
:raises: :py:class:`.RequestError`
2728
if requested endpoint doesn't exist.
2829
"""
29-
def __init__(self, app, api_kwargs=None):
30-
self.app = app
31-
self.api_kwargs = api_kwargs
30+
31+
def __init__(self, api, name, model=None):
32+
self.api = api
33+
self.name = name
34+
self.model = model
35+
self._choices = None
3236

3337
def __getattr__(self, name):
34-
return Endpoint(
35-
name,
36-
api_kwargs=self.api_kwargs,
37-
app=self.app
38-
)
38+
return Endpoint(self.api, self, name, model=self.model)
39+
40+
def choices(self):
41+
""" Returns _choices response from App
42+
43+
:Returns: Raw response from NetBox's _choices endpoint.
44+
"""
45+
if self._choices:
46+
return self._choices
47+
48+
self._choices = Request(
49+
base="{}/{}/_choices/".format(self.api.base_url, self.name),
50+
ssl_verify=self.api.ssl_verify,
51+
).get()
52+
53+
return self._choices
3954

4055

4156
class Api(object):
@@ -83,44 +98,44 @@ class Api(object):
8398
.. _requests: http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification
8499
""" # noqa
85100

86-
def __init__(self, url, token=None, private_key=None,
87-
private_key_file=None, version=None, ssl_verify=True):
101+
def __init__(
102+
self,
103+
url,
104+
token=None,
105+
private_key=None,
106+
private_key_file=None,
107+
ssl_verify=True,
108+
):
88109
if private_key and private_key_file:
89110
raise ValueError(
90111
'"private_key" and "private_key_file" cannot be used together.'
91112
)
92-
base_url = "{}/api".format(url if url[-1] != '/' else url[:-1])
93-
94-
self.api_kwargs = {
95-
"token": token,
96-
"private_key": private_key,
97-
"private_key_file": private_key_file,
98-
"base_url": base_url,
99-
"ssl_verify": ssl_verify,
100-
}
101-
102-
if self.api_kwargs.get('private_key_file'):
103-
with open(self.api_kwargs.get('private_key_file'), 'r') as kf:
113+
base_url = "{}/api".format(url if url[-1] != "/" else url[:-1])
114+
self.token = token
115+
self.private_key = private_key
116+
self.private_key_file = private_key_file
117+
self.base_url = base_url
118+
self.ssl_verify = ssl_verify
119+
self.session_key = None
120+
121+
if self.private_key_file:
122+
with open(self.private_key_file, "r") as kf:
104123
private_key = kf.read()
105-
self.api_kwargs.update(private_key=private_key)
106-
if not version:
107-
version = Request(base=base_url,
108-
ssl_verify=ssl_verify).get_version()
109-
self.api_kwargs.update(version=version)
124+
self.private_key = private_key
110125

111126
req = Request(
112127
base=base_url,
113128
token=token,
114129
private_key=private_key,
115-
ssl_verify=ssl_verify
130+
ssl_verify=ssl_verify,
116131
)
117-
if token and private_key:
118-
self.api_kwargs.update(session_key=req.get_session_key())
119-
120-
self.dcim = App(dcim, api_kwargs=self.api_kwargs)
121-
self.ipam = App(ipam, api_kwargs=self.api_kwargs)
122-
self.circuits = App(circuits, api_kwargs=self.api_kwargs)
123-
self.secrets = App('secrets', api_kwargs=self.api_kwargs)
124-
self.tenancy = App('tenancy', api_kwargs=self.api_kwargs)
125-
self.extras = App('extras', api_kwargs=self.api_kwargs)
126-
self.virtualization = App(virtualization, api_kwargs=self.api_kwargs)
132+
if self.token and self.private_key:
133+
self.session_key = req.get_session_key()
134+
135+
self.dcim = App(self, "dcim", model=dcim)
136+
self.ipam = App(self, "ipam", model=ipam)
137+
self.circuits = App(self, "circuits", model=circuits)
138+
self.secrets = App(self, "secrets", model=None)
139+
self.tenancy = App(self, "tenancy", model=None)
140+
self.extras = App(self, "extras", model=None)
141+
self.virtualization = App(self, "virtualization", model=virtualization)

0 commit comments

Comments
 (0)