jeremyschulman / netbox-pyswagger

Python Swagger client for Netbox
MIT License
18 stars 4 forks source link

Python3 Not Compatible #5

Closed bdlamprecht closed 6 years ago

bdlamprecht commented 6 years ago

This is just for reference as the issue was discussed via a DM in the Slack channel NetworkToCode. There are no changes to what occurred in that conversation. The only additional information I'm including here is the full traceback I encountered.

When using python3 in jupyter notebook and following your YouTube video, the following error is seen in step [5] and [6]:

[5] rqst = netbox.request.ipam.ipam_vlans_create
[6] rqst
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/.virtualenvs/jupyter/lib/python3.5/site-packages/IPython/core/formatters.py in __call__(self, obj)
    700                 type_pprinters=self.type_printers,
    701                 deferred_pprinters=self.deferred_printers)
--> 702             printer.pretty(obj)
    703             printer.flush()
    704             return stream.getvalue()

~/.virtualenvs/jupyter/lib/python3.5/site-packages/IPython/lib/pretty.py in pretty(self, obj)
    393                             if callable(meth):
    394                                 return meth(obj, self, cycle)
--> 395             return _default_pprint(obj, self, cycle)
    396         finally:
    397             self.end_group()

~/.virtualenvs/jupyter/lib/python3.5/site-packages/IPython/lib/pretty.py in _default_pprint(obj, p, cycle)
    508     if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
    509         # A user-provided repr. Find newlines and replace them with p.break_()
--> 510         _repr_pprint(obj, p, cycle)
    511         return
    512     p.begin_group(1, '<')

~/.virtualenvs/jupyter/lib/python3.5/site-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
    699     """A pprint that just redirects to the normal repr function."""
    700     # Find newlines and replace them with p.break_()
--> 701     output = repr(obj)
    702     for idx,output_line in enumerate(output.splitlines()):
    703         if idx:

~/.virtualenvs/jupyter/lib/python3.5/site-packages/halutz/request.py in __repr__(self)
    111             'path': self.path,
    112             'params': self.params.keys()
--> 113         }, indent=3)

/usr/lib/python3.5/json/__init__.py in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    235         check_circular=check_circular, allow_nan=allow_nan, indent=indent,
    236         separators=separators, default=default, sort_keys=sort_keys,
--> 237         **kw).encode(obj)
    238 
    239 

/usr/lib/python3.5/json/encoder.py in encode(self, o)
    198         chunks = self.iterencode(o, _one_shot=True)
    199         if not isinstance(chunks, (list, tuple)):
--> 200             chunks = list(chunks)
    201         return ''.join(chunks)
    202 

/usr/lib/python3.5/json/encoder.py in _iterencode(o, _current_indent_level)
    427             yield from _iterencode_list(o, _current_indent_level)
    428         elif isinstance(o, dict):
--> 429             yield from _iterencode_dict(o, _current_indent_level)
    430         else:
    431             if markers is not None:

/usr/lib/python3.5/json/encoder.py in _iterencode_dict(dct, _current_indent_level)
    401                 else:
    402                     chunks = _iterencode(value, _current_indent_level)
--> 403                 yield from chunks
    404         if newline_indent is not None:
    405             _current_indent_level -= 1

/usr/lib/python3.5/json/encoder.py in _iterencode(o, _current_indent_level)
    434                     raise ValueError("Circular reference detected")
    435                 markers[markerid] = o
--> 436             o = _default(o)
    437             yield from _iterencode(o, _current_indent_level)
    438             if markers is not None:

/usr/lib/python3.5/json/encoder.py in default(self, o)
    177 
    178         """
--> 179         raise TypeError(repr(o) + " is not JSON serializable")
    180 
    181     def encode(self, o):

TypeError: dict_keys(['data']) is not JSON serializable

When the same steps are done using python2, this error does NOT occur.

No rush on solving this, I'm good with using this workaround for now. Much appreciated. :smile:

bdlamprecht commented 6 years ago

With the changes made on branch py3, the functionality works when following along with your tutorial. I haven't had the chance yet to fully test everything else out yet and not sure when I'll get to do that.

I installed it in my virtualenv with this command:

pip install -e git+http://github.com/jeremyschulman/halutz.git@py3#egg=halutz

The only difference I noticed was in the call for body.keys() (step [8] in the tutorial, step [7] in my reproduction) is formatted differently and not, in my opinion, as cleanly (my screenshot below):

image

I'm not sure if that is an inherit difference between py2 and py3, but thought I would mention it.

Again, this is just a cosmetic issue, not a functionality problem and if you feel comfortable merging it as it currently stands, I'd be okay with that.

Thanks again for making the necessary changes so quickly.

jeremyschulman commented 6 years ago

@bdlamprecht - ah, re showing the ".keys()" - this is indeed a function of Py3 vs. Py2. You can get the same "effect" by doing using list() on the body. For example:

In [6]: list(rqst.body)
Out[6]: 
['bound_to',
 'description',
 'virtual_gateway_ipv4',
 'vn_id',
 'virtual_mac',
 'label',
 'l3_connectivity',
 'svi_ips',
 'ipv4_subnet',
 'vn_type',
 'endpoints',
 'dhcp_service']
bdlamprecht commented 6 years ago

Yeah, not real familiar with all of the differences between py2 and py3, but your example above works for me.

FYI, the variables you used in the tutorial are different than the ones you used above, so for my reference only, it should be the following:

In  [7]: list(body.keys())
Out [7]: 
['group',
 'site',
 'vid',
 'tenant',
 'status',
 'role',
 'custom_fields',
 'name',
 'description']

Again, thanks a bunch!