Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-17 Thread Michael Selik
On Fri, Jun 17, 2016 at 11:42 AM boB Stepp  wrote:

> On Thu, Jun 16, 2016 at 11:40 AM, Alan Gauld via Tutor 
> wrote:
> > On 16/06/16 16:38, boB Stepp wrote:
> >
> >> class FTPFiles(FTP, object):
> >> """FTP files to Windows server location(s)."""
>
> I was struggling to come up with a good name here that would not cause
> me any name collision issues with the contents of ftplib.FTP().


That's why we have namespaces. Your ``FTP`` would not collide with
``ftplib.FTP``, because they are in separate modules.

I looked up LSP last night.  I can see how I can easily get burned
>
even on something seemingly simple.  One example, which I imagine is
> often used, is of a square class inheriting from a rectangle class.
> Squares have same sized sides; rectangles not necessarily so.  So any
> size changing methods from the rectangle class inherited by the square
> class can potentially wreak havoc on squares.  Am I getting the
> essence of the potential issues I might encounter?
>

Yes, that's the gist of it. It's very hard to anticipate what features your
base class may need in the future, months or years down the road. Many of
them may be inappropriate for one or more child classes.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-17 Thread Alan Gauld via Tutor
On 17/06/16 16:41, boB Stepp wrote:

>> Inheritance is a powerful tool but it carries lots of potential for
>> problems too,...
> 
> I looked up LSP last night.  I can see how I can easily get burned
> even on something seemingly simple.  One example, which I imagine is
> often used, is of a square class inheriting from a rectangle class.
> Squares have same sized sides; rectangles not necessarily so.  So any
> size changing methods from the rectangle class inherited by the square
> class can potentially wreak havoc on squares.  Am I getting the
> essence of the potential issues I might encounter?

Yes, that's one case. Another good example(in Java) is in the book
"Effective Java". It uses the example of a superclass which is a
collection and has add() and add_many() methods. Now let's say you want
to create a counted collection so you override the add() method to add
one to a total each time its called. Then you override add_many() to add
the number of items in the params list.

The problem is that, unknown to you, the inherited add_many()
calls self.add() internally so you wind up double counting on
add_many()... You need to know about the internals of the
superclass to correctly implement your sub class, which
breaks the concept of data hiding...

There is no way round this its just one of the inherent(sic)
issues with OOP, but a good reason to use delegation rather
than inheritance if possible. Inheritance is a powerful tool
but comes with sharp claws. (Its even worse in a static language
like Java but even in Python there are plenty of  opportunities
to mess up).

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-17 Thread boB Stepp
I guess I did not emphasize enough that I was just starting to think
through this.  The code I posted yesterday was more in the way of
exploratory code, trying to understand how to implement inheritance,
using new-style classes (I am trying to integrate the work with Python
3 at home as much as possible with what I am forced to in Python 2.4
at work where I have no choices as to Python version.).

On Fri, Jun 17, 2016 at 10:31 AM, Steven D'Aprano  wrote:
> Some futher thoughts:
>
> On Thu, Jun 16, 2016 at 10:38:13AM -0500, boB Stepp wrote:
>> class FTPFiles(FTP, object):
>> """FTP files to Windows server location(s)."""
>>
>> def __init__(self, host=server_ip, user=user, passwd=passwd):
>> """Initialize FTPFiles object.  Normally the defaults will be 
>> used."""
>>
>> super(FTPFiles, self).__init__(host, user, passwd)
>> self.host = host
>> self.user = user
>> self.passwd = passwd
>
> Do you actually need to record these? Once they're used to establish a
> connection and login, what are they for?

No, I was just spelling everything out for myself while I was trying
to figure out why my original code was not working.  All the things I
said I "learned" were not in my earlier versions.  These lines have
already been excised as I am getting closer to something I might
actually want to implement.  Also, now that I have had the opportunity
to play around with inheritance, I don't see any need to specialize
the FTP class as I mention in my response to Alan I just sent out.

>
>> def print_welcome_msg(self):
>> """Print welcome message sent by FTP server."""
>> print self.getwelcome()
>
> The getwelcome method already prints the message, which is a bad design.
> But only if debugging is true. So I would approach this in one of two
> ways:

The only point of this method was to ensure that I was actually
connected to my server.  During earlier versions, things were acting
weird and I was not understanding what was going on.  So I wanted to
be certain I was in fact connected; it turned out I was not!  This
also has been excised today.

> (1) Delegate to the existing getwelcome method:
>
> def print_welcome_msg(self):
> save_flag = self.debugging
> self.debugging = True
> try:
> x = self.getwelcome()  # prints the msg
> finally:
> self.debugging = save_flag
>
>
> (2) Re-implement the print functionality.
>
> def print_welcome_msg(self):
> print "*welcome*", self.welcome
>
>
> (3) If you really want to be paranoid, use:
>
> print "*welcome*", self.sanitize(self.welcome)
>
>
> although I don't think it's likely to make any real difference in
> practice.
>
> (The sanitize method makes a feeble attempt to hide the password.)

Some interesting ideas to aid debugging.  Thanks!

>> What I learned today:
>>
>> 1)  FTP from ftplib appears to be an old-style class.
>>
>> 2)  I can't just use "class FTPFiles(FTP)" or I will be using old-style 
>> classes.
>
> Is this a problem? Old-style classes are good enough for many purposes.

Not really.  I am just trying to consolidate the studies I am doing at
home with Python 3 as much as I can when I am working with Python 2.

>> 3)  I need to use "class FTPFiles(FTP, object)" to use new-style
>> classes and "object" must come AFTER "FTP".
>>
>> 4)  I have to use "super(FTPFiles, self).__init__(host, user, passwd)"
>> or I cannot successfully inherit from the FTP() class.  Also, "self"
>> apparently must come AFTER "FTPFiles" in the super expression.
>
> For old-style classes, don't use super because it doesn't work. Instead
> just write:
>
> FTP.__init__(self, host, user, passwd)

Yeah, if I just stuck to old-style, things would have been easier.

> That means that you cannot engage in multiple inheritence with new-style
> classes, but MI is a serious pain to get right, and 99% of the time it
> is overkill, so you're not missing much.

Right now just the simpler OOP stuff is a "serious pain" while I am
still in the relatively early stages of learning.  ~(:>))

boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-17 Thread boB Stepp
On Thu, Jun 16, 2016 at 11:40 AM, Alan Gauld via Tutor  wrote:
> On 16/06/16 16:38, boB Stepp wrote:
>
>> class FTPFiles(FTP, object):
>> """FTP files to Windows server location(s)."""
>
> OK, First comment. You describe this as an action(verb)
> rather than a noun. Classes should represent nouns
> (objects) not actions. FTP represents a protocol
> connection with which you can do things (one of
> which is put/get files) you class should be the same.
> (Remember inheritance m,eans you are imp0lementing
> an "is a" relationship. So FTPFiles is an FTP...or
> should be.)

I was struggling to come up with a good name here that would not cause
me any name collision issues with the contents of ftplib.FTP().  I
have for the moment changed the class name to "CustomFTP", which
bothers me for some reason that I cannot put my finger on.  However,
this looks to become a non-issue; see below.

>> 4)  As this class stuff is mostly treading new ground for me, am I
>> doing anything that I should not be doing or should do in a more
>> preferred way?  Keep in mind that I am just starting on this code
>> today.
>
> I'll leave someone with more ftplib experience to answer the other
> points but the question I'd ask is what are you planning to add to FTP?
> Creating a new class by inheritance implies that you are going to be
> extending (or specializing) its capabilities in some way. What are you
> planning to extend/specialize? For example are you going to limit it to
> manipulating files only? ie prevent listing directories say?

My first objective was just to play around with inheritance as a
learning opportunity.  Now that I have gotten it to work and have
somewhat a feel for the possibilities, I am actually going to abandon
it for this specific project.  I think I can use the FTP class
unmodified and just write appropriate helper functions to get the
specifics of what I want, passing my specific FTP instance object to
these functions.

> You need to know what you are changing to warrant using inheritance.
> Inheritance is a powerful tool but it carries lots of potential for
> problems too, especially if you plan on mixing your new class in with
> the old one (or sharing it with others who will) - you need to be
> careful to abide by the Liskov substitution principle (LSP).

I looked up LSP last night.  I can see how I can easily get burned
even on something seemingly simple.  One example, which I imagine is
often used, is of a square class inheriting from a rectangle class.
Squares have same sized sides; rectangles not necessarily so.  So any
size changing methods from the rectangle class inherited by the square
class can potentially wreak havoc on squares.  Am I getting the
essence of the potential issues I might encounter?

boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-17 Thread Steven D'Aprano
Some futher thoughts:

On Thu, Jun 16, 2016 at 10:38:13AM -0500, boB Stepp wrote:
> class FTPFiles(FTP, object):
> """FTP files to Windows server location(s)."""
> 
> def __init__(self, host=server_ip, user=user, passwd=passwd):
> """Initialize FTPFiles object.  Normally the defaults will be used."""
> 
> super(FTPFiles, self).__init__(host, user, passwd)
> self.host = host
> self.user = user
> self.passwd = passwd

Do you actually need to record these? Once they're used to establish a 
connection and login, what are they for?


> def print_welcome_msg(self):
> """Print welcome message sent by FTP server."""
> print self.getwelcome()

The getwelcome method already prints the message, which is a bad design. 
But only if debugging is true. So I would approach this in one of two 
ways:

(1) Delegate to the existing getwelcome method:

def print_welcome_msg(self):
save_flag = self.debugging
self.debugging = True
try:
x = self.getwelcome()  # prints the msg
finally:
self.debugging = save_flag


(2) Re-implement the print functionality.

def print_welcome_msg(self):
print "*welcome*", self.welcome


(3) If you really want to be paranoid, use:

print "*welcome*", self.sanitize(self.welcome)


although I don't think it's likely to make any real difference in 
practice.

(The sanitize method makes a feeble attempt to hide the password.)




> if __name__ == '__main__':
> ftp = FTPFiles()
> ftp.print_welcome_msg()
> ftp.quit()

This appears to be equivalent to:

ftp = FTP(host, user, passwd)
ftp.debugging = True
x = ftp.getwelcome()
ftp.quit()




> What I learned today:
> 
> 1)  FTP from ftplib appears to be an old-style class.
> 
> 2)  I can't just use "class FTPFiles(FTP)" or I will be using old-style 
> classes.

Is this a problem? Old-style classes are good enough for many purposes.

> 3)  I need to use "class FTPFiles(FTP, object)" to use new-style
> classes and "object" must come AFTER "FTP".
> 
> 4)  I have to use "super(FTPFiles, self).__init__(host, user, passwd)"
> or I cannot successfully inherit from the FTP() class.  Also, "self"
> apparently must come AFTER "FTPFiles" in the super expression.

For old-style classes, don't use super because it doesn't work. Instead 
just write:

FTP.__init__(self, host, user, passwd)


That means that you cannot engage in multiple inheritence with new-style 
classes, but MI is a serious pain to get right, and 99% of the time it 
is overkill, so you're not missing much.



-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-17 Thread Steven D'Aprano
On Thu, Jun 16, 2016 at 10:38:13AM -0500, boB Stepp wrote:

> I am extremely gradually trying to dip my big toe into the waters of
> writing classes.

[...]
> What I learned today:
> 
> 1)  FTP from ftplib appears to be an old-style class.
> 
> 2)  I can't just use "class FTPFiles(FTP)" or I will be using old-style 
> classes.
> 
> 3)  I need to use "class FTPFiles(FTP, object)" to use new-style
> classes and "object" must come AFTER "FTP".
> 
> 4)  I have to use "super(FTPFiles, self).__init__(host, user, passwd)"
> or I cannot successfully inherit from the FTP() class.  Also, "self"
> apparently must come AFTER "FTPFiles" in the super expression.
> 
> Questions:
> 
> 1)  Are there any more common "gotchas" that might be coming my way in
> trying to use a new-style class inheriting from an old-style class in
> ancient Py 2.4.4?

That's a very interesting question. I *think* the answer is "No", but I 
wouldn't put money on it.


> 2)  I don't have much knowledge about FTP processes.  This is being
> used on a secure intranet environment.  And I am using the ftplib for
> the first time.  In its docs it mentioned that the quit() method is
> the "polite" way to close the connection, but that an exception may be
> raised if the responds with an error to the "QUIT" command the method
> sends.  If this happens, will the connection close? 

According to the source code, yes.


> Or should I do something like:
> 
> try:
> ftp.quit()
> except:
> ftp.close()
> 
> ?  It seems here (If I should use the "try" block.) that a bare
> "except" is appropriate as I would think I would want to close the
> connection regardless of the type of error the "QUIT" command
> generates.

Bare except is nearly never appropriate. Consider:

try:
fpt.quit()
except:
ftp.close()


> 3)  The point of the print_welcome_msg() method is to be sure that I
> have actually successfully connected to the FTP server.  Is there a
> better way to check for connection success?

If the connect method doesn't raise an exception, it connected 
successfully. 




-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-16 Thread Alan Gauld via Tutor
On 16/06/16 16:38, boB Stepp wrote:

> class FTPFiles(FTP, object):
> """FTP files to Windows server location(s)."""

OK, First comment. You describe this as an action(verb)
rather than a noun. Classes should represent nouns
(objects) not actions. FTP represents a protocol
connection with which you can do things (one of
which is put/get files) you class should be the same.
(Remember inheritance m,eans you are imp0lementing
an "is a" relationship. So FTPFiles is an FTP...or
should be.)

> def __init__(self, host=server_ip, user=user, passwd=passwd):
> """Initialize FTPFiles object.  Normally the defaults will be used."""
> 
> super(FTPFiles, self).__init__(host, user, passwd)
> self.host = host
> self.user = user
> self.passwd = passwd
> 
> def print_welcome_msg(self):
> """Print welcome message sent by FTP server."""
> print self.getwelcome()


> 1)  FTP from ftplib appears to be an old-style class.

Using Python 2.4 that's not too surprising, FTP is an
old module.

> 4)  I have to use "super(FTPFiles, self).__init__(host, user, passwd)"
> or I cannot successfully inherit from the FTP() class.  Also, "self"
> apparently must come AFTER "FTPFiles" in the super expression.

That's the v2 super(). v3 super is far supeerior.

> 4)  As this class stuff is mostly treading new ground for me, am I
> doing anything that I should not be doing or should do in a more
> preferred way?  Keep in mind that I am just starting on this code
> today.

I'll leave someone with more ftplib experience to answer the other
points but the question I'd ask is what are you planning to add to FTP?
Creating a new class by inheritance implies that you are going to be
extending (or specializing) its capabilities in some way. What are you
planning to extend/specialize? For example are you going to limit it to
manipulating files only? ie prevent listing directories say?

You need to know what you are changing to warrant using inheritance.
Inheritance is a powerful tool but it carries lots of potential for
problems too, especially if you plan on mixing your new class in with
the old one (or sharing it with others who will) - you need to be
careful to abide by the Liskov substitution principle (LSP).

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Py 2.4.4: Inheriting from ftplib.FTP()

2016-06-16 Thread boB Stepp
I am extremely gradually trying to dip my big toe into the waters of
writing classes.  I have a little bit of extra time at work today, so
I thought I would start writing a class to replace a bunch of shell
FTP scripts I've used in various programs that would be flexible
enough to be reused wherever I need it.  I immediately ran into
problems, which I have (to the best of my knowledge) resolved.
However, I am still in the early stages of writing the methods for
this class, so I thought I would ask for any likely "gotchas" that
might come my way.

Python 2.4.4 on Solaris 10:

from ftplib import FTP

# Current values for Windows-based intranet FTP server:
server_ip = 'my_default_IP'
user = 'default_user'
passwd = 'default_pw'

class FTPFiles(FTP, object):
"""FTP files to Windows server location(s)."""

def __init__(self, host=server_ip, user=user, passwd=passwd):
"""Initialize FTPFiles object.  Normally the defaults will be used."""

super(FTPFiles, self).__init__(host, user, passwd)
self.host = host
self.user = user
self.passwd = passwd

def print_welcome_msg(self):
"""Print welcome message sent by FTP server."""

print self.getwelcome()


if __name__ == '__main__':
ftp = FTPFiles()
ftp.print_welcome_msg()
ftp.quit()

What I learned today:

1)  FTP from ftplib appears to be an old-style class.

2)  I can't just use "class FTPFiles(FTP)" or I will be using old-style classes.

3)  I need to use "class FTPFiles(FTP, object)" to use new-style
classes and "object" must come AFTER "FTP".

4)  I have to use "super(FTPFiles, self).__init__(host, user, passwd)"
or I cannot successfully inherit from the FTP() class.  Also, "self"
apparently must come AFTER "FTPFiles" in the super expression.

Questions:

1)  Are there any more common "gotchas" that might be coming my way in
trying to use a new-style class inheriting from an old-style class in
ancient Py 2.4.4?

2)  I don't have much knowledge about FTP processes.  This is being
used on a secure intranet environment.  And I am using the ftplib for
the first time.  In its docs it mentioned that the quit() method is
the "polite" way to close the connection, but that an exception may be
raised if the responds with an error to the "QUIT" command the method
sends.  If this happens, will the connection close?  Or should I do
something like:

try:
ftp.quit()
except:
ftp.close()

?  It seems here (If I should use the "try" block.) that a bare
"except" is appropriate as I would think I would want to close the
connection regardless of the type of error the "QUIT" command
generates.

3)  The point of the print_welcome_msg() method is to be sure that I
have actually successfully connected to the FTP server.  Is there a
better way to check for connection success?

4)  As this class stuff is mostly treading new ground for me, am I
doing anything that I should not be doing or should do in a more
preferred way?  Keep in mind that I am just starting on this code
today.

As always, many thanks in advance!

-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor