Search code examples
pythonpython-3.xnamedtupletelnetlib

Using static NamedTuples variables outside of class in a function


I'm using a NamedTuple to define a server to which I want to connect using telnetlib. Then I created a class which defines the connection to the server, with the server details and connection method inside the class. Then outside of the class, I want to use the connection method with the server's NamedTuple as connection credentials. However I keep getting the Error that the connection method is missing the NamedTuple argument.

I've tried pulling the NamedTuple outside of the class, tried to put the Namedtuple inside the init method of the class. nothing seems to work.

This is my code:

import telnetlib
from typing import NamedTuple

class Unit(NamedTuple):
    name: str
    ip: str
    port: str

    def printunit(self, unit):
        print(unit.name)
        print(unit.ip)
        print(unit.port)

class TnCnct:
    Server1 = Unit("Server1", "1.1.1.1", "23")
    Server2 = Unit("Server2", "2.2.2.2", "23")
    Server3 = Unit("Server3", "3.3.3.3", "23")

    def __init__(self):
        pass

    def cnct(self, u):
        try:
            tn = telnetlib.Telnet(u.ip, u.port, 10)
            tn.open(u.ip, u.port)
            tn.close()
            response = u.name + " " + "Success!"
        except Exception as e:
            response = u.name + " " + "Failed!"
            print(e)
        finally:
            print(response)


TnCnct.cnct(TnCnct.Server1)

The exact Error I get:

TypeError: cnct() missing 1 required positional argument: 'u'

Solution

  • 1. You might want to use namedtuples from collections - not typing:

    namedtuples:

    Returns a new tuple subclass named typename. The new subclass is used to create tuple-like objects that have fields accessible by attribute lookup as well as being indexable and iterable. Instances of the subclass also have a helpful docstring (with typename and field_names) and a helpful repr() method which lists the tuple contents in a name=value format.

    vs typing:

    This module supports type hints as specified by PEP 484 and PEP 526. The most fundamental support consists of the types Any, Union, Tuple, Callable, TypeVar, and Generic. For full specification please see PEP 484. For a simplified introduction to type hints see PEP 483.

    The typing NamedTuples are just a wrapper around the original namedtuples.

    2. You need instances to use instancemethods:

    Fixes for both:

    import telnetlib
    from collections import namedtuple
    
    def printunit(self, unit):
        print(unit.name)
        print(unit.ip)
        print(unit.port)
    
    Unit = namedtuple("Unit","name ip port")
    Unit.printunit = printunit 
    
    class TnCnct:
        Server1 = Unit("Server1", "1.1.1.1", "23")
        Server2 = Unit("Server2", "2.2.2.2", "23")
        Server3 = Unit("Server3", "3.3.3.3", "23")
    
        def __init__(self):
            pass
    
        def cnct(self, u):
            try:
                tn = telnetlib.Telnet(u.ip, u.port, 10)
                tn.open(u.ip, u.port)
                tn.close()
                response = u.name + " " + "Success!"
            except Exception as e:
                response = u.name + " " + "Failed!"
                print(e)
            finally:
                print(response)
    
    # create a class instance and use the cnct method of it 
    connector = TnCnct()
    connector.cnct(TnCnct.Server1)
    

    The difference between instance and class (methods/variables) is detailed f.e. here: