EPOLLERR and EPOLLHUP never happens in the code pasted in the post is because they've always occurred in conjunction with an EPOLLIN or an EPOLLOUT (several of these can be set at once), so the if/then/else have always picked up an EPOLLIN or EPOLLOUT.
Experimenting I've found that EPOLLHUP only happens in conjunction with EPOLLERR, the reason for this may be the way python interfaces with epoll and lowlevel IO, normally recv would return a -1 and set errno to EAGAIN when nothing is available on a non-blocking recv, however python uses '' (nothing returned) to signal EOF.
Closing your telnet-session only closes that end of the tcp-connection, so it's still perfectly valid to call recv on your side, there may be pending data in the tcp receive buffers which your application hasn't read yet so that won't trigger an error-condition.
It seems that EPOLLIN and a recv that returns an empty string is indicative of the other end having closed the connection, however, using an older version of python (before epoll were introduced) and plain select on a pipe, I've experienced that a read that returned '' did not indicate EOF just a lack of available data.