Juan Gomez avatar Juan Gomez committed d18adb5

Introduced changes to comply with with PEP 257

Comments (0)

Files changed (1)

-# newsfetcher.py - fetches news from an NNTP group and sends them by email
-#
-# Copyright 2010 Juan Gomez <juandg@gmail.com>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2, incorporated herein by reference.
+"""newsfetcher.py - fetches news from an NNTP group and sends them by email
+
+Copyright 2010 Juan Gomez <juandg@gmail.com>
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2, incorporated herein by reference.
+
+"""
 
 
 from datetime import datetime, timedelta
 from nntplib import NNTP, NNTPError
-from smtplib import SMTP
+from smtplib import SMTP, SMTPException
 from email.mime.text import MIMEText
 from email.mime.multipart import MIMEMultipart
 
 
 
 class ProtocolProxy():
-    '''Base class for all protocol proxies. It acts a litle bit as a factory
-    because it's really the one that instantiates the actual protocol it also
-    aides in testing'''
+    """Base class for all protocol proxies.
+
+    It acts almost as a factory because it instantiates the actual protocol,
+    It also aides in testing as a Mock protocol can be easily passed as
+    argument to the constructor.
+
+    Keyword arguments:
+    protocol: class warpping unerliting protocol
+    server_uri: The uri of a server supporting the given protocol
+    port: port used by the server to listen for rquests
+
+    """
 
     def __init__(self, protocol, server_uri, port):
         self.uri = server_uri
         self.port = port
         self.server = protocol(self.uri, self.port)
 
+
 class NNTPGroupProxy(ProtocolProxy):
-    '''Proxy class for the NNTP news group'''
+    """Proxy class for the NNTP newsgroup."""
 
     def __init__(self, nntp_server_uri, name, port=119):
         try:
         except NNTPError as error:
             print(error)
         else:
-            resp, self.post_count, self.first_id, self.last_id, self.name = \
-                                                self.server.group(name)
+            resp, self.post_count, self.first_id, self.last_id, self.name =\
+            self.server.group(name)
 
     def get_new_news(self, date):
-        '''gets all the newsgroup post that have a date later than the
-        supplied 'date'
+        """Get all posts with a date later or equal to 'date'
 
-        This is a very powerful generator method that showcases all the
-        strenghts of Python it returns an iterator (via the 'yields' keyword)
-        and it uses the power of Python's functional programming to filter all
-        the posts headers'''
+        This is a very neat method that showcases some of the functional
+        strenghts of Python. It's a generator method, so it returns an iterator
+        (via the 'yield' keyword) and it uses the power of lambda functions and
+        the 'filter' and 'map' built-in functions to filter all the posts and
+        their headers
 
+        """
         self.date = date
         resp, subject_list = self.server.xhdr('subject', self.first_id + '-' +
                                                          self.last_id)
         for id, date_header in filter(self.__is_new_post,
                                       map(self.__get_post_date, subject_list)):
-            yield NNTPNewsPost(self, id)
+            yield NNTPNewsPost(nntp_proxy=self, post_id=id)
 
     def __is_new_post(self, date_header):
+        """Determine if post is newer than the supplied date."""
         id, str_date = date_header
         return datetime.strptime(str_date.lstrip('Date: ')[:-6],
                                  '%a, %d %b %Y %H:%M:%S') >= self.date
 
     def __get_post_date(self, subject):
+        """Filter all headers and return only the post Id and date header."""
         id, str_subject = subject
-        return (id, filter(self.__get_date_header, self.server.head(id)[3])[0])
-
-    def __get_date_header(self, header):
-        return header.startswith('Date')
+        return (id, filter(lambda header: header.startswith('Date'),
+                           self.server.head(id)[3])[0])
 
 
 class NNTPNewsPost:
-    '''Helper class to encapsultae the fetching of the actual NNTP post'''
+    """Helper class to encapsultae the fetching of the actual NNTP post.
 
-    def __init__(self, nntp_proxy, id):
+    Keyword arguments:
+    nntp_proxy: The proxy object wrapping the NNTP header
+    post_id: The Id of the newsgroup post
+
+    """
+
+    def __init__(self, nntp_proxy, post_id):
         self.__proxy = nntp_proxy
-        self.msg_id = id
+        self.msg_id = post_id
 
     def get_post_body(self):
-        resp, line_count, self.msg_id, message = \
-                                        self.__proxy.server.body(self.msg_id)
+        resp, line_count, self.msg_id, message =\
+        self.__proxy.server.body(self.msg_id)
         return message
 
     def get_post_headers(self):
-        resp, header_count, self.msg_id, headers = \
-                                        self.__proxy.server.head(self.msg_id)
+        resp, header_count, self.msg_id, headers =\
+        self.__proxy.server.head(self.msg_id)
         return headers
 
 
 class EmailProxy(ProtocolProxy):
-    '''Proxy class for the email server'''
+    """Proxy class for the email server."""
 
     def __init__(self, smtp_server_uri, smtp_username, smtp_password,
                  port=587):
-        ProtocolProxy.__init__(self, SMTP, smtp_server_uri, port)
         self.user = smtp_username
         self.password = smtp_password
+        try:
+            ProtocolProxy.__init__(self, SMTP, smtp_server_uri, port)
+        except SMTPException as error:
+            print(error)
 
     def send_msg(self, from_, to_, subject, body):
+        """Send email message using the SMTP server.
+
+        Keyword arguments:
+        from_: the originating email address
+        to_: a string of email addresses separated by comma
+        subject: the email's subject line
+        body: the plain text body of the email message
+
+        """
         self.server.ehlo()
         self.server.starttls()
         self.server.ehlo()
 
 
 def main():
-    '''Main execution of the News Fetcher program'''
+    """Main execution of the News Fetcher program."""
 
-    nntp_uri = 'news.cs.mum.edu'
-    nntp_group = 'courses.de.cs425'
+    nntp_uri = 'news.cs.mum.edu'    # Uri of the NNTP news server
+    nntp_group = 'courses.de.cs425' # name of the newsgroup on the above server
 
-    smtp_uri = 'smtp.gmail.com'
-    smtp_user = '<user>@gmail.com'
-    smtp_password = '<password>'
+    smtp_uri = 'smtp.gmail.com'     # Uri of the SMTP email server
+    smtp_user = '<you>@gmail.com'  # username on the SMTP server
+    smtp_password = '<password>'  # password of the provided user name
 
     news_proxy = NNTPGroupProxy(nntp_server_uri=nntp_uri, name=nntp_group)
-    diff = timedelta(days=-2)
-    last_date = datetime.now() + diff
+    diff = timedelta(days=-5)  # establish the span of time to search for posts
+    last_date = datetime.now() + diff # calculate date based on today's date
     message_body = ''
     for post in news_proxy.get_new_news(last_date):
-        message_body += '\n'.join(post.get_post_headers()) + '\n' + \
-                        '\n'.join(post.get_post_body()) + \
+        message_body += '\n'.join(post.get_post_headers()) + '\n' +\
+                        '\n'.join(post.get_post_body()) +\
                         '\n \n-----new message-----\n\n'
 
     mail_proxy = EmailProxy(smtp_server_uri=smtp_uri,
                             smtp_username=smtp_user,
                             smtp_password=smtp_password)
 
-    sender = '<user>@gmail.com'
-    recipients = '<someone@email.com>'
+    sender = '<you>@gmail.com'         # originating email
+    recipients = '<one@email.com>'  # list of recipients separated by comma
     subject = 'Latest Posts on \'courses.de.cs425\''
     mail_proxy.send_msg(from_=sender, to_=recipients, subject=subject,
-                       body=message_body[:-25])
+                        body=message_body[:-25])
 
 
 if __name__ == '__main__':
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.