2

I want to have a class that represents an IMAP connection and use it with a with statement as follows:

class IMAPConnection:
    def __enter__(self):
        connection = imaplib.IMAP4_SSL(IMAP_HOST)

        try:
            connection.login(MAIL_USERNAME, MAIL_PASS)
        except imaplib.IMAP4.error:
            log.error('Failed to log in')

        return connection

    def __exit__(self, type, value, traceback):
        self.close()

with IMAPConnection() as c:
    rv, data = c.list()
    print(rv, data)

Naturally this fails since IMAPConnections has no attribute close. How can I store the connection and pass it to the __exit__ function when the with statement is finished?

mart1n
  • 5,969
  • 5
  • 46
  • 83

2 Answers2

4

You need to store connection in object attributes. Something like this:

class IMAPConnection:
    def __enter__(self):
        self.connection = imaplib.IMAP4_SSL(IMAP_HOST)

        try:
            self.connection.login(MAIL_USERNAME, MAIL_PASS)
        except imaplib.IMAP4.error:
            log.error('Failed to log in')

        return self.connection

    def __exit__(self, type, value, traceback):
        self.connection.close()

You would also want to implement list method for you class.

Edit: I just now realized what your actual problem is. when you do with SomeClass(*args, **kwargs) as c c is not a value returned by __enter__ method. c is instance of SomeClass. That's a root of your problem you returned connection from __enter__ and assumed that c is said connection.

Darth Kotik
  • 2,261
  • 1
  • 20
  • 29
0

You need to implement a __exit__() function within your IMAPConnection class.

__enter__() function is called before executing the code within the with block where as __exit__() is called while exiting the with block.

Below is the sample structure:

def __exit__(self, exc_type, exc_val, exc_tb):
    # Close the connection and other logic applicable
    self.connection.close()

Check: Explaining Python's 'enter' and 'exit' for more information.

Community
  • 1
  • 1
Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126