nautobot / pynautobot

Nautobot Python SDK
https://pynautobot.readthedocs.io/en/latest/index.html
Apache License 2.0
36 stars 32 forks source link

fix: Enhancement of __repr__ method (#67) #113

Closed nautics889 closed 1 year ago

nautics889 commented 1 year ago

Update Record class in pynautobot/core/response.py module. Add more detailed info the __repr__() method returns.

Example:

main.py:

def main():
    api_obj = api('http://localhost:8888',
                  token=os.environ.get('NAUTOBOT_API_TOKEN'))

    device = api_obj.dcim.devices.get('***')
    print(repr(device))

    print("=" * 79)

    interfaces_list = api_obj.dcim.interfaces.all()
    pprint(interfaces_list)

Output:

<pynautobot.models.dcim.Devices object (name='hAP lite router')>
===============================================================================
[<pynautobot.models.dcim.Interfaces object (name='test ethernet1/1 interface (ethernet1/1)')>,
 <pynautobot.models.dcim.Interfaces object (name='test ethernet1/2 interface (ethernet1/2)')>]
joewesch commented 1 year ago

@nautics889 thank you for the PR. Were there any design choices you made on the repr format or are you copying this pattern from somewhere else? I'm not used to seeing the word object in a repr, it's normally just <class_name at memory_location>.

nautics889 commented 1 year ago

@nautics889 thank you for the PR. Were there any design choices you made on the repr format or are you copying this pattern from somewhere else? I'm not used to seeing the word object in a repr, it's normally just <class_name at memory_location>.

@joewesch i've been considering what __repr__() returns in Python3

Python 3.8.10 (default, Apr  4 2023, 14:44:36) 
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class Bar:
...     pass
... 
>>> b = Bar()
>>> 
>>> b
<__main__.Bar object at 0x7ffabda20100>
>>> repr(b)
'<__main__.Bar object at 0x7ffabda20100>'

implying b is an object of class Bar. In Python2.x the word instance was used instead:

Python 2.7.18 (default, Apr  4 2023, 14:46:24) 
[GCC 9.4.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class Bar:
...     pass
... 
>>> b = Bar()
>>> b
<__main__.Bar instance at 0x7f9d2b34c190>

Although i've missed memory location in the implementation, i can add one if it matters (like hex(id(self)))


According to Python docs __repr__() should return whether a string which can fully recreate same object or "a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object".

I wouldn't say in this case __repr__() should return string for re-creating the object. So i'd make the next implemention (without word 'object' like you've suggested):

class Record(object):
...
def __repr__(self):
    "<{}.{} at {} (name='{}')>".format(self.__class__.__module__, self.__class__.__name__, hex(id(self)), self)
...

>>> print(repr(obj))  # for example
<pynautobot.models.dcim.Devices at 0x7f9d2b34c190 (name='test1-switch1')>
...

I'll update the PR in a few hours...

nautics889 commented 1 year ago

Done.

The result would look like:

<pynautobot.models.dcim.Devices name='hAP lite router' at 0x1953d8bcf40>

@joewesch could you please have a look at https://github.com/nautobot/pynautobot/pull/113/commits/cc32152c98659eadece8fe77c89f90315f289485?

nautics889 commented 1 year ago

@joewesch thanks for review!