0

I have following class in file1.py

class api:
  def server(self):
    DEFAULT_SERVER = socket.gethostname()
    try:
      SATELLITE_SERVER = raw_input('Enter RedHat Satellite Server Name [%s]: ' % DEFAULT_SERVER)
    except KeyboardInterrupt:
      print ""
      sys.exit(1)
    if not SATELLITE_SERVER:
      SATELLITE_SERVER = DEFAULT_SERVER
    try:
      SATELLITE_URL = 'http://' + SATELLITE_SERVER + '/rpc/api'
      CLIENT = xmlrpclib.Server(SATELLITE_URL, verbose=0)
      print "Welcome to RedHat Satellite Server %s" % CLIENT.api.systemVersion()
    except socket.error, e:
      print "Incorrect Server Name -", e
      sys.exit(1)
    return CLIENT

  def username(self):
    DEFAULT_LOGIN = getpass.getuser()
    try:
      SATELLITE_LOGIN = raw_input("Enter RedHat Satellite Login Name [%s]: " % DEFAULT_LOGIN)
    except KeyboardInterrupt:
      print ""
      sys.exit(1)
    if not SATELLITE_LOGIN:
      SATELLITE_LOGIN = DEFAULT_LOGIN
    return SATELLITE_LOGIN

  def password(self):
    try:
      SATELLITE_PASSWORD = getpass.getpass("Enter Your Password: ")
    except KeyboardInterrupt:
      print ""
      sys.exit(1)
    if not SATELLITE_PASSWORD:
      self.password()
    return SATELLITE_PASSWORD

  def __init__(self):
    CLIENT = self.server()
    SATELLITE_LOGIN = self.username()
    SATELLITE_PASSWORD = self.password()
    KEY = CLIENT.auth.login(SATELLITE_LOGIN, SATELLITE_PASSWORD)

  def __new__(self):
    return (self.KEY, self.CLIENT)

And I am calling this class in file2.py,

KEY, CLIENT = file1.api()
print KEY
print CLIENT

When I execute the file2.py then I get the error,

Traceback (most recent call last):
  File "./test.py", line 24, in <module>
    KEY, CLIENT = satelliteapi.api()
TypeError: iteration over non-sequence

I am not sure what I am doing wrong, may be something around retuning the values from the class, may be new is not the right way to return in this case. Please help.

8
  • What does satlliteapi.api() return? Commented Jul 23, 2014 at 17:46
  • what version of python is this? Commented Jul 23, 2014 at 17:47
  • where is satelliteapi coming from? Also what are self.KEY and self.CLIENT? Commented Jul 23, 2014 at 17:49
  • Class instantiation should always return an instance of the class (as you could imagine). If you just want the tuple, why don't you just use a function that creates both objects (CLIENT and KEY) and returns them instead of a class? Commented Jul 23, 2014 at 17:51
  • Sorry @Hoopdady and Padraic that was typo, I have corrected that. It is file1.api() Commented Jul 23, 2014 at 17:54

1 Answer 1

1

Essentially, overriding __new__ is not the way you should go about doing what you are doing. If you simply want to make it so you can easily unpack the KEY and CLIENT values, you can do the following:

class api(object):
....
def __iter__(self):
    return (value for value in (self.KEY, self.CLIENT))

__iter__ is the special method that defines if a class may be iterated over. It returns an iterator instance (in this case, a generator) that can be used as a 'sequence' representation of an object. This question has a good explanation of the topic.

If you wanted to make it even more explicit, you can do:

class api(object):
....
def get_key_and_client(self):
    return self.KEY, self.CLIENT
def __iter__(self):
    return (value for value in self.get_key_and_client())

This lets you get the same information without needing to actually use the iterator, and makes the iterator an alias of the get_key_and_client() method.

Sign up to request clarification or add additional context in comments.

2 Comments

Got an error TypeError: __iter__ returned non-iterator of type 'tuple'after chaning to __iter__ so end up using the suggestion of @javidcf to use function instead of class.
@SGL Yeah, sorry, I forgot the __iter__ command wouldn't propagate the unpack to to the returned tuple. I edited the answer to correct, but definitely have a method as per javidcf's answer or my second example is the more clear option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.