wxPyMail - Tutorial Application comments

Hi,

I finally got done putting together a tutorial using a real live wxPython application. It is (unfortunately) a Windows-only application that one can use for sending (but not receiving) emails. It was created to catch the "mailto" event from internet browsers and redirect that data to my script. I won't be too surprised if you find a bug here and there since I only tested it on XP. You may also need to tell your firewall(s) to let it send your emails.

I have posted it to my blog here:

http://www.blog.pythonlibrary.org/?p=38

The tutorial is a little code heavy, but I think I explain the most important bits. I am hoping for some constructive comments for making the code and/or the tutorial better. I could have went into depth on a lot of what's in there, but it ended up being so long that I thought it was a little overwhelming as it was.

Someone on this list was wanting to know about login dialogs... well, this application uses one so if they still need help in getting their mind around that, they can check it out.

···

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

Mike this is some fabulous stuff. Thank you for sharing it. I have it
bookmarked for future reference.

If I could suggest one change it would be that you use named
parameters on as many of your wx.Method() calls as possible. I've
found my own code much more readable and self-explanatory since I use
every named parameter I can get my hands on.

···

On Sun, Aug 17, 2008 at 10:39 AM, Mike Driscoll <mike@pythonlibrary.org> wrote:

Hi,

I finally got done putting together a tutorial using a real live wxPython
application. It is (unfortunately) a Windows-only application that one can
use for sending (but not receiving) emails. It was created to catch the
"mailto" event from internet browsers and redirect that data to my script. I
won't be too surprised if you find a bug here and there since I only tested
it on XP. You may also need to tell your firewall(s) to let it send your
emails.

I have posted it to my blog here:

wxPyMail: Creating an Application to Send Emails - Mouse Vs Python

The tutorial is a little code heavy, but I think I explain the most
important bits. I am hoping for some constructive comments for making the
code and/or the tutorial better. I could have went into depth on a lot of
what's in there, but it ended up being so long that I thought it was a
little overwhelming as it was.

Someone on this list was wanting to know about login dialogs... well, this
application uses one so if they still need help in getting their mind around
that, they can check it out.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

--
Stand Fast,
tjg. [Timothy Grant]

Timothy Grant wrote:

  

Hi,

I finally got done putting together a tutorial using a real live wxPython
application. It is (unfortunately) a Windows-only application that one can
use for sending (but not receiving) emails. It was created to catch the
"mailto" event from internet browsers and redirect that data to my script. I
won't be too surprised if you find a bug here and there since I only tested
it on XP. You may also need to tell your firewall(s) to let it send your
emails.

I have posted it to my blog here:

wxPyMail: Creating an Application to Send Emails - Mouse Vs Python

The tutorial is a little code heavy, but I think I explain the most
important bits. I am hoping for some constructive comments for making the
code and/or the tutorial better. I could have went into depth on a lot of
what's in there, but it ended up being so long that I thought it was a
little overwhelming as it was.

Someone on this list was wanting to know about login dialogs... well, this
application uses one so if they still need help in getting their mind around
that, they can check it out.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org
    
Mike this is some fabulous stuff. Thank you for sharing it. I have it
bookmarked for future reference.

If I could suggest one change it would be that you use named
parameters on as many of your wx.Method() calls as possible. I've
found my own code much more readable and self-explanatory since I use
every named parameter I can get my hands on.

Just to clarify, you think I should do something like this:

self.parseURL(url="http://www.python.org")

instead of

self.parseURL("http://www.python.org")

correct?

Fortunately, most of my methods are event methods so they don't really support that, but I'll definitely keep this in mind when I refactor the code for my Linux version.

Mike

···

On Sun, Aug 17, 2008 at 10:39 AM, Mike Driscoll <mike@pythonlibrary.org> wrote:

Mike Driscoll wrote:

Hi,

I finally got done putting together a tutorial using a real live
wxPython application. It is (unfortunately) a Windows-only application
that one can use for sending (but not receiving) emails. It was created
to catch the “mailto” event from internet browsers and redirect that
data to my script. I won’t be too surprised if you find a bug here and
there since I only tested it on XP. You may also need to tell your
firewall(s) to let it send your emails.

I have posted it to my blog here:

The tutorial is a little code heavy, but I think I explain the most
important bits. I am hoping for some constructive comments for making
the code and/or the tutorial better. I could have went into depth on a
lot of what’s in there, but it ended up being so long that I thought it
was a little overwhelming as it was.
Hi Mike,

I happened to look over your class EditDialog. I noticed that the
onDelete method is longer than necessary. Mutable sequences types in
Python have a handy function remove() that correctly removes an object
from the sequence, eliminating the need for the loop at the end of the
function that you have now. So your onDelete method could be as simple
and concise as this (I left out the print statements):

def onDelete(self,_event):

    for item in range(len(self.filepaths)):

        if self.chkList.IsChecked(item):

            self.filepaths.remove(self.chkList.GetString(item))

    self.Close()

There is no need to check whether a particular string is in the
filepath list; since you previously built the chkList object from
filepaths.

Also you might want to look into a possible alias issue. You pass the
variable self.filepaths from the parent class (SendMailWx) into the
EditDialog class constructor. There you bind this object to a variable
in EditDialog, also named filepaths. You now have two variables but
only one object. When you delete items in onDelete you are actually
removing them from the original SendMailWx.filepaths, although it
doesn’t look like it. In the onAttachEdit function, you have these
lines:

dialog.ShowModal()
    self.filepaths = dialog.filepaths

The second line is actually a no-op, since self.filepaths and
dialog.filepaths are the same object. This program will work, so
that’s not a problem. It’s a matter of style. But I try to avoid
this type of situation, since I just know that I will go to modify the
program in six months and I will screw it up.

Paul Cornelius

···

http://www.blog.pythonlibrary.org/?p=38

http://blog.pythonlibrary.org
http://www.pythonlibrary.org

wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Paul Cornelius wrote:

Mike Driscoll wrote:

Hi,

I finally got done putting together a tutorial using a real live wxPython application. It is (unfortunately) a Windows-only application that one can use for sending (but not receiving) emails. It was created to catch the "mailto" event from internet browsers and redirect that data to my script. I won't be too surprised if you find a bug here and there since I only tested it on XP. You may also need to tell your firewall(s) to let it send your emails.

I have posted it to my blog here:

wxPyMail: Creating an Application to Send Emails - Mouse Vs Python

The tutorial is a little code heavy, but I think I explain the most important bits. I am hoping for some constructive comments for making the code and/or the tutorial better. I could have went into depth on a lot of what's in there, but it ended up being so long that I thought it was a little overwhelming as it was.

Hi Mike,

I happened to look over your class EditDialog. I noticed that the onDelete method is longer than necessary. Mutable sequences types in Python have a handy function remove() that correctly removes an object from the sequence, eliminating the need for the loop at the end of the function that you have now. So your onDelete method could be as simple and concise as this (I left out the print statements):
    def onDelete(self,_event):
        for item in range(len(self.filepaths)):
            if self.chkList.IsChecked(item):
                self.filepaths.remove(self.chkList.GetString(item))
        self.Close()

I figured there would be a few things that needed improvements. I plan on writing an article where I refactor the code based on the comments I receive from this list. I'll add this to it then.

There is no need to check whether a particular string is in the filepath list; since you previously built the chkList object from filepaths.

Also you might want to look into a possible alias issue. You pass the variable self.filepaths from the parent class (SendMailWx) into the EditDialog class constructor. There you bind this object to a variable in EditDialog, also named filepaths. You now have two variables but only one object. When you delete items in onDelete you are actually removing them from the original SendMailWx.filepaths, although it doesn't look like it. In the onAttachEdit function, you have these lines:
    dialog.ShowModal()
    self.filepaths = dialog.filepaths
The second line is actually a no-op, since self.filepaths and dialog.filepaths are the same object. This program will work, so that's not a problem. It's a matter of style. But I try to avoid this type of situation, since I just know that I will go to modify the program in six months and I will screw it up.

Paul Cornelius

That's a good point too! I got lazy there. I'll have to try running PyLint on it and see if that catches anything too...

···

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

A couple of examples...

self.fromLbl = wx.StaticText(p, label='From', size=(60,-1))
self.fromTxt = wx.TextCtrl(p, value=self.email)

...

subjSizer.Add(self.subjectTxt, proportion=1, flag=wx.EXPAND)
attachSizer.Add(self.attachBtn, proportion=0, flag=wx.ALL, border=5)

One last thing and it's likely a religious thing, but you use
self.Bind() instead of self.widget.Bind().

···

On Mon, Aug 18, 2008 at 7:22 PM, Mike Driscoll <mike@pythonlibrary.org> wrote:

Timothy Grant wrote:

On Sun, Aug 17, 2008 at 10:39 AM, Mike Driscoll <mike@pythonlibrary.org> >> wrote:

Hi,

I finally got done putting together a tutorial using a real live wxPython
application. It is (unfortunately) a Windows-only application that one
can
use for sending (but not receiving) emails. It was created to catch the
"mailto" event from internet browsers and redirect that data to my
script. I
won't be too surprised if you find a bug here and there since I only
tested
it on XP. You may also need to tell your firewall(s) to let it send your
emails.

I have posted it to my blog here:

wxPyMail: Creating an Application to Send Emails - Mouse Vs Python

The tutorial is a little code heavy, but I think I explain the most
important bits. I am hoping for some constructive comments for making the
code and/or the tutorial better. I could have went into depth on a lot of
what's in there, but it ended up being so long that I thought it was a
little overwhelming as it was.

Someone on this list was wanting to know about login dialogs... well,
this
application uses one so if they still need help in getting their mind
around
that, they can check it out.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

Mike this is some fabulous stuff. Thank you for sharing it. I have it
bookmarked for future reference.

If I could suggest one change it would be that you use named
parameters on as many of your wx.Method() calls as possible. I've
found my own code much more readable and self-explanatory since I use
every named parameter I can get my hands on.

Just to clarify, you think I should do something like this:

self.parseURL(url="http://www.python.org")

instead of

self.parseURL("http://www.python.org")

correct?

Fortunately, most of my methods are event methods so they don't really
support that, but I'll definitely keep this in mind when I refactor the code
for my Linux version.

Mike

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

--
Stand Fast,
tjg. [Timothy Grant]

Timothy Grant wrote:

One last thing and it's likely a religious thing, but you use
self.Bind() instead of self.widget.Bind().

Just one note that self.widget.Bind is not always the correct method to use IMO; just usually. I don't think a religious habit of this is proper or healthy since it can sometimes be the case that you want one event handler to catch the same event, say EVT_BUTTON, from every child widget, and in that case there is nothing wrong with self.Bind as long as the event propagates.

I just wanted to point this out since your comment gave me the impression that self.Bind is universally wrong or inferior and everyone should stop using it, and this is not really the case. Do you disagree?

- Mike

Timothy,

<snip>

Just to clarify, you think I should do something like this:

self.parseURL(url="http://www.python.org")

instead of

self.parseURL("http://www.python.org")

correct?

Fortunately, most of my methods are event methods so they don't really
support that, but I'll definitely keep this in mind when I refactor the code
for my Linux version.

Mike

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

A couple of examples...

self.fromLbl = wx.StaticText(p, label='From', size=(60,-1))
self.fromTxt = wx.TextCtrl(p, value=self.email)

...

subjSizer.Add(self.subjectTxt, proportion=1, flag=wx.EXPAND)
attachSizer.Add(self.attachBtn, proportion=0, flag=wx.ALL, border=5)

Ooh...I forgot about those. I can definitely start sticking that back in, although it makes the lines a lot longer...which I know PyLint will not like. But if it makes it more clear, I'll gladly start doing that.

One last thing and it's likely a religious thing, but you use
self.Bind() instead of self.widget.Bind().

Have you read this: self.Bind vs. self.button.Bind - wxPyWiki ?

I guess the reason I usually use self.Bind is because that's how Robin's book is most of the time, as is the demo. Even the new widgets in the demo use self.Bind more often than not. Is this the right way to do it? I don't know. I just know that I love the demo and so I copy it a lot.

···

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

Mike, you've been doing this far longer than I have, so I argue from a
position of far less experience.

As I have refactored my current project several times now, I have
found that there are far fewer things I don't understand happening in
my code using the self.widget.Bind() over the self.Bind().

When I only want one event handler (and there have been many times
that's been the case), I simply have all of the items call the same
event handler.

I'm sure there may be a time when I find the self.Bind() construct to
be preferred, but I haven't run into one yet, therefore it is not what
comes out of my fingers when I'm writing code.

···

On Tue, Aug 19, 2008 at 9:37 AM, Mike Rooney <mxr@qvii.com> wrote:

Timothy Grant wrote:

One last thing and it's likely a religious thing, but you use
self.Bind() instead of self.widget.Bind().

Just one note that self.widget.Bind is not always the correct method to use
IMO; just usually. I don't think a religious habit of this is proper or
healthy since it can sometimes be the case that you want one event handler
to catch the same event, say EVT_BUTTON, from every child widget, and in
that case there is nothing wrong with self.Bind as long as the event
propagates.

I just wanted to point this out since your comment gave me the impression
that self.Bind is universally wrong or inferior and everyone should stop
using it, and this is not really the case. Do you disagree?

- Mike

--
Stand Fast,
tjg. [Timothy Grant]

Timothy,

<snip>

Just to clarify, you think I should do something like this:

self.parseURL(url="http://www.python.org")

instead of

self.parseURL("http://www.python.org")

correct?

Fortunately, most of my methods are event methods so they don't really
support that, but I'll definitely keep this in mind when I refactor the
code
for my Linux version.

Mike

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

A couple of examples...

self.fromLbl = wx.StaticText(p, label='From', size=(60,-1))
self.fromTxt = wx.TextCtrl(p, value=self.email)

...

subjSizer.Add(self.subjectTxt, proportion=1, flag=wx.EXPAND)
attachSizer.Add(self.attachBtn, proportion=0, flag=wx.ALL, border=5)

Ooh...I forgot about those. I can definitely start sticking that back in,
although it makes the lines a lot longer...which I know PyLint will not
like. But if it makes it more clear, I'll gladly start doing that.

You can just break the lines to prevent pylint from complaining. I
just like not having to guess about which parameter is which. I think
you can also safely leave out the vast majority of the IDs as they're
automagically created.

One last thing and it's likely a religious thing, but you use
self.Bind() instead of self.widget.Bind().

Have you read this:
self.Bind vs. self.button.Bind - wxPyWiki ?

Yes I have, that's where I learned about self.widget.Bind().

I guess the reason I usually use self.Bind is because that's how Robin's
book is most of the time, as is the demo. Even the new widgets in the demo
use self.Bind more often than not. Is this the right way to do it? I don't
know. I just know that I love the demo and so I copy it a lot.

I have yet to get Robin's book. Though it's on my list of purchases,
and it's one of the things that bugs me about the Demo, Though I do
love the demo, especially the edit the demo to test new ideas stuff.

···

On Tue, Aug 19, 2008 at 10:06 AM, Mike Driscoll <mike@pythonlibrary.org> wrote:

--
Stand Fast,
tjg. [Timothy Grant]

Timothy,

<snip>

A couple of examples...

self.fromLbl = wx.StaticText(p, label='From', size=(60,-1))
self.fromTxt = wx.TextCtrl(p, value=self.email)

...

subjSizer.Add(self.subjectTxt, proportion=1, flag=wx.EXPAND)
attachSizer.Add(self.attachBtn, proportion=0, flag=wx.ALL, border=5)

Ooh...I forgot about those. I can definitely start sticking that back in,
although it makes the lines a lot longer...which I know PyLint will not
like. But if it makes it more clear, I'll gladly start doing that.
    
You can just break the lines to prevent pylint from complaining. I
just like not having to guess about which parameter is which. I think
you can also safely leave out the vast majority of the IDs as they're
automagically created.

Yeah. I know. It just looks kind of funky to me. But I'm new to PyLint and just started discovering what it thinks are good practices, some of which I agree with and others that I really don't care about. IronPython has really long imports that I think would be a pain to break up though, but I'm getting off-topic. Thanks for all the suggestions. I'll try to blog more often this month and get this stuff in there.

Mike