From guest0x013 at gmail.com  Mon Jan  1 16:38:39 2018
From: guest0x013 at gmail.com (Pi)
Date: Mon, 1 Jan 2018 22:38:39 +0100
Subject: [Tutor] checking connection to internet until success
Message-ID: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com>

Hi Tutor,

with this code i am getting actual date from internet. I need correct 
date, because i am not sure this set on computer is right.


import requests, time

try:
 ??? OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10]
 ??? OffLineDate = time.strftime("%Y-%m-%d")

 ??? if OnLineDate == OffLineDate:

 ? ? ? ? do_something

 ? ? else:

 ? ? ? ? do_something_else


except requests.ConnectionError:
 ??? print("Can not connect.")


But this code is run once. And i am stuck. Tries with while loop doesnt 
took any advance. I was thinking about something like after method used 
in tkinter, but still i cant figure out how do this. Can You guide me, 
how check connection to internet to check for every lets say 30 seconds 
until success?


Best regards


From __peter__ at web.de  Tue Jan  2 11:20:38 2018
From: __peter__ at web.de (Peter Otten)
Date: Tue, 02 Jan 2018 17:20:38 +0100
Subject: [Tutor] checking connection to internet until success
References: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com>
Message-ID: <p2gbcu$77t$1@blaine.gmane.org>

Pi wrote:

> Hi Tutor,
> 
> with this code i am getting actual date from internet. I need correct
> date, because i am not sure this set on computer is right.
>
> import requests, time
> 
> try:
>      OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10]
>      OffLineDate = time.strftime("%Y-%m-%d")
> 
>      if OnLineDate == OffLineDate:
> 
>          do_something
> 
>      else:
> 
>          do_something_else
> 
> 
> except requests.ConnectionError:
>      print("Can not connect.")
> 
> But this code is run once. And i am stuck. Tries with while loop doesnt
> took any advance. I was thinking about something like after method used
> in tkinter, but still i cant figure out how do this. Can You guide me,
> how check connection to internet to check for every lets say 30 seconds
> until success?

You are on the right track with the while-loop. You can use the else clause 
of the try...except construct to break out of the loop once you have 
successfully read the date:

# untested
import requests, time

while True:  # run forever
    try:
         OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10]
    except requests.ConnectionError:
         print("Can not connect.")
    else:
         # no exception
         OffLineDate = time.strftime("%Y-%m-%d")
         if OnLineDate == OffLineDate:
             do_something
         else:
             do_something_else
        break  # out of the while-True loop
    time.sleep(30)  # try again after 30 seconds


If you want to give up after a few tries replace the while loop with

for attempt in range(max_attempts):
    ...   # same as above


From alan.gauld at yahoo.co.uk  Tue Jan  2 11:36:54 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Tue, 2 Jan 2018 16:36:54 +0000
Subject: [Tutor] checking connection to internet until success
In-Reply-To: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com>
References: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com>
Message-ID: <p2gcb9$3ok$1@blaine.gmane.org>

On 01/01/18 21:38, Pi wrote:
> with this code i am getting actual date from internet. I need correct 
> date, because i am not sure this set on computer is right.

The first obvious pointto make is that all modern OS come
with an option to read the date/time from an internet time
server so this is the correct solution to your problem
rather than writing a web scraper. At the very least you
should access a time server directly rather than scrape
a web site. (try the ntplib module)

But if you do want to try doing it yourself...

> import requests, time
> 
> try:
>  ??? OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10]
>  ??? OffLineDate = time.strftime("%Y-%m-%d")>
>  ??? if OnLineDate == OffLineDate:
>  ? ? ? ? do_something
>  ? ? else:
>  ? ? ? ? do_something_else
> except requests.ConnectionError:
>  ??? print("Can not connect.")
> 
> 
> But this code is run once. And i am stuck. Tries with while loop doesnt 
> took any advance.

WE need to see what doesn't work to comment. A while loop
with a suitable sleep() should work.

But again it's probably better to use the OS to set up
a timed job.

On Unix this is done either with 'cron' or 'at'.
On Windows I believe 'at' is the tool.
There are other schedulers available too with GUIs etc.

> how check connection to internet to check for every lets say 30 seconds 
> until success?

What is success? When the times match? Or when they don't?
Or just whenever you succesfully connect?

-- 
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



From alan.gauld at yahoo.co.uk  Tue Jan  2 20:39:58 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Wed, 3 Jan 2018 01:39:58 +0000
Subject: [Tutor] Fwd: Re:  checking connection to internet until success
In-Reply-To: <449c5226-29e4-d2b2-d79f-38542abede0a@gmail.com>
References: <449c5226-29e4-d2b2-d79f-38542abede0a@gmail.com>
Message-ID: <df370abe-8d9f-ab1c-6aed-8fcb13833a28@yahoo.co.uk>

Forwarding to list...



-------- Forwarded Message --------
Subject: 	Re: [Tutor] checking connection to internet until success
Date: 	Wed, 3 Jan 2018 01:35:18 +0100
From: 	Pi <guest0x013 at gmail.com>
To: 	Alan Gauld <alan.gauld at yahoo.co.uk>



10 months ago i wrote application using time from OS (Windows 7), but my 
alpha tester found how to trick my app. Thats why i need to use date 
from web. And success of new application is when code will know, that 
computer is connected to web and can get actual date.


On 02.01.2018? 17:36, Alan Gauld via Tutor wrote:
> On 01/01/18 21:38, Pi wrote:
>> with this code i am getting actual date from internet. I need correct
>> date, because i am not sure this set on computer is right.
> The first obvious pointto make is that all modern OS come
> with an option to read the date/time from an internet time
> server so this is the correct solution to your problem
> rather than writing a web scraper. At the very least you
> should access a time server directly rather than scrape
> a web site. (try the ntplib module)
>
> But if you do want to try doing it yourself...
>
>> import requests, time
>>
>> try:
>>   ??? OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10]
>>   ??? OffLineDate = time.strftime("%Y-%m-%d")>
>>   ??? if OnLineDate == OffLineDate:
>>   ? ? ? ? do_something
>>   ? ? else:
>>   ? ? ? ? do_something_else
>> except requests.ConnectionError:
>>   ??? print("Can not connect.")
>>
>>
>> But this code is run once. And i am stuck. Tries with while loop doesnt
>> took any advance.
> WE need to see what doesn't work to comment. A while loop
> with a suitable sleep() should work.
>
> But again it's probably better to use the OS to set up
> a timed job.
>
> On Unix this is done either with 'cron' or 'at'.
> On Windows I believe 'at' is the tool.
> There are other schedulers available too with GUIs etc.
>
>> how check connection to internet to check for every lets say 30 seconds
>> until success?
> What is success? When the times match? Or when they don't?
> Or just whenever you succesfully connect?
>



From renukeshnk15 at gmail.com  Wed Jan  3 00:31:54 2018
From: renukeshnk15 at gmail.com (renukesh nk)
Date: Wed, 3 Jan 2018 11:01:54 +0530
Subject: [Tutor] CSV row and column width automation
Message-ID: <CAO2EJjjztAO3m5U=FDDCNy_WA3=UrJpViYxzFx+DpJLji40ctQ@mail.gmail.com>

Hi,

Is there any way to automatically set the column and row width in a CSV
file through python script

From alan.gauld at yahoo.co.uk  Wed Jan  3 06:10:11 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Wed, 3 Jan 2018 11:10:11 +0000
Subject: [Tutor] CSV row and column width automation
In-Reply-To: <CAO2EJjjztAO3m5U=FDDCNy_WA3=UrJpViYxzFx+DpJLji40ctQ@mail.gmail.com>
References: <CAO2EJjjztAO3m5U=FDDCNy_WA3=UrJpViYxzFx+DpJLji40ctQ@mail.gmail.com>
Message-ID: <p2idim$lc8$1@blaine.gmane.org>

On 03/01/18 05:31, renukesh nk wrote:

> Is there any way to automatically set the column and row width in a CSV
> file through python script

I'm not sure what you mean. CSV files don't have widths,
they are just sequences of data strings separated by commas.
Each piece of data takes as much space as it needs.

You could write code to force the strings to all
be the same width as the longest string but that would
just be making life harder for yourself when it comes
to extracting it again. CSV is a data transport mechanism
not a display format.

Are you thinking about some kind of display mechanism
like a web page table or a spreadsheet perhaps? They
have widths. But how you set them is very different
so you'd need to tell us what kind of table you have
in mind.

-- 
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



From robertvstepp at gmail.com  Wed Jan  3 21:20:25 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Wed, 3 Jan 2018 20:20:25 -0600
Subject: [Tutor] How to handle passwords in programs that perform FTP
 processes?
Message-ID: <CANDiX9+vy6ZKMvMLZFpbq_-NLkNKC+F0tRD6pPzKZXx2HFaf+A@mail.gmail.com>

Python 2.4, Solaris 10.

I have several programs that must transfer files from our Solaris
10-based intranet to our Windows-based intranet.  They each have their
own shell script to perform these file transfers, each customized for
each program.  Today I wrote a Python 2 program using the ftplib
module that will replace all of these shell script programs and
provide a standard interface for doing these transfers.  It also will
serve as a method for me to backup my programs on the Solaris 10-based
intranet to a location on the Windows side.  Even though these
networks are supposed to be secure intranets where those who need to
know know the generic user name and password for the FTP server, I
would like to be as secure as possible with this information.  How do
I go about doing this?  I am limited to whatever is available on the
Solaris 10 operating system and it must work with Python 2.4 and its
available standard libraries.  I cannot use any outside software.
However, I am free to write all the software I might like, assuming I
can find time to do so.  What would you sage Pythonistas recommend for
my situation?
-- 
boB

From cs at cskk.id.au  Thu Jan  4 17:24:04 2018
From: cs at cskk.id.au (Cameron Simpson)
Date: Fri, 5 Jan 2018 09:24:04 +1100
Subject: [Tutor] How to handle passwords in programs that perform FTP
 processes?
In-Reply-To: <CANDiX9+vy6ZKMvMLZFpbq_-NLkNKC+F0tRD6pPzKZXx2HFaf+A@mail.gmail.com>
References: <CANDiX9+vy6ZKMvMLZFpbq_-NLkNKC+F0tRD6pPzKZXx2HFaf+A@mail.gmail.com>
Message-ID: <20180104222404.GA51412@cskk.homeip.net>

On 03Jan2018 20:20, boB Stepp <robertvstepp at gmail.com> wrote:
>Python 2.4, Solaris 10.
>
>I have several programs that must transfer files from our Solaris
>10-based intranet to our Windows-based intranet.  They each have their
>own shell script to perform these file transfers, each customized for
>each program.  Today I wrote a Python 2 program using the ftplib
>module that will replace all of these shell script programs and
>provide a standard interface for doing these transfers.  It also will
>serve as a method for me to backup my programs on the Solaris 10-based
>intranet to a location on the Windows side.  Even though these
>networks are supposed to be secure intranets where those who need to
>know know the generic user name and password for the FTP server, I
>would like to be as secure as possible with this information.  How do
>I go about doing this?  I am limited to whatever is available on the
>Solaris 10 operating system and it must work with Python 2.4 and its
>available standard libraries.  I cannot use any outside software.
>However, I am free to write all the software I might like, assuming I
>can find time to do so.  What would you sage Pythonistas recommend for
>my situation?

Look at the netrc module. Tradition ftp programs used to be able to use .netrc 
files, and this module reads them. It means storing credentials in the clear 
(obvious make the .netrc file 0600 permissions), but in most batch situations 
you're stuck with that anyway.

Cheers,
Cameron Simpson <cs at cskk.id.au>

From alan.gauld at yahoo.co.uk  Fri Jan  5 08:49:34 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Fri, 5 Jan 2018 13:49:34 +0000
Subject: [Tutor] Updates to web tutor
In-Reply-To: <cfed362f-03d8-4402-958a-e271a2f4960f@yahoo.co.uk>
References: <cfed362f-03d8-4402-958a-e271a2f4960f@yahoo.co.uk>
Message-ID: <p2nvlh$828$1@blaine.gmane.org>

On 15/11/17 17:41, Alan Gauld via Tutor wrote:
> Only just on topic but I'd like some help please...
> 
> I've been doing some much needed maintenance to my web tutor.

The latest update is that I think I've got the styling and
structure as I want it and everything should be usable on
all devices (?!!!)

I've now started updating the content and in particular
fixing broken links and updating all the MS Windows stuff
from XP to Windows 10. So far I've completed up to the end
of the Basics section (error handling).

I have also completed the last section (on applications)
with 4 new topics on web programming and one on concurrent
programming(threading and multiprocessing).

I'll be working through the remaining topics over the next
2 weeks and aim to move the test site to become the main
tutor landing page by the end of the month.

As before, if anyone can spare the time to take a look at
the new and updated material and send me feedback (offlist)
it will be appreciated.

-- 
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



From alan.gauld at yahoo.co.uk  Fri Jan  5 18:51:40 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Fri, 5 Jan 2018 23:51:40 +0000
Subject: [Tutor] Updates to web tutor
In-Reply-To: <p2nvlh$828$1@blaine.gmane.org>
References: <cfed362f-03d8-4402-958a-e271a2f4960f@yahoo.co.uk>
 <p2nvlh$828$1@blaine.gmane.org>
Message-ID: <p2p2ue$cqf$1@blaine.gmane.org>

On 05/01/18 13:49, Alan Gauld via Tutor wrote:

> As before, if anyone can spare the time to take a look at
> the new and updated material and send me feedback (offlist)
> it will be appreciated.

Just realized I forgot to include the test site url!
If it's not a yellow theme then it's the wrong site!
It should be:

http://www.alan-g.me.uk/l2p2

Sorry about that,

-- 
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



From robertvstepp at gmail.com  Sun Jan  7 01:49:59 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Sun, 7 Jan 2018 00:49:59 -0600
Subject: [Tutor] Why does os.path.realpath('test_main.py') give different
 results for unittest than for testing statement in interpreter?
Message-ID: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>

Win7, Python 3.6.2

If I run a unit test with the following embedded:

print('realpath =', os.path.realpath('test_main.py'))

I get the following in my test output (Only relevant line is shown):

Ensure expected list of string integers is returned. ... realpath =
c:\Projects\solitaire_scorekeeper\test_main.py

In actuality "test_main.py" is located at
"c:\Projects\solitaire_scorekeeper\tests\test_main.py"

If I open the interpreter from the directory
"c:\Projects\solitaire_scorekeeper\tests\" I get what I expect:

py3: import os.path
py3: os.path.realpath('test_main.py')
'c:\\Projects\\solitaire_scorekeeper\\tests\\test_main.py'

Would someone enlighten me as to why the different results?

TIA!

-- 
boB

From steve at pearwood.info  Sun Jan  7 03:05:59 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Sun, 7 Jan 2018 19:05:59 +1100
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
Message-ID: <20180107080558.GC4152@ando.pearwood.info>

On Sun, Jan 07, 2018 at 12:49:59AM -0600, boB Stepp wrote:

> Win7, Python 3.6.2
> 
> If I run a unit test with the following embedded:
> 
> print('realpath =', os.path.realpath('test_main.py'))
> 
> I get the following in my test output (Only relevant line is shown):
> 
> Ensure expected list of string integers is returned. ... 
> realpath = c:\Projects\solitaire_scorekeeper\test_main.py


realpath() returns the canonical path of the given filename. It doesn't 
try to locate some actual existing file. The fact that there is a file 
called "test_main.py" located here:

> In actuality "test_main.py" is located at
> "c:\Projects\solitaire_scorekeeper\tests\test_main.py"

is irrelevent. You asked for the "real" (canonical) path name to the 
relative pathname "test_main.py". That means in the current directory, 
which apparently is C:\Projects\solitaire_scorekeeper. Hence you get the 
result C:\Projects\solitaire_scorekeeper\test_main.py even though the 
"real file" is one directory further in.


> If I open the interpreter from the directory
> "c:\Projects\solitaire_scorekeeper\tests\" I get what I expect:

Indeed, because now the current directory is different.

I think you may be confused because you think realpath() has something 
to do with actual existing files. It doesn't. Remember that realpath() 
isn't just called on existing files, it may be called on arbitrary file 
names which don't exist. Its more like os.path.abspath() except that if 
the path contains symbolic links (not likely on Windows, but possible) 
they will be resolved to their real path.


-- 
Steve

From robertvstepp at gmail.com  Sun Jan  7 04:07:26 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Sun, 7 Jan 2018 03:07:26 -0600
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <20180107080558.GC4152@ando.pearwood.info>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
Message-ID: <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>

On Sun, Jan 7, 2018 at 2:05 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Sun, Jan 07, 2018 at 12:49:59AM -0600, boB Stepp wrote:
>
>> Win7, Python 3.6.2
>>
>> If I run a unit test with the following embedded:
>>
>> print('realpath =', os.path.realpath('test_main.py'))
>>
>> I get the following in my test output (Only relevant line is shown):
>>
>> Ensure expected list of string integers is returned. ...
>> realpath = c:\Projects\solitaire_scorekeeper\test_main.py
>
>
> realpath() returns the canonical path of the given filename. It doesn't
> try to locate some actual existing file. The fact that there is a file
> called "test_main.py" located here:
>
>> In actuality "test_main.py" is located at
>> "c:\Projects\solitaire_scorekeeper\tests\test_main.py"
>
> is irrelevent. You asked for the "real" (canonical) path name to the
> relative pathname "test_main.py". That means in the current directory,
> which apparently is C:\Projects\solitaire_scorekeeper. Hence you get the
> result C:\Projects\solitaire_scorekeeper\test_main.py even though the
> "real file" is one directory further in.

After some searching I have yet to locate a definition of "canonical
path" that makes sense to me.  The dictionary definition of canonical
does not seem to be very helpful in understanding this.  Can you
clarify this?  What is the methodology that os.path.realpath(path) is
actually following to yield a particular path name?  And why does it
not care if path refers to a real file or not?

What I *really* want to do is locate and open a file "test_data.dat"
that is in the same directory as the file with the tests,
"tests/test_main.py".  I asked a related question a while back but I
now suspect I did not fully get everything.  I have recently been
experimenting with the os and os.path modules and thought I had found
the magic bullet with os.path.realpath().  Anyway, based on that
earlier related question and your answer tonight I have modified my
test class to the following:

class TestOpenFileStrIntsToList(unittest.TestCase):
    """Tests for the function open_file_str_ints_to_list."""

    def test_open_file_str_ints_to_list(self):
        """Ensure expected list of string integers is returned."""

        path = os.path.dirname(
                os.path.realpath(__file__)) + '/test_data.dat'
        print('realpath =', os.path.realpath(__file__))
        expected_list = ['-3', '-2', '-1', '0', '1', '2', '3']
        self.assertEqual(open_file_str_ints_to_list(path), expected_list)

The test_data file is just the expected_list values, one value per
line in the file.  The function being tested is:

def open_file_str_ints_to_list(path):
    """Given a path to the file, open this file containing one string integer
    per line, and convert it to a list of string integers, which is then
    returned by this function."""

    with open(path) as infile:
        string_integers = [line.strip() for line in infile]

    return string_integers

BTW, I am having trouble coming up with a good name for a string that
looks like an integer that I plan on using int() later to convert the
string to an integer.  "String integer" is my best thought at this
time.

Anyway, the print() statement in the test case is giving me the
correct result.  Is this way of determining the directory which
test_main.py is running from bullet proof?


-- 
boB

From sjeik_appie at hotmail.com  Sun Jan  7 05:51:20 2018
From: sjeik_appie at hotmail.com (Albert-Jan Roskam)
Date: Sun, 7 Jan 2018 10:51:20 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
Message-ID: <HE1PR1001MB1308C53243E15530F7FDD5A483120@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>


On Jan 7, 2018 09:08, Steven D'Aprano <steve at pearwood.info> wrote:
>
> On Sun, Jan 07, 2018 at 12:49:59AM -0600, boB Stepp wrote:
>
> > Win7, Python 3.6.2
> >
> > If I run a unit test with the following embedded:
> >
> > print('realpath =', os.path.realpath('test_main.py'))
> >
> > I get the following in my test output (Only relevant line is shown):
> >
> > Ensure expected list of string integers is returned. ...
> > realpath = c:\Projects\solitaire_scorekeeper\test_main.py
>
>
> realpath() returns the canonical path of the given filename. It doesn't
> try to locate some actual existing file.

I always thought that os.path.realpath is the Python equivalent of Linux realpath/readlink (http://man7.org/linux/man-pages/man3/realpath.3.html). And that, thus, there's only a difference between input and output when the input is a symlink (and maybe also when it's a hard link - in this case the function actually also does something in Windows). But then, I don't really know the meaning of the word "canonical", to tell you the truth (maybe #4 in http://www.dictionary.com/browse/canonical)

From alan.gauld at yahoo.co.uk  Sun Jan  7 09:32:38 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Sun, 7 Jan 2018 14:32:38 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
Message-ID: <p2tau9$5vg$1@blaine.gmane.org>

On 07/01/18 09:07, boB Stepp wrote:
> clarify this?  What is the methodology that os.path.realpath(path) is
> actually following to yield a particular path name?  And why does it
> not care if path refers to a real file or not?

The os.path module is mostly a string manipulation toolkit.

It checks that a string looks like a path and it de/constructs
paths from strings. But it does not pay muchy(any?) attention
to the filesystem. It doesn't care if the paths it deals
with are real paths or not, its purely manipulating the
strings according to the syntax rules for paths.

The exceptions are the test functions like isfile(), isdir() etc.

> What I *really* want to do is locate and open a file "test_data.dat"
> that is in the same directory as the file with the tests,

For that you need to do some work with listdir or glob.
You might need to do a os.getcwd() but I suspect it will
return the folder where you started te program rather than
the folder the file lives in. For that you may need to
use the __file__ attribute of the test module. So
something like:

dir = os.path.dirname(__file__)  # assuming this is in the test module
fn = os.path.join(dir,fname)
if os.path.isfile(fn)   # check the file actually exists
   f = open(fn)


> class TestOpenFileStrIntsToList(unittest.TestCase):
>     """Tests for the function open_file_str_ints_to_list."""
> 
>     def test_open_file_str_ints_to_list(self):
>         """Ensure expected list of string integers is returned."""
> 
>         path = os.path.dirname(
>                 os.path.realpath(__file__)) + '/test_data.dat'
>         print('realpath =', os.path.realpath(__file__))

Yes, thats it although you could test using isfile() or
better still use a try/except around the open.

Also you should strictly use os.path.join() to create the path

> BTW, I am having trouble coming up with a good name for a string that
> looks like an integer that I plan on using int() later to convert the
> string to an integer.  "String integer" is my best thought at this
> time.

What's it for? Where did it come from?
type based names are rarely good, better to describe why/where.

input_Id, read_Id, stored_Id etc....

Or substitute Ref, or Count or whatever for Id.

Then the real int var name becomes the second part:

Id = int(input_Id)

or

count = int(stored_count)

> Is this way of determining the directory which
> test_main.py is running from bullet proof?

If its really in the same folder then I believe
so - or as bullet proof as it gets. Maybe if you
create a shortcut to the real folder etc you might
need to revert to realpath.


-- 
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



From robertvstepp at gmail.com  Sun Jan  7 17:56:52 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Sun, 7 Jan 2018 16:56:52 -0600
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <HE1PR1001MB1308C53243E15530F7FDD5A483120@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB1308C53243E15530F7FDD5A483120@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <CANDiX9+AD5gyqXReEUBX3OtsX0TC9Oxg5jtzDoqfUoJewwCKqg@mail.gmail.com>

On Sun, Jan 7, 2018 at 4:51 AM, Albert-Jan Roskam
<sjeik_appie at hotmail.com> wrote:
>
> On Jan 7, 2018 09:08, Steven D'Aprano <steve at pearwood.info> wrote:

>> realpath() returns the canonical path of the given filename. It doesn't
>> try to locate some actual existing file.
>
> I always thought that os.path.realpath is the Python equivalent of Linux realpath/readlink (http://man7.org/linux/man-pages/man3/realpath.3.html). And that, thus, there's only a difference between input and output when the input is a symlink (and maybe also when it's a hard link - in this case the function actually also does something in Windows). But then, I don't really know the meaning of the word "canonical", to tell you the truth (maybe #4 in http://www.dictionary.com/browse/canonical)

My hangup was mostly that I was assuming that an actually existing
path to a real file was implied.  Apparently that is not the case.  So
Alan's explanation has cleared that up for me (I think!).

I agree with you that the 4th definition you cite:

"4. Mathematics. (of an equation, coordinate, etc.) in simplest or
standard form."

is the most sensible definition in this context with Steve's caveats.

-- 
boB

From steve at pearwood.info  Sun Jan  7 18:38:50 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Mon, 8 Jan 2018 10:38:50 +1100
Subject: [Tutor] Testing
Message-ID: <20180107233850.GI6667@ando.pearwood.info>

I've tried emailing in response to the os.path.realpath thread twice, 
and neither email has made it through.

Alan, am I stuck in the moderator queue for some reason?



-- 
Steve

From robertvstepp at gmail.com  Sun Jan  7 19:17:33 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Sun, 7 Jan 2018 18:17:33 -0600
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <p2tau9$5vg$1@blaine.gmane.org>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <p2tau9$5vg$1@blaine.gmane.org>
Message-ID: <CANDiX9L=0XcawwinzyTTAiY4278wb+zTuuOb7sAt1u46Z86cUQ@mail.gmail.com>

On Sun, Jan 7, 2018 at 8:32 AM, Alan Gauld via Tutor <tutor at python.org> wrote:
> On 07/01/18 09:07, boB Stepp wrote:
>> clarify this?  What is the methodology that os.path.realpath(path) is
>> actually following to yield a particular path name?  And why does it
>> not care if path refers to a real file or not?
>
> The os.path module is mostly a string manipulation toolkit.

This is the critical piece that was eluding me.  I assumed that the
actual file system was being queried, checked and expanded as needed.

> It checks that a string looks like a path and it de/constructs
> paths from strings. But it does not pay muchy(any?) attention
> to the filesystem. It doesn't care if the paths it deals
> with are real paths or not, its purely manipulating the
> strings according to the syntax rules for paths.

I was assuming it was computing the actual path to the file given as
its argument.  Steve's comments make much more sense now as well as
the "canonical" aspect.

>> class TestOpenFileStrIntsToList(unittest.TestCase):
>>     """Tests for the function open_file_str_ints_to_list."""
>>
>>     def test_open_file_str_ints_to_list(self):
>>         """Ensure expected list of string integers is returned."""
>>
>>         path = os.path.dirname(
>>                 os.path.realpath(__file__)) + '/test_data.dat'
>>         print('realpath =', os.path.realpath(__file__))
>
> Yes, thats it although you could test using isfile() or
> better still use a try/except around the open.
>
> Also you should strictly use os.path.join() to create the path

Duly noted on os.path.join().  I have not gotten to thinking about the
UI yet, and don't mind if a file not found error is generated here in
the testing code as it will let me know I've screwed something up.
This is strictly a play project to record my manual games of
solitaire.  I doubt it will be useful to anyone else.  Once I get to
coding the UI I might wrap this in a try/except if I feel I would gain
any benefit from handling the exception.

>> BTW, I am having trouble coming up with a good name for a string that
>> looks like an integer that I plan on using int() later to convert the
>> string to an integer.  "String integer" is my best thought at this
>> time.
>
> What's it for? Where did it come from?
> type based names are rarely good, better to describe why/where.
>
> input_Id, read_Id, stored_Id etc....
>
> Or substitute Ref, or Count or whatever for Id.
>
> Then the real int var name becomes the second part:
>
> Id = int(input_Id)
>
> or
>
> count = int(stored_count)

The above has just now led me to a Homer Simpson "Doh!" moment.  When
I open the file and covert it to a list of "string" integers I
currently have:

with open(path) as infile:
       string_integers = [line.strip() for line in infile]

and then run the list through another function to get an integer list.

Why on earth didn't I just write:

with open(path) as infile:
       total_scores = [int(line.strip()) for line in infile]

which directly creates what I want directly?  [Please don't answer
this question!  ~(:>)) ]


-- 
boB

From robertvstepp at gmail.com  Sun Jan  7 19:24:44 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Sun, 7 Jan 2018 18:24:44 -0600
Subject: [Tutor] Testing
In-Reply-To: <20180107233850.GI6667@ando.pearwood.info>
References: <20180107233850.GI6667@ando.pearwood.info>
Message-ID: <CANDiX9KfWL56UmSXe-WuXQKSr+AVza1KOj7uhvYJ6cX9Ff_pjg@mail.gmail.com>

On Sun, Jan 7, 2018 at 5:38 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> I've tried emailing in response to the os.path.realpath thread twice,
> and neither email has made it through.
>
> Alan, am I stuck in the moderator queue for some reason?

This one made it through.  My original answer to your post last night
took so long to appear on https://mail.python.org/pipermail/tutor that
I finally gave up and went to bed.  But it was there when I awoke
today!

-- 
boB

From alan.gauld at yahoo.co.uk  Sun Jan  7 19:39:07 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Mon, 8 Jan 2018 00:39:07 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <CANDiX9L=0XcawwinzyTTAiY4278wb+zTuuOb7sAt1u46Z86cUQ@mail.gmail.com>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <p2tau9$5vg$1@blaine.gmane.org>
 <CANDiX9L=0XcawwinzyTTAiY4278wb+zTuuOb7sAt1u46Z86cUQ@mail.gmail.com>
Message-ID: <p2uefd$ais$1@blaine.gmane.org>

On 08/01/18 00:17, boB Stepp wrote:

>> The os.path module is mostly a string manipulation toolkit.
> 
> This is the critical piece that was eluding me.  I assumed that the
> actual file system was being queried, checked and expanded as needed.

To be fair realpath() does do a tiny bit of magic in that it
checks if the file (or any part of the path) is a link (aka
shortcut) and tries to give you the actual path to the
original file - ie it follows the link. I'm not sure how
effective it is, I've only played with it but never used
it in earnest.

But in general I tend not to rely on os.path doing anything
remotely clever.

-- 
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



From steve at pearwood.info  Sun Jan  7 20:21:49 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Mon, 8 Jan 2018 12:21:49 +1100
Subject: [Tutor] Testing
In-Reply-To: <3cfe3325-9fe4-d495-f809-a97cb2e57066@yahoo.co.uk>
References: <20180107233850.GI6667@ando.pearwood.info>
 <3cfe3325-9fe4-d495-f809-a97cb2e57066@yahoo.co.uk>
Message-ID: <20180108012146.GJ6667@ando.pearwood.info>

On Mon, Jan 08, 2018 at 12:31:06AM +0000, Alan Gauld wrote:
> On 07/01/18 23:38, Steven D'Aprano wrote:
> > I've tried emailing in response to the os.path.realpath thread twice, 
> > and neither email has made it through.
> >
> > Alan, am I stuck in the moderator queue for some reason?
> 
> Nope, nothing from you there.
> 
> And your account settings all look fine.

I've made another attempt to send through my response to the realpath 
thread.



-- 
Steve

From steve at pearwood.info  Mon Jan  8 01:47:00 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Mon, 8 Jan 2018 17:47:00 +1100
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <p2uefd$ais$1@blaine.gmane.org>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <p2tau9$5vg$1@blaine.gmane.org>
 <CANDiX9L=0XcawwinzyTTAiY4278wb+zTuuOb7sAt1u46Z86cUQ@mail.gmail.com>
 <p2uefd$ais$1@blaine.gmane.org>
Message-ID: <20180108064700.GL6667@ando.pearwood.info>

On Mon, Jan 08, 2018 at 12:39:07AM +0000, Alan Gauld via Tutor wrote:

> To be fair realpath() does do a tiny bit of magic in that it
> checks if the file (or any part of the path) is a link (aka
> shortcut) and tries to give you the actual path to the
> original file - ie it follows the link.

As I actually explained in my previous email, the one which has 
disappeared into the aether, realpath resolves symbolic links and 
replaces them by the real path they represent.

But that's only on Unix/Linux/Mac, on Windows it does not.

Symbolic links, however, are *not* Windows shortcuts. Windows shortcuts 
are just a special sort of file, one which the Windows file explorer 
treats as an alias to another file or folder.

Symbolic links on Unix are a feature of the file system itself, not a 
kind of file.

What's the difference?

With a shortcut, if you tell Python or some other program to open a 
shortcut, it will treat it as an ordinary file (because that's what it 
is!) and read from the shortcut file itself. Only programs like Windows 
Explorer which have been specially programmed to follow shortcuts will 
do so.

But with a symbolic link, programs don't need to know anything about 
them. If you have a link:

/A/link ---> /B/C/file

then *any* program will treat opening /A/link as if it were /B/C/file.

In other words:

- under Windows, a shortcut is a regular file, unless the programmer
  takes special action to treat it as an alias;

- under Unix, a symbolic link is an alias, unless the programmer 
  takes special action to treat it as a symbolic link.


(Aside: starting with Windows Vista, NTFS also supports symbolic links, 
like Unix. But few Windows users know this, or use them.)




-- 
Steve

From eryksun at gmail.com  Mon Jan  8 08:28:11 2018
From: eryksun at gmail.com (eryk sun)
Date: Mon, 8 Jan 2018 13:28:11 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <HE1PR1001MB1308C53243E15530F7FDD5A483120@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB1308C53243E15530F7FDD5A483120@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <CACL+1auPAa-g0y9rhjHjav0KO0XfQsw1-zF0yCXyyPv3OEymyA@mail.gmail.com>

On Sun, Jan 7, 2018 at 10:51 AM, Albert-Jan Roskam
<sjeik_appie at hotmail.com> wrote:
>
> On Jan 7, 2018 09:08, Steven D'Aprano <steve at pearwood.info> wrote:
>>
>> realpath() returns the canonical path of the given filename. It doesn't
>> try to locate some actual existing file.
>
> I always thought that os.path.realpath is the Python equivalent of Linux
> realpath/readlink

In POSIX, os.path.realpath resolves a path that contains symlinks by
calling os.readlink in a loop until all links are resolved.

In Windows, os.path.realpath is an alias for os.path.abspath. This
decision predates NTFS support for junctions (2000) and symbolic links
(Vista). It's simply the case that no one has gotten around to
implementing realpath for Windows.

In Windows, os.path.abspath calls os.path._getfullpathname (WinAPI
GetFullPathName). Other than resolving the working directory, this is
a string transformation to return a canonical, fully-qualified path.
It doesn't touch the filesystem. Note that in the case of classic DOS
devices, the canonical path is a local-device path (i.e. "\\.\"
prefix). For example:

    >>> print(os.path.abspath('C:/path/to/nul'))
    \\.\nul

> maybe also when it's a hard link - in this case the function actually also does
> something in Windows

A hard link shouldn't be resolved to another path by os.path.realpath.
It's already a real path.

Cross-platform Python 3 code that needs to resolve symbolic links (or
junctions) can use pathlib.Path.resolve(). For example:

    >>> pathlib.Path('C:/Documents and Settings').resolve()
    WindowsPath('C:/Users')

On Windows this relies on os.path._getfinalpathname (WinAPI
GetFinalPathNameByHandle). This function returns the final opened
filename, so the OS does all of the work to resolve the final path. In
non-strict mode pathlib uses a loop to reduce the path when it can't
be resolved to an existing file. (There are open issues for edge cases
in this code, but it should work as intended with regular files in
accessible directories.)

For those who are curious, WinAPI GetFinalPathNameByHandle is called
with a handle for a File object that's opened via CreateFile. It gets
the NT name of the volume (e.g, "\Device\HarddiskVolume1") and the
filesystem path (e.g. "\Users"). Then it asks the mount-point manager
to map this NT name back to a DOS name such as drive "C:"; or an NTFS
volume mountpoint such as "C:\Mount\VolumeName"; or a "Volume{GUID}"
name. (In the latter case, Python's _getfinalpathname and pathlib have
bugs and need improvement.)

From steve at pearwood.info  Tue Jan  9 03:47:33 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Tue, 9 Jan 2018 19:47:33 +1100
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
Message-ID: <20180109084733.GG4152@ando.pearwood.info>

On Sun, Jan 07, 2018 at 03:07:26AM -0600, boB Stepp wrote:

> After some searching I have yet to locate a definition of "canonical
> path" that makes sense to me.  The dictionary definition of canonical
> does not seem to be very helpful in understanding this.

Probably the best definition would be "the simplest authoritative form 
of the path".


> What is the methodology that os.path.realpath(path) is
> actually following to yield a particular path name?

Trust the Source, Luke :-)

The Python 3.5 source code for os.path.realpath under Windows looks like 
this:

# realpath is a no-op on systems without islink support
realpath = abspath

The comment is misleading[1] for two reasons:

- it isn't a no-op, since abspath() actually does something; 
  what they mean is that on Windows realpath() doesn't do
  anything beyond what abspath() does;

  (on Linux and Mac, it also checks for symbolic links, and
  converts them to their actual paths)

- and technically speaking, some Windows file systems *do*
  support symbolic links, although few people know this or
  use them.

https://en.wikipedia.org/wiki/NTFS_symbolic_link


Nevertheless, we can say that under Windows realpath() does nothing more 
than abspath() (at least up to Python 3.5). So what does abspath() do?

The source for abspath() is a more little complicated, because it has 
two different implementations depending on whether you are *actually* 
running Windows or not. But basically, abspath() does this:

- if the path is a relative path (does not start with C:\ or similar)
  then prepend the current directory to the path;

- then normalise the path.

What does it mean to normalise the path?

It converts it to the simplest form, eliminating redundant slashes and 
dots. Because this is Windows, there are a bunch of special cases for 
device names and literal paths (whatever they are!) that look like this:

    \\.\ -> device names
     \\?\ -> literal paths


but for the standard case of ordinary file names, normpath() on Windows 
will convert forward slashes / to backslashes \ and eliminate duplicated 
slashes and dots in the path. Remember that . means "this directory" and 
.. means "one directory up", normpath() will normalise any of these:

    A//B
    A/./B
    A/foo/../B

to A\B. Since the Windows version of realpath() doesn't care about 
symbolic links, it doesn't need to care whether any of the directories 
and files actually exist or not. All it needs to do is turn a relative 
path into an absolute path, then normalise the path. And none of that 
depends on the path actually existing.


> What I *really* want to do is locate and open a file "test_data.dat"
> that is in the same directory as the file with the tests,
> "tests/test_main.py".

If you can assume that tests/test_main.py is always in the current 
directory, then you can just write:

PATH = 'tests/test_main.py'

and use that. open(PATH) will happily work on relative paths as well as 
absolute.

Reminder: absolute paths start with a drive:

    A:\foo\bar

relative paths don't, and so they implicitly start in the current 
directory.

*But* that assumes that you have started running the tests from inside 
the directory which includes tests/test_main.py. That might not be the 
case. In order to solve this problem properly, I think we need to know 
how your project is laid out, including the tests.

But my guess is that the solution is to extract the path of the running 
module, and append tests/test_main.py to that path.

If this isn't clear, ask and I'll explain in more detail. (But later, 
I'm about to move off the computer for a few hours.)


> Anyway, based on that
> earlier related question and your answer tonight I have modified my
> test class to the following:
[...]

I'll read it later.




[1] "At Resolver we've found it useful to short-circuit any doubt and 
just refer to comments in code as 'lies'. "
--Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22


-- 
Steve

From steve at pearwood.info  Tue Jan  9 03:49:40 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Tue, 9 Jan 2018 19:49:40 +1100
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <CANDiX9JPNRbqBGuDhVu0_fSgTJX3DoFrLzFWEN8MDorJye8kqw@mail.gmail.com>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <p2tau9$5vg$1@blaine.gmane.org>
 <CANDiX9L=0XcawwinzyTTAiY4278wb+zTuuOb7sAt1u46Z86cUQ@mail.gmail.com>
 <p2uefd$ais$1@blaine.gmane.org> <20180108064700.GL6667@ando.pearwood.info>
 <CANDiX9JPNRbqBGuDhVu0_fSgTJX3DoFrLzFWEN8MDorJye8kqw@mail.gmail.com>
Message-ID: <20180109084939.GQ6667@ando.pearwood.info>

On Mon, Jan 08, 2018 at 05:08:49PM -0600, boB Stepp wrote:
> Hi Steve,
> 
> On Mon, Jan 8, 2018 at 12:47 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> 
> > As I actually explained in my previous email, the one which has
> > disappeared into the aether, ...
> 
> Do you still have the email you sent?  I would like to read it if you
> don't mind sending it to me.

Mystery solved. I've been sending to the wrong email address...

Fixed now, and re-sent to the list.


-- 
Steve

From sjeik_appie at hotmail.com  Tue Jan  9 09:48:16 2018
From: sjeik_appie at hotmail.com (Albert-Jan Roskam)
Date: Tue, 9 Jan 2018 14:48:16 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <20180109084733.GG4152@ando.pearwood.info>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>,
 <20180109084733.GG4152@ando.pearwood.info>
Message-ID: <HE1PR1001MB130883816412E20BE03E640883100@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>

From: Tutor <tutor-bounces+sjeik_appie=hotmail.com at python.org> on behalf of Steven D'Aprano <steve at pearwood.info>
Sent: Tuesday, January 9, 2018 8:47 AM
To: tutor at python.org
Subject: Re: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter?

<snip>? 
> The Python 3.5 source code for os.path.realpath under Windows looks like 
> this:
>
># realpath is a no-op on systems without islink support
> realpath = abspath

D?j?-vu [1], but I think that it would be a great enhancement if os.realpath would return the UNC path if given a mapped drive in Windows, if needed as extended path (prefixed with "\\?\UNC\"). That's something I use all the time, unlike symlinks, in Windows. 

And I would also welcome a convenience function in the os.path module that does expanduser, expandvars, normpath, realpath, and maybe more.

I haven't used pathlib yet. Will os.path development some day be frozen so pathlib becomes the standard? It seems to be nicer.

[1] http://python.6.x6.nabble.com/Tutor-getUncPath-mappedDrive-td4652304.html

From tsu.yubo at gmail.com  Tue Jan  9 09:20:14 2018
From: tsu.yubo at gmail.com (YU Bo)
Date: Tue, 9 Jan 2018 22:20:14 +0800
Subject: [Tutor] delete strings from specificed words
Message-ID: <20180109142008.aduremugxw7ufmby@debian.debian>

Hi,

I am learning python to reslove issue,which make happy:)

But, i am facing an interesting question.I have no idea to deal with it.

The text i will working as follow:

```text

[PATCH] perf tools: Fix copyfile_offset update of output offset

We need to increase output offset in each iteration,
not decrease it as we currently do.

I guess we were lucky to finish in most cases in first
iteration, so the bug never showed. However it shows a
lot when working with big (~4GB) size data.

Link: http://lkml.kernel.org/n/tip-f4az7t2nxjbjz5tqrv83z64e at xxxxxxxxxxxxxx
Signed-off-by: Jiri Olsa <jolsa at xxxxxxxxxx>
---
 tools/perf/util/util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index a789f952b3e9..443892dabedb 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -210,7 +210,7 @@ static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64

 		size -= ret;
 		off_in += ret;
-		off_out -= ret;
+		off_out += ret;
 	}
 	munmap(ptr, off_in + size);

--
2.13.6

```
In fact, this is a patch from lkml,my goal is to design a kernel podcast
for myself to focus on what happened in kernel. I have crawled the text
with python and want to remove strings from *diff --git*, because reading
the git commit above, i have a shape in head.

I have tried split(), replace(), but i have no idea to deal with it.

I will  appericate if you have any idea.

Thanks!

From alan.gauld at yahoo.co.uk  Tue Jan  9 17:25:11 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Tue, 9 Jan 2018 22:25:11 +0000
Subject: [Tutor] delete strings from specificed words
In-Reply-To: <20180109142008.aduremugxw7ufmby@debian.debian>
References: <20180109142008.aduremugxw7ufmby@debian.debian>
Message-ID: <p33fca$anf$1@blaine.gmane.org>

On 09/01/18 14:20, YU Bo wrote:

> But, i am facing an interesting question.I have no idea to deal with it.

I don;t think you have given us enough context to
be able to help much. WE would need some idea of
the input and output data (both current and desired)

> [PATCH] perf tools: Fix copyfile_offset update of output offset
> 
> We need to increase output offset in each iteration,
> not decrease it as we currently do.
> 

It sounds like you are building some kind of pretty printer.
Maybe you could use Pythons pretty-print module as a design
template? Or maybe even use some of it directly. It just
depends on your data formats etc.

> In fact, this is a patch from lkml,my goal is to design a kernel podcast
> for myself to focus on what happened in kernel. 

Sorry, I've no idea what lkml is nor what kernel you are talking about.

Can you show us what you are receiving, what you are
currently producing and what you are trying to produce?

Some actual code might be an idea too.
And the python version and OS.

-- 
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



From eryksun at gmail.com  Tue Jan  9 22:56:16 2018
From: eryksun at gmail.com (eryk sun)
Date: Wed, 10 Jan 2018 03:56:16 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <HE1PR1001MB130883816412E20BE03E640883100@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <20180109084733.GG4152@ando.pearwood.info>
 <HE1PR1001MB130883816412E20BE03E640883100@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <CACL+1atYexUCOHn4HoO1fs6dj1C80BrywYaAWu2L2u1-HyZNwg@mail.gmail.com>

On Tue, Jan 9, 2018 at 2:48 PM, Albert-Jan Roskam
<sjeik_appie at hotmail.com> wrote:
>
> I think that it would be a great enhancement if os.realpath would return the UNC path if
> given a mapped drive in Windows, if needed as extended path (prefixed with "\\?\UNC\").
> That's something I use all the time, unlike symlinks, in Windows.

pathlib can do this for you, or call os.path._getfinalpathname. I
recently helped someone that wanted the reverse, to map the resolved
UNC path back to a logical drive:

https://bugs.python.org/issue32442

> And I would also welcome a convenience function in the os.path module that does
> expanduser, expandvars, normpath, realpath, and maybe more.

pathlib implements expanduser, but it's still lame on Windows for a
user other than the current user. It assumes all user profiles are in
the same directory instead of directly getting the user's profile
path. Anyway, expanduser is of limited use.

We can't assume in general that a user's special folders (e.g.
Desktop, Documents) are in the default location relative to the
profile directory. Almost all of them are relocatable. There are shell
APIs to look up the current locations, such as SHGetKnownFolderPath.
This can be called with ctypes [1]. For users other than the current
user, it requires logging on and impersonating the user, which
requires administrator access.

[1]: https://stackoverflow.com/a/33181421/205580

You can log a user on without a password by calling LsaLogonUser to
request an MSV1 S4U (service for user) logon. The access token will
only be identification level, unless the script is running as a SYSTEM
service. But identification level is enough to query the location of a
user's known folders. I don't recommended calling LsaLogonUser via
ctypes if you have the option to write an extension module in C/C++,
but I did manage to get it working with ctypes [2]. For example:

    >>> from security_lsa import logon_msv1_s4u
    >>> from knownfolders import FOLDERID, get_known_folder_path

    >>> logon_info = logon_msv1_s4u('Administrator')
    >>> get_known_folder_path(FOLDERID.Desktop, logon_info.Token)
    'C:\\Users\\Administrator\\Desktop'

[2]: https://stackoverflow.com/a/43233332/205580

Also, please don't use expanduser to enable applications to spam the
profile directory with configuration files and directories. Use the
local and roaming application data directories.

From tsu.yubo at gmail.com  Tue Jan  9 22:45:23 2018
From: tsu.yubo at gmail.com (YU Bo)
Date: Wed, 10 Jan 2018 11:45:23 +0800
Subject: [Tutor] delete strings from specificed words
In-Reply-To: <p33fca$anf$1@blaine.gmane.org>
References: <20180109142008.aduremugxw7ufmby@debian.debian>
 <p33fca$anf$1@blaine.gmane.org>
Message-ID: <20180110034521.twc73s25xrxsqr77@debian.debian>

Hi,

First, thank you very much for your reply.

On Tue, Jan 09, 2018 at 10:25:11PM +0000, Alan Gauld via Tutor wrote:
>On 09/01/18 14:20, YU Bo wrote:
>
>> But, i am facing an interesting question.I have no idea to deal with it.
>
>I don;t think you have given us enough context to
>be able to help much. WE would need some idea of
>the input and output data (both current and desired)
>
>>
>
>It sounds like you are building some kind of pretty printer.
>Maybe you could use Pythons pretty-print module as a design
>template? Or maybe even use some of it directly. It just
>depends on your data formats etc.

Yes. I think python can deal with it directly.

>
>> In fact, this is a patch from lkml,my goal is to design a kernel podcast
>> for myself to focus on what happened in kernel.
>
>Sorry, I've no idea what lkml is nor what kernel you are talking about.
>
>Can you show us what you are receiving, what you are
>currently producing and what you are trying to produce?
>
>Some actual code might be an idea too.
>And the python version and OS.

Sorry, i don't to explain it.But, my code is terribly.

lkml.py:

```code
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# File Name: lkml.py
# Author: Bo Yu

""" This is source code in page that i want to get

"""
import sys
reload(sys)
sys.setdefaultencoding('utf8')

import urllib2
from bs4 import BeautifulSoup
import requests

import chardet
import re

# import myself print function

from get_content import print_content

if __name__ == '__main__':
    comment_url = []
    target = 'https://www.spinics.net/lists/kernel/threads.html'
    req = requests.get(url=target)
    req.encoding = 'utf-8'
    content = req.text
    bf = BeautifulSoup(content ,'lxml') # There is no problem

    context = bf.find_all('strong')
    for ret in context[0:1]:
          for test in ret:
                print '\t'
	        x = re.split(' ', str(test))
		y = re.search('"(.+?)"', str(x)).group(1)
		comment_url.append(target.replace("threads.html", str(y)))

    for tmp_target in comment_url:
	print "===This is a new file ==="
	print_content(tmp_target, 'utf-8', 'title')

```
get_content.py:

```code
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# File Name: get_content.py

import urllib2
from bs4 import BeautifulSoup
import requests

import chardet
import re

def print_content(url, charset, find_id):
    req = requests.get(url=url)
    req.encoding = charset
    content = req.text
    bf = BeautifulSoup(content ,'lxml')
    article_title = bf.find('h1')
    #author = bf.find_all('li')
    commit = bf.find('pre')
    print '\t'
    print article_title.get_text()
    print '\t'
    x = str(commit.get_text())
    print x
```
python --version: Python 2.7.13
OS: debian 9
usage: python lkml.py
output: oh...
https://pastecode.xyz/view/04645424

Please ignore my print debug format.

This is my code and i can get text like output above.
So, simple my quzz:
I dont know how to delete strings after special word, for example:

```text
The registers rax, rcx and rdx are touched when controlling IBRS
so they need to be saved when they can't be clobbered.

diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index 45a63e0..3b9b238 100644
...
```
I want to delete string from *diff --git* to end, because too many code is here

Whatever, thanks!


>
>--
>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 at python.org
>To unsubscribe or change subscription options:
>https://mail.python.org/mailman/listinfo/tutor

From __peter__ at web.de  Wed Jan 10 04:37:09 2018
From: __peter__ at web.de (Peter Otten)
Date: Wed, 10 Jan 2018 10:37:09 +0100
Subject: [Tutor] delete strings from specificed words
References: <20180109142008.aduremugxw7ufmby@debian.debian>
 <p33fca$anf$1@blaine.gmane.org>
 <20180110034521.twc73s25xrxsqr77@debian.debian>
Message-ID: <p34moa$4ph$1@blaine.gmane.org>

YU Bo wrote:

> ```text
> The registers rax, rcx and rdx are touched when controlling IBRS
> so they need to be saved when they can't be clobbered.
> 
> diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
> index 45a63e0..3b9b238 100644
> ...
> ```
> I want to delete string from *diff --git* to end, because too many code is
> here

Use str.split() or str.partition() and only keep the first part: 

>>> text = """The registers rax, rcx and rdx are touched when controlling 
IBRS
... so they need to be saved when they can't be clobbered.
... 
... diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
... index 45a63e0..3b9b238 100644
... """
>>> cleaned_text = text.partition("diff --git")[0].strip()
>>> print(cleaned_text)
The registers rax, rcx and rdx are touched when controlling IBRS
so they need to be saved when they can't be clobbered.



From tsu.yubo at gmail.com  Wed Jan 10 07:22:24 2018
From: tsu.yubo at gmail.com (YU Bo)
Date: Wed, 10 Jan 2018 20:22:24 +0800
Subject: [Tutor] delete strings from specificed words
In-Reply-To: <p34moa$4ph$1@blaine.gmane.org>
References: <20180109142008.aduremugxw7ufmby@debian.debian>
 <p33fca$anf$1@blaine.gmane.org>
 <20180110034521.twc73s25xrxsqr77@debian.debian>
 <p34moa$4ph$1@blaine.gmane.org>
Message-ID: <20180110122221.sf4r2674o5nfqog2@debian.debian>

Hi,
On Wed, Jan 10, 2018 at 10:37:09AM +0100, Peter Otten wrote:
>YU Bo wrote:
>
>> index 45a63e0..3b9b238 100644
>> ...
>> ```
>> I want to delete string from *diff --git* to end, because too many code is
>> here
>
>Use str.split() or str.partition() and only keep the first part:
>
>>>> text = """The registers rax, rcx and rdx are touched when controlling
>IBRS
>... so they need to be saved when they can't be clobbered.
>...
>... diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
>... index 45a63e0..3b9b238 100644
>... """
>>>> cleaned_text = text.partition("diff --git")[0].strip()
>>>> print(cleaned_text)
>The registers rax, rcx and rdx are touched when controlling IBRS
>so they need to be saved when they can't be clobbered.

Cool,It is what i want.

Thanks all!

Bo

>
>
>_______________________________________________
>Tutor maillist  -  Tutor at python.org
>To unsubscribe or change subscription options:
>https://mail.python.org/mailman/listinfo/tutor

From sjeik_appie at hotmail.com  Wed Jan 10 07:59:32 2018
From: sjeik_appie at hotmail.com (Albert-Jan Roskam)
Date: Wed, 10 Jan 2018 12:59:32 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <CACL+1atYexUCOHn4HoO1fs6dj1C80BrywYaAWu2L2u1-HyZNwg@mail.gmail.com>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <20180109084733.GG4152@ando.pearwood.info>
 <HE1PR1001MB130883816412E20BE03E640883100@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>,
 <CACL+1atYexUCOHn4HoO1fs6dj1C80BrywYaAWu2L2u1-HyZNwg@mail.gmail.com>
Message-ID: <HE1PR1001MB1308B70141F625274F3F0A7F83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>


From: eryk sun <eryksun at gmail.com>
Sent: Wednesday, January 10, 2018 3:56 AM
To: tutor at python.org
Cc: Albert-Jan Roskam
Subject: Re: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter?
? 

On Tue, Jan 9, 2018 at 2:48 PM, Albert-Jan Roskam
<sjeik_appie at hotmail.com> wrote:
>
>> I think that it would be a great enhancement if os.realpath would return the UNC path if
>> given a mapped drive in Windows, if needed as extended path (prefixed with "\\?\UNC\").
>> That's something I use all the time, unlike symlinks, in Windows.
>
>pathlib can do this for you, or call os.path._getfinalpathname. 

I tried: 
>>> from os.path import _getfullpathname
>>> _getfullpathname(r"H:")
'h:\\path\\to\\folder'
>>> import os
>>> os.getcwd()
'h:\\path\\to\\folder'

I expected h:\ to be \\server\share\foo. The fact that the current working directory was returned was even more unexpected.

>>I recently helped someone that wanted the reverse, to map the resolved
>>UNC path back to a logical drive:

Oh dear. Why would anybody *want* the drive letters? They are only useful because (a) they save on keystrokes (b) they bypass the annoying limitation of the cd command on windows, ie. it does not work with UNC paths. Driveletter-->UNC conversion is useful when e.g. logging file paths. I do wonder whether the method used to assign the drive letter matters with the . I know net use, pushd, subst. I use 'net use' for more or less permanent drives and pushd/popd to get a temporary drive, available letter (cd nuisance).

>We can't assume in general that a user's special folders (e.g.
>Desktop, Documents) are in the default location relative to the
>profile directory. Almost all of them are relocatable. There are shell
>APIs to look up the current locations, such as SHGetKnownFolderPath.
>This can be called with ctypes [1]. For users other than the current
>user, it requires logging on and impersonating the user, which
>requires administrator access.
>
>[1]: https://stackoverflow.com/a/33181421/205580

Interesting code! I have used the following, which uses SHGetFolderPath, ie. without 'Known'.
from win32com.shell import shell, shellcon
desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0)

Working with ctypes.wintypes is quite complex!



From sjeik_appie at hotmail.com  Wed Jan 10 11:08:04 2018
From: sjeik_appie at hotmail.com (Albert-Jan Roskam)
Date: Wed, 10 Jan 2018 16:08:04 +0000
Subject: [Tutor] question about metaclasses
Message-ID: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>

Hi,


In another thread on this list I was reminded of types.SimpleNamespace. This is nice, but I wanted to create a bag class with constants that are read-only. My main question is about example #3 below (example #2 just illustrates my thought process). Is this a use case to a metaclass? Or can I do it some other way (maybe a class decorator?). I would like to create a metaclass that converts any non-special attributes (=not starting with '_') into properties, if needed. That way I can specify my bag class in a very clean way: I only specify the metaclass, and I list the attributes as normal attrbutes, because the metaclass will convert them into properties.


Why does following the line (in #3) not convert the normal attribute into a property?

setattr(cls, attr, property(lambda self: obj))  # incorrect!



# 1-------------------------------------------------
# nice, but I want the constants to be read-only
from types import SimpleNamespace
const = SimpleNamespace(YES=1, NO=0, DUNNO=9)
const.YES = 0
print(const)


# 2-------------------------------------------------
# works, but I wonder if there's a builtin way
class Const(object):
    """Adding attributes is ok, modifying them is not"""
    YES = property(lambda self: 1)
    NO = property(lambda self: 0)
    DUNNO = property(lambda self: 42)
    #THROWS_ERROR = 666

    def __new__(cls):
        for attr in dir(cls):
            if attr.startswith('_'):
                continue
            elif not isinstance(getattr(cls, attr), property):
                raise ValueError("Only properties allowed")
        return super().__new__(cls)
    def __repr__(self):
        kv = ["%s=%s" % (attr, getattr(self, attr)) for \
              attr in sorted(dir(Const)) if not attr.startswith('_')]
        return "ReadOnlyNamespace(" + ", ".join(kv) + ")"

c = Const()
print(repr(c))
#c.YES = 42  # raises AttributeError (desired behavior)

print(c.YES)


# 3-------------------------------------------------
class Meta(type):
    def __new__(cls, name, bases, attrs):
        for attr, obj in attrs.items():
            if attr.startswith('_'):
                continue
            elif not isinstance(obj, property):
                import pdb;pdb.set_trace()
                #setattr(cls, attr, property(lambda self: obj))  # incorrect!
                raise ValueError("Only properties allowed")
        return super().__new__(cls, name, bases, attrs)

class MyReadOnlyConst(metaclass=Meta):
    __metaclass__ = Meta
    YES = property(lambda self: 1)
    NO = property(lambda self: 0)
    DUNNO = property(lambda self: 42)
    THROWS_ERROR = 666


c2 = MyReadOnlyConst()
print(c2.THROWS_ERROR)
#c2.THROWS_ERROR = 777
#print(c2.THROWS_ERROR)


Thank you in advance and sorry about the large amount of code!


Albert-Jan


From steve at pearwood.info  Wed Jan 10 12:54:38 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Thu, 11 Jan 2018 04:54:38 +1100
Subject: [Tutor] question about metaclasses
In-Reply-To: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <20180110175438.GS6667@ando.pearwood.info>

On Wed, Jan 10, 2018 at 04:08:04PM +0000, Albert-Jan Roskam wrote:

> In another thread on this list I was reminded of 
> types.SimpleNamespace. This is nice, but I wanted to create a bag 
> class with constants that are read-only.

If you expect to specify the names of the constants ahead of time, the 
best solution is (I think) a namedtuple.

from collections import namedtuple
Bag = namedtuple('Bag', 'yes no dunno')
a = Bag(yes=1, no=0, dunno=42)
b = Bag(yes='okay', no='no way', dunno='not a clue')

ought to do what you want.

Don't make the mistake of doing this:

from collections import namedtuple
a = namedtuple('Bag', 'yes no dunno')(yes=1, no=0, dunno=42)
b = namedtuple('Bag', 'yes no dunno')(yes='okay', no='no way', dunno='not a clue')

because that's quite wasteful of memory: each of a and b belong to a 
separate hidden class, and classes are rather largish objects.


If you expect to be able to add new items on the fly, but have them 
read-only once set, that's a different story.


-- 
Steve

From zachary.ware+pytut at gmail.com  Wed Jan 10 13:08:39 2018
From: zachary.ware+pytut at gmail.com (Zachary Ware)
Date: Wed, 10 Jan 2018 12:08:39 -0600
Subject: [Tutor] question about metaclasses
In-Reply-To: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <CAKJDb-MbWHTs3y7es72O7mZ4h=K_6zX452hO3VW_VxkzTozB0g@mail.gmail.com>

On Wed, Jan 10, 2018 at 10:08 AM, Albert-Jan Roskam
<sjeik_appie at hotmail.com> wrote:
> Hi,
>
>
> In another thread on this list I was reminded of types.SimpleNamespace. This is nice, but I wanted to create a bag class with constants that are read-only. My main question is about example #3 below (example #2 just illustrates my thought process). Is this a use case to a metaclass? Or can I do it some other way (maybe a class decorator?). I would like to create a metaclass that converts any non-special attributes (=not starting with '_') into properties, if needed. That way I can specify my bag class in a very clean way: I only specify the metaclass, and I list the attributes as normal attrbutes, because the metaclass will convert them into properties.

You appear to be reimplementing Enum.

> Why does following the line (in #3) not convert the normal attribute into a property?
>
> setattr(cls, attr, property(lambda self: obj))  # incorrect!

Because `cls` is `Meta`, not `MyReadOnlyConst`; `__new__` is
implicitly a classmethod and `MyReadOnlyConst` doesn't actually exist
yet.  When `MyReadOnlyConst` is created by `type.__new__` it will be
filled with the contents of `attrs`, so instead of `setattr` you want
`attrs[attr] = property(...)`.

But once you're past the learning exercise that this is, just use
enum.Enum or collections.namedtuple :)

-- 
Zach

From __peter__ at web.de  Wed Jan 10 13:29:58 2018
From: __peter__ at web.de (Peter Otten)
Date: Wed, 10 Jan 2018 19:29:58 +0100
Subject: [Tutor] question about metaclasses
References: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <p35lvd$jp0$1@blaine.gmane.org>

Albert-Jan Roskam wrote:

> Why does following the line (in #3) 

> # 3-------------------------------------------------
> class Meta(type):
>     def __new__(cls, name, bases, attrs):
>         for attr, obj in attrs.items():
>             if attr.startswith('_'):
>                 continue
>             elif not isinstance(obj, property):
>                 import pdb;pdb.set_trace()
>                 #setattr(cls, attr, property(lambda self: obj))  #
>                 #incorrect!
>                 raise ValueError("Only properties allowed")
>         return super().__new__(cls, name, bases, attrs)
> 
> class MyReadOnlyConst(metaclass=Meta):
>     __metaclass__ = Meta
>     YES = property(lambda self: 1)
>     NO = property(lambda self: 0)
>     DUNNO = property(lambda self: 42)
>     THROWS_ERROR = 666
> 
> 
> c2 = MyReadOnlyConst()
> print(c2.THROWS_ERROR)
> #c2.THROWS_ERROR = 777
> #print(c2.THROWS_ERROR)

> not convert the normal attribute into
> a property?
> 
> setattr(cls, attr, property(lambda self: obj))  # incorrect!

cls is Meta itself, not MyReadOnlyConst (which is an instance of Meta).
When the code in Meta.__new__() executes MyReadOnlyConst does not yet exist,
but future attributes are already there, in the form of the attrs dict.
Thus to convert the integer value into a read-only property you can 
manipulate that dict (or the return value of super().__new__()):

class Meta(type):
    def __new__(cls, name, bases, attrs):
        for attr, obj in attrs.items():
            if attr.startswith('_'):
                continue
            elif not isinstance(obj, property):
                attrs[attr] = property(lambda self, obj=obj: obj)
                
        return super().__new__(cls, name, bases, attrs)

class MyReadOnlyConst(metaclass=Meta):
    YES = property(lambda self: 1)
    NO = property(lambda self: 0)
    DUNNO = property(lambda self: 42)
    THROWS_ERROR = 666

c = MyReadOnlyConst()
try:
    c.THROWS_ERROR = 42
except AttributeError:
    pass
else:
    assert False
assert c.THROWS_ERROR == 666

PS: If you don't remember why the obj=obj is necessary:
Python uses late binding; without that trick all lambda functions would 
return the value bound to the obj name when the for loop has completed.
A simplified example:

>>> fs = [lambda: x for x in "abc"]
>>> fs[0](), fs[1](), fs[2]()
('c', 'c', 'c')
>>> fs = [lambda x=x: x for x in "abc"]
>>> fs[0](), fs[1](), fs[2]()
('a', 'b', 'c')



From eryksun at gmail.com  Wed Jan 10 15:20:57 2018
From: eryksun at gmail.com (eryk sun)
Date: Wed, 10 Jan 2018 20:20:57 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <HE1PR1001MB1308B70141F625274F3F0A7F83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <20180109084733.GG4152@ando.pearwood.info>
 <HE1PR1001MB130883816412E20BE03E640883100@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
 <CACL+1atYexUCOHn4HoO1fs6dj1C80BrywYaAWu2L2u1-HyZNwg@mail.gmail.com>
 <HE1PR1001MB1308B70141F625274F3F0A7F83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <CACL+1asRF84w1F2cgkEd3n43pjf7nVmX3_j-JbLqBoPHV_ZLgQ@mail.gmail.com>

On Wed, Jan 10, 2018 at 12:59 PM, Albert-Jan Roskam
<sjeik_appie at hotmail.com> wrote:
>
> I tried:
>>>> from os.path import _getfullpathname
>>>> _getfullpathname(r"H:")
> 'h:\\path\\to\\folder'
>>>> import os
>>>> os.getcwd()
> 'h:\\path\\to\\folder'
>
> I expected h:\ to be \\server\share\foo.

You called _getfullpathname (WinAPI GetFullPathName), not
_getfinalpathname (WinAPI GetFinalPathNameByHandle). GetFullPathName
works on the path as a string without touching the filesystem.
GetFinalPathNameByHandle reconstructs a path when given a handle to a
file or directory.

> The fact that the current working directory was returned was even more unexpected.

"H:" or "H:relative/path" is relative to the working directory on
drive H:. The process only has one working directory, but
GetFullPathName also checks for environment variables such as "=H:".
The C runtime's _chdir function sets these magic variables, as does
Python's os.chdir function (we don't call C _chdir). WinAPI
SetCurrentDirectory does not set them. For example:

    >>> os.chdir('Z:/Temp')
    >>> win32api.GetEnvironmentVariable('=Z:')
    'Z:\\Temp'
    >>> os.path._getfullpathname('Z:relative')
    'Z:\\Temp\\relative'

> Why would anybody *want* the drive letters? They are only useful because (a) they save on
> keystrokes (b) they bypass the annoying limitation of the cd command on windows, ie. it
> does not work with UNC paths.

Windows itself has no problem using a UNC path as the working
directory. That's a limit of the CMD shell.

SUBST drives can be used to access long paths. Since the substitution
occurs in the kernel, it avoids the MAX_PATH 260-character limit. Of
course, you can also use junctions and symlinks to access long paths,
or in Windows 10 simply enable long-path support.

> I know net use, pushd, subst. I use 'net use' for more or less permanent drives and
> pushd/popd to get a temporary drive, available letter (cd nuisance).

`net.exe use` and CMD's PUSHD command (with a UNC path) both call
WinAPI WNetAddConnection2 to create a mapped network drive. The
difference is that net.exe can supply alternate credentials and create
a persistent mapping, while PUSHD uses the current user's credentials
and creates a non-persistent mapping.

If your account gets logged on with a UAC split token, the standard
and elevated tokens actually have separate logon sessions with
separate local-device mappings. You can enable a policy to link the
two logon sessions. Set a DWORD value of 1 named
"EnableLinkedConnections" in the key
"HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System", and
reboot.

subst.exe creates substitute paths using WinAPI DefineDosDevice.
Unlike the WNet API, this function doesn't use MPR (multiple provider
router) to create a direct link for the network provider (e.g.
\Device\LanmanRedirectory); doesn't create a linked connection when
EnableLinkedConnections is defined; and can't create a persistent
drive with stored credentials (though you can use an account logon
script for this). On the plus side, a drive mapped via subst.exe can
target any path.

> Interesting code! I have used the following, which uses SHGetFolderPath, ie. without 'Known'.
> from win32com.shell import shell, shellcon
> desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0)

SHGetFolderPath is usually fine, but still, it's outdated and
deprecated. win32com.shell doesn't wrap SHGetKnownFolderPath for some
reason, but you can still use the new known-folder API without ctypes.
Just create a KnownFolderManager instance. For example:

    import pythoncom
    from win32com.shell import shell

    kfmgr = pythoncom.CoCreateInstance(shell.CLSID_KnownFolderManager, None,
                pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IKnownFolderManager)

    desktop_path = kfmgr.GetFolder(shell.FOLDERID_Desktop).GetPath()

This doesn't work as conveniently for getting known folders of other
users. While the high-level SHGetKnownFolderPath function takes care
of loading the user profile and impersonating, we have to do this
ourselves when using a KnownFolderManager instance.

That said, to correct my previous post, you have to be logged on with
SeTcbPrivilege access (e.g. a SYSTEM service) to get and set other
users' known folders without their password. (If you have the password
you can use a regular logon instead of an S4U logon, and that works
fine.)

> Working with ctypes.wintypes is quite complex!

I wouldn't say ctypes is complex in general. But calling LsaLogonUser
is complex due to all of the structs that include variable-sized
buffers. And working with COM via ctypes is also complex, which is why
comtypes exists.

From alan.gauld at yahoo.co.uk  Wed Jan 10 19:14:15 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Thu, 11 Jan 2018 00:14:15 +0000
Subject: [Tutor] Why does os.path.realpath('test_main.py') give
 different results for unittest than for testing statement in interpreter?
In-Reply-To: <CACL+1asRF84w1F2cgkEd3n43pjf7nVmX3_j-JbLqBoPHV_ZLgQ@mail.gmail.com>
References: <CANDiX9+0m4nuEjDQWgVvxBr7fPRFRq3EoiSX4qkE901otR8uDg@mail.gmail.com>
 <20180107080558.GC4152@ando.pearwood.info>
 <CANDiX9Kd9dnMAVnNe9CA2-pdD0jxz0DB8_NGofSuioE5bj-feQ@mail.gmail.com>
 <20180109084733.GG4152@ando.pearwood.info>
 <HE1PR1001MB130883816412E20BE03E640883100@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
 <CACL+1atYexUCOHn4HoO1fs6dj1C80BrywYaAWu2L2u1-HyZNwg@mail.gmail.com>
 <HE1PR1001MB1308B70141F625274F3F0A7F83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
 <CACL+1asRF84w1F2cgkEd3n43pjf7nVmX3_j-JbLqBoPHV_ZLgQ@mail.gmail.com>
Message-ID: <p36a4p$s5o$1@blaine.gmane.org>

On 10/01/18 20:20, eryk sun wrote:

> ... And working with COM via ctypes is also complex, which is why
> comtypes exists.

Or easier still Pythonwin (aka PyWin32).
I far prefer pythonwin over ctypes for any kind of COM work.

-- 
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



From cs at cskk.id.au  Wed Jan 10 19:40:35 2018
From: cs at cskk.id.au (Cameron Simpson)
Date: Thu, 11 Jan 2018 11:40:35 +1100
Subject: [Tutor] delete strings from specificed words
In-Reply-To: <20180109142008.aduremugxw7ufmby@debian.debian>
References: <20180109142008.aduremugxw7ufmby@debian.debian>
Message-ID: <20180111004035.GA54986@cskk.homeip.net>

On 09Jan2018 22:20, YU Bo <tsu.yubo at gmail.com> wrote:
>The text i will working as follow:
>
>```text
[...]
>diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
>index a789f952b3e9..443892dabedb 100644
[...]
>+++ b/tools/perf/util/util.c
[...]
>```
>In fact, this is a patch from lkml,my goal is to design a kernel podcast
>for myself to focus on what happened in kernel. I have crawled the text
>with python and want to remove strings from *diff --git*, because reading
>the git commit above, i have a shape in head.
>
>I have tried split(), replace(), but i have no idea to deal with it.

Do you have the text as above - a single string - or coming from a file? I'll 
presume a single string.

I would treat the text as lines, particularly since the diff markers etc are 
all line oriented.

So you might write something like this:

  interesting = []
  for line in the_text.splitlines():
    if line.startswith('diff --git '):
      break
    interesting.append(line)

Now the "interesting" list has the lines you want.

There's any number of variations on that you might use, but that should get you 
going.

Cheers,
Cameron Simpson <cs at cskk.id.au>

From robertvstepp at gmail.com  Wed Jan 10 21:02:24 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Wed, 10 Jan 2018 20:02:24 -0600
Subject: [Tutor] When is and isn't "__file__" set?
Message-ID: <CANDiX9JUV6zYkxHZAkc7=ZVYhbAELWw2Z-qJ4sM_8MD1zEG0Hw@mail.gmail.com>

I am actually interested in the answer to this question for Python
versions 2.4, 2.6 and 3.x.

At https://docs.python.org/3/reference/import.html?highlight=__file__#__file__
it says:

<quote>
__file__ is optional. If set, this attribute?s value must be a string.
The import system may opt to leave __file__ unset if it has no
semantic meaning (e.g. a module loaded from a database).

If __file__ is set, it may also be appropriate to set the __cached__
attribute which is the path to any compiled version of the code (e.g.
byte-compiled file). The file does not need to exist to set this
attribute; the path can simply point to where the compiled file would
exist (see PEP 3147).

It is also appropriate to set __cached__ when __file__ is not set.
However, that scenario is quite atypical. Ultimately, the loader is
what makes use of __file__ and/or __cached__. So if a loader can load
from a cached module but otherwise does not load from a file, that
atypical scenario may be appropriate.
</quote>

I am still puzzling over things from the thread, "Why does
os.path.realpath('test_main.py') give different results for unittest
than for testing statement in interpreter?"  The basic question I am
trying to answer is how to determine the path to a particular module
that is being run.  For the experiments I have run thus far, the
module attribute, "__file__", has so far reliably given me the
absolute path to the module being run.  But the documentation suggests
that this attribute is optional.  So what can I rely on here with
"__file__"?  The first sentence of the cited quote is not illuminating
this sufficiently for me.


-- 
boB

From steve at pearwood.info  Wed Jan 10 21:44:26 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Thu, 11 Jan 2018 13:44:26 +1100
Subject: [Tutor] When is and isn't "__file__" set?
In-Reply-To: <CANDiX9JUV6zYkxHZAkc7=ZVYhbAELWw2Z-qJ4sM_8MD1zEG0Hw@mail.gmail.com>
References: <CANDiX9JUV6zYkxHZAkc7=ZVYhbAELWw2Z-qJ4sM_8MD1zEG0Hw@mail.gmail.com>
Message-ID: <20180111024426.GU6667@ando.pearwood.info>

On Wed, Jan 10, 2018 at 08:02:24PM -0600, boB Stepp wrote:

> I am still puzzling over things from the thread, "Why does
> os.path.realpath('test_main.py') give different results for unittest
> than for testing statement in interpreter?"  The basic question I am
> trying to answer is how to determine the path to a particular module
> that is being run.  For the experiments I have run thus far, the
> module attribute, "__file__", has so far reliably given me the
> absolute path to the module being run.  But the documentation suggests
> that this attribute is optional.  So what can I rely on here with
> "__file__"?  The first sentence of the cited quote is not illuminating
> this sufficiently for me.

Modules which are loaded from a .py or .pyc file on disk should always 
have __file__ set. If they don't, that's a bug in the interpreter.

Modules which are loaded from a .dll or .so binary file also should have 
__file__ set.

Modules that you create on the fly like this:

py> from types import ModuleType
py> module = ModuleType('module')
py> module.__file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'module' has no attribute '__file__'


will not have __file__ set unless you manually set it yourself. Such 
hand-made modules can be stored in databases and retrieved later, in 
which case they still won't have a __file__ attribute.

Module objects which are built into the interpreter itself, like sys, 
also won't have a __file__ attribute:

py> sys.__file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'sys' has no attribute '__file__'


One tricky, but unusual case, is that Python supports importing 
and running modules loaded from zip files. Very few people know this 
feature even exists -- it is one of Python's best kept secrets -- and 
even fewer know how it works. I'm not sure what happens when you load a 
module from a zip file, whether it will have a __file__ or not.

Basically, if you still to reading module.__file__ for modules which 
come from a .py file, you should be absolutely fine. But to practice 
defensive programming, something like:

try:
    path = module.__file__
except AttributeError:
    print('handle the case where the module doesn't exist on disk')
else:
    print('handle the case where the module does exist on disk')
    

might be appropriate.



-- 
Steve

From tsu.yubo at gmail.com  Wed Jan 10 23:16:47 2018
From: tsu.yubo at gmail.com (YU Bo)
Date: Thu, 11 Jan 2018 12:16:47 +0800
Subject: [Tutor] delete strings from specificed words
In-Reply-To: <20180111004035.GA54986@cskk.homeip.net>
References: <20180109142008.aduremugxw7ufmby@debian.debian>
 <20180111004035.GA54986@cskk.homeip.net>
Message-ID: <20180111041645.qion2zqoam4czfnj@debian.debian>

Hi,
On Thu, Jan 11, 2018 at 11:40:35AM +1100, Cameron Simpson wrote:
>On 09Jan2018 22:20, YU Bo <tsu.yubo at gmail.com> wrote:
>>The text i will working as follow:
>>
>>```text
>[...]
>>diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
>>index a789f952b3e9..443892dabedb 100644
>[...]
>>+++ b/tools/perf/util/util.c
>[...]
>>```
[...]
>>
>>I have tried split(), replace(), but i have no idea to deal with it.
>
>Do you have the text as above - a single string - or coming from a
>file? I'll presume a single string.

En.., the text is  multi-string from str(something) within python.

>
>I would treat the text as lines, particularly since the diff markers
>etc are all line oriented.
>
>So you might write something like this:
>
> interesting = []
> for line in the_text.splitlines():
>   if line.startswith('diff --git '):
>     break
>   interesting.append(line)
>
>Now the "interesting" list has the lines you want.

Yes, i test your method  and it will come to my intend, but maybe cast
a few of other steps.

I think that the method will offer a similar ways to solve others issues.
I personally like peter's method: text.partition("diff  --git")[0].strip()

Thanks,
Bo
>
>There's any number of variations on that you might use, but that
>should get you going.
>
>Cheers,
>Cameron Simpson <cs at cskk.id.au>

From cs at cskk.id.au  Thu Jan 11 03:20:42 2018
From: cs at cskk.id.au (Cameron Simpson)
Date: Thu, 11 Jan 2018 19:20:42 +1100
Subject: [Tutor] delete strings from specificed words
In-Reply-To: <20180111041645.qion2zqoam4czfnj@debian.debian>
References: <20180111041645.qion2zqoam4czfnj@debian.debian>
Message-ID: <20180111082042.GA55776@cskk.homeip.net>

On 11Jan2018 12:16, YU Bo <tsu.yubo at gmail.com> wrote:
>Hi,

Hi,

>On Thu, Jan 11, 2018 at 11:40:35AM +1100, Cameron Simpson wrote:
>>Do you have the text as above - a single string - or coming from a
>>file? I'll presume a single string.
>
>En.., the text is  multi-string from str(something) within python.

That's a single string in my thinking.

>>I would treat the text as lines, particularly since the diff markers
>>etc are all line oriented.
>>
>>So you might write something like this:
>>
>>interesting = []
>>for line in the_text.splitlines():
>>  if line.startswith('diff --git '):
>>    break
>>  interesting.append(line)
>>
>>Now the "interesting" list has the lines you want.
>
>Yes, i test your method  and it will come to my intend, but maybe cast
>a few of other steps.
>
>I think that the method will offer a similar ways to solve others issues.
>I personally like peter's method: text.partition("diff  --git")[0].strip()

Yes, Peter's partition method is very short and direct. Personally I would 
include a leading newline in the string, thus:

  text.partition("\ndiff --git ")

to make it more precise. Consider a patch which discusses your script; its 
comment area might well mention the string "diff --git", as this email does.

What you end up with may depend on what further things you do with the text.

Cheers,
Cameron Simpson <cs at cskk.id.au>

From rls4jc at gmail.com  Thu Jan 11 17:52:50 2018
From: rls4jc at gmail.com (Roger Lea Scherer)
Date: Thu, 11 Jan 2018 14:52:50 -0800
Subject: [Tutor] xlrd has no attribute
Message-ID: <CAPvEsMz2iv_kxnjnJFumJNONNvzhXOsKX7O2W7O8BrZ+=Xrp6A@mail.gmail.com>

I'm trying to learn how open a xls file in python. I thought this would be
easier. I've read on a blog this code and seen it on other websites. I
thought I'd try it out. I'm on Windows 10 with python 3.6.4.

import xlrd

def open_file(path):
    """
    Open and read an Excel file
    """
    book = xlrd.open_workbook(path)

    # print number of sheets
    print(book.nsheets)

    # print sheet names
    print(book.sheet_names())

    # get the first worksheet
    first_sheet = book.sheet_by_index(0)

    # read a row
    print(first_sheet.row_values(0))

    # read a cell
    cell = first_sheet.cell(0,0)
    print(cell)
    print(cell.value)

open_file("C:/Users/Roger/Documents/Roger/archive/area codes.xls")

But I get an error:

Traceback (most recent call last):
  File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 1, in <module>
    import xlrd
  File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 26, in <module>
    open_file("C:/Users/Roger/Documents/Roger/archive/area codes.xls")
  File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 7, in open_file
    book = xlrd.open_workbook(path)
AttributeError: module 'xlrd' has no attribute 'open_workbook'

I've looked at http://www.lexicon.net/sjmachin/xlrd.html and it looks like
it should be ok. I've looked at Stack overflow and I have the
opening/closing parentheses appropriately placed to make it a method.

Can you help, please?

From alan.gauld at yahoo.co.uk  Thu Jan 11 19:22:25 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Fri, 12 Jan 2018 00:22:25 +0000
Subject: [Tutor] xlrd has no attribute
In-Reply-To: <CAPvEsMz2iv_kxnjnJFumJNONNvzhXOsKX7O2W7O8BrZ+=Xrp6A@mail.gmail.com>
References: <CAPvEsMz2iv_kxnjnJFumJNONNvzhXOsKX7O2W7O8BrZ+=Xrp6A@mail.gmail.com>
Message-ID: <p38v03$hg7$1@blaine.gmane.org>

On 11/01/18 22:52, Roger Lea Scherer wrote:

> Traceback (most recent call last):
>   File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 1, in <module>
>     import xlrd

Look closely at the error message.
What is the name of the file that causes the error?
What is the name of the module you are importing?

You are masking the xlrd module with your xlrd.py file
and so import your own file.

Your file does not have the method so you get an error.

Don't name your applications after the modules you are using.

-- 
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



From sjeik_appie at hotmail.com  Fri Jan 12 12:22:05 2018
From: sjeik_appie at hotmail.com (Albert-Jan Roskam)
Date: Fri, 12 Jan 2018 17:22:05 +0000
Subject: [Tutor] When is and isn't "__file__" set?
Message-ID: <HE1PR1001MB13088EBE72CAFA8FCA4F6ED083170@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>


On Jan 11, 2018 03:47, Steven D'Aprano <steve at pearwood.info> wrote:
>
> On Wed, Jan 10, 2018 at 08:02:24PM -0600, boB Stepp wrote:
>
> > I am still puzzling over things from the thread, "Why does
> > os.path.realpath('test_main.py') give different results for unittest
> > than for testing statement in interpreter?"  The basic question I am
> > trying to answer is how to determine the path to a particular module
> > that is being run.  For the experiments I have run thus far, the
> > module attribute, "__file__", has so far reliably given me the
> > absolute path to the module being run.  But the documentation suggests
> > that this attribute is optional.  So what can I rely on here with
> > "__file__"?  The first sentence of the cited quote is not illuminating
> > this sufficiently for me.
>
> Modules which are loaded from a .py or .pyc file on disk should always
> have __file__ set. If they don't, that's a bug in the interpreter.
>
> Modules which are loaded from a .dll or .so binary file also should have
> __file__ set.

And .pyd? I would hope so

> Modules that you create on the fly like this:
>
> py> from types import ModuleType
> py> module = ModuleType('module')
> py> module.__file__
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> AttributeError: module 'module' has no attribute '__file__'

Fascinating. Will this allow you to write a BLOB of the marshalled module object to a database? Do you happen to know a use case of this?

> will not have __file__ set unless you manually set it yourself. Such
> hand-made modules can be stored in databases and retrieved later, in
> which case they still won't have a __file__ attribute.
>
> Module objects which are built into the interpreter itself, like sys,
> also won't have a __file__ attribute:
>
> py> sys.__file__
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> AttributeError: module 'sys' has no attribute '__file__'
>
>
> One tricky, but unusual case, is that Python supports importing
> and running modules loaded from zip files. Very few people know this
> feature even exists -- it is one of Python's best kept secrets -- and
> even fewer know how it works. I'm not sure what happens when you load a
> module from a zip file, whether it will have a __file__ or not.

On this page https://pymotw.com/3/sys/imports.html, I see these lines:
"# Set a few properties required by PEP 302
mod.__file__ = fullname
"

Which suggests to me that it depends on the discipline of the custom importer's author. Since zipimport is part of the standard library, I would *guess* that they follow pep 302. Interesting to test it.

> Basically, if you still to reading module.__file__ for modules which
> come from a .py file, you should be absolutely fine. But to practice
> defensive programming, something like:
>
> try:
>     path = module.__file__
> except AttributeError:
>     print('handle the case where the module doesn't exist on disk')
> else:
>     print('handle the case where the module does exist on disk')
>
>
> might be appropriate.
>
>
>
> --
> Steve
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor

From eryksun at gmail.com  Fri Jan 12 18:25:11 2018
From: eryksun at gmail.com (eryk sun)
Date: Fri, 12 Jan 2018 23:25:11 +0000
Subject: [Tutor] When is and isn't "__file__" set?
In-Reply-To: <HE1PR1001MB13088EBE72CAFA8FCA4F6ED083170@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB13088EBE72CAFA8FCA4F6ED083170@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <CACL+1avbxBapGjZCfobEhnw0rON3PiNv3Mn7SPsvPAR3h4_oOg@mail.gmail.com>

On Fri, Jan 12, 2018 at 5:22 PM, Albert-Jan Roskam
<sjeik_appie at hotmail.com> wrote:
> On Jan 11, 2018 03:47, Steven D'Aprano <steve at pearwood.info> wrote:
>>
>> Modules which are loaded from a .dll or .so binary file also should have
>> __file__ set.
>
> And .pyd? I would hope so

A .pyd is a Windows DLL (i.e. PE/COFF shared library). The .pyd type
is associated with the "Python.Extension" program identifier, which
sets a custom descriptive name and icon in Explorer. Sometimes a
Python extension module uses the .dll file extension instead of .pyd.
For example, from PyWin32:

    >>> print(pywintypes.__file__)
    C:\Program Files\Python36\pywintypes36.dll
    >>> print(pythoncom.__file__)
    C:\Program Files\Python36\pythoncom36.dll

From steve at pearwood.info  Fri Jan 12 19:27:47 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Sat, 13 Jan 2018 11:27:47 +1100
Subject: [Tutor] When is and isn't "__file__" set?
In-Reply-To: <HE1PR1001MB13088EBE72CAFA8FCA4F6ED083170@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB13088EBE72CAFA8FCA4F6ED083170@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <20180113002747.GV6667@ando.pearwood.info>

On Fri, Jan 12, 2018 at 05:22:05PM +0000, Albert-Jan Roskam wrote:
> 
> On Jan 11, 2018 03:47, Steven D'Aprano <steve at pearwood.info> wrote:

[...]
> > Modules which are loaded from a .py or .pyc file on disk should always
> > have __file__ set. If they don't, that's a bug in the interpreter.
> >
> > Modules which are loaded from a .dll or .so binary file also should have
> > __file__ set.
> 
> And .pyd? I would hope so

The full list of file extensions handled by Python is version and 
platform dependent. There are also .pyo files, on Windows there is at 
least one other, .pyw, and there may be more on other platforms.

I don't know the full list.


> > Modules that you create on the fly like this:
> >
> > py> from types import ModuleType
> > py> module = ModuleType('module')
> > py> module.__file__
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > AttributeError: module 'module' has no attribute '__file__'
> 
> Fascinating. Will this allow you to write a BLOB of the marshalled 
> module object to a database? Do you happen to know a use case of this?

Apparently you cannot either marshal or pickle a module:

py> import pickle, marshal
py> from types import ModuleType
py> x = ModuleType('x')
py> pickle.dumps(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <class 'module'>: attribute lookup 
module on builtins failed
py> marshal.dumps(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: unmarshallable object



-- 
Steve

From wpmartin at gmail.com  Sat Jan 13 00:15:43 2018
From: wpmartin at gmail.com (Pat Martin)
Date: Fri, 12 Jan 2018 21:15:43 -0800
Subject: [Tutor] Graphical/web program
Message-ID: <CAOFYKhKcG=OwU7XNgPnDzRqjMx=dHJA1p0BexWQwP_E_P3-6bg@mail.gmail.com>

Hello,

I have recently written a program to add switches and hosts to my ssh
config file, I use argparse for some switches like user name and such and
it has been working pretty well.

I was thinking of turning this into a web app (one that is just run on my
local machine)  something like have a form with text box, checkbox and
radio buttons for the options/flags.

My question is, is something like that practical? Will I be able to write
to a local file (home/user/.ssh/config) with say a flask app? I don't know
flask but am willing to learn it and thought this might be a good program
for it.

Thanks in advance for any thoughts or ideas.

From alan.gauld at yahoo.co.uk  Sat Jan 13 04:02:53 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Sat, 13 Jan 2018 09:02:53 +0000
Subject: [Tutor] Graphical/web program
In-Reply-To: <CAOFYKhKcG=OwU7XNgPnDzRqjMx=dHJA1p0BexWQwP_E_P3-6bg@mail.gmail.com>
References: <CAOFYKhKcG=OwU7XNgPnDzRqjMx=dHJA1p0BexWQwP_E_P3-6bg@mail.gmail.com>
Message-ID: <p3chrv$3pc$1@blaine.gmane.org>

On 13/01/18 05:15, Pat Martin wrote:

> I was thinking of turning this into a web app (one that is just run on my
> local machine)  something like have a form with text box, checkbox and
> radio buttons for the options/flags.
> 
> My question is, is something like that practical? Will I be able to write
> to a local file (home/user/.ssh/config) with say a flask app? I don't know
> flask but am willing to learn it and thought this might be a good program
> for it.

It is definitely doable and as a learning experience on web apps its a
good starter project. You will need to run a web server on your machine,
but Flask provides a basic server that will suffice. It can write to a
file or a database.

Looking beyond the web aspect, if its just for your local machine use
then a desktop GUI might be a more suitable mechanism than a web page,
it would be lighter weight and offer more design features. But if you
want to learn Flask then this is a good starting point.


-- 
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



From mamathanaik64 at gmail.com  Sat Jan 13 07:05:13 2018
From: mamathanaik64 at gmail.com (mamatha n)
Date: Sat, 13 Jan 2018 17:35:13 +0530
Subject: [Tutor] python gui Tkinter
Message-ID: <CAGZNpHr3GE+KY_5fTjv=r_yfWBZ2coAKhsnKx=dN65p71sk1Ew@mail.gmail.com>

please any one give me the code for
username (entryfld)-----
pwrd (entryfld)----
login(button),    changepwrd(button)
 virtualkeyboard-----user has to be use dis keyboard
 once click on login button regester page open
register page content 1.emply name(entryfld)
                         2.emply id(entryfld),
 3.mbil no(entryfld), 4. RFID(entryfld) ,   5.back (button),
6.clearbtn(button),  7. ok(button)

next user want to clear employee details click on clear button1. employee
id text feild shd open click on ok employee id should be removed




please i need this code immediatly any one tell me please.

From breamoreboy at gmail.com  Sat Jan 13 09:14:34 2018
From: breamoreboy at gmail.com (Mark Lawrence)
Date: Sat, 13 Jan 2018 14:14:34 +0000
Subject: [Tutor] python gui Tkinter
In-Reply-To: <CAGZNpHr3GE+KY_5fTjv=r_yfWBZ2coAKhsnKx=dN65p71sk1Ew@mail.gmail.com>
References: <CAGZNpHr3GE+KY_5fTjv=r_yfWBZ2coAKhsnKx=dN65p71sk1Ew@mail.gmail.com>
Message-ID: <p3d44e$l2e$1@blaine.gmane.org>

On 13/01/18 12:05, mamatha n wrote:
> please any one give me the code for
> username (entryfld)-----
> pwrd (entryfld)----
> login(button),    changepwrd(button)
>   virtualkeyboard-----user has to be use dis keyboard
>   once click on login button regester page open
> register page content 1.emply name(entryfld)
>                           2.emply id(entryfld),
>   3.mbil no(entryfld), 4. RFID(entryfld) ,   5.back (button),
> 6.clearbtn(button),  7. ok(button)
> 
> next user want to clear employee details click on clear button1. employee
> id text feild shd open click on ok employee id should be removed
> 
> please i need this code immediatly any one tell me please.

Terribly sorry but that's not how this list works.  You provide the code 
and we help you fix any problems.  Anybody giving you the code is doing 
you a grave disservice in the long term as you will not learn.

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence


From alan.gauld at yahoo.co.uk  Sat Jan 13 09:18:50 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Sat, 13 Jan 2018 14:18:50 +0000
Subject: [Tutor] python gui Tkinter
In-Reply-To: <CAGZNpHr3GE+KY_5fTjv=r_yfWBZ2coAKhsnKx=dN65p71sk1Ew@mail.gmail.com>
References: <CAGZNpHr3GE+KY_5fTjv=r_yfWBZ2coAKhsnKx=dN65p71sk1Ew@mail.gmail.com>
Message-ID: <p3d4cc$gs6$1@blaine.gmane.org>

On 13/01/18 12:05, mamatha n wrote:
> please any one give me the code for

We don't write code for you (unless you want to pay
one of us as a contractor) But we can point you at
some examples:

> username (entryfld)-----
> pwrd (entryfld)----
> login(button),    changepwrd(button)

So far very basic Tkinter, any tutorial would cover it.
You could try mine at:

http://www.alan-g.me.uk/tutgui.htm


>  virtualkeyboard-----user has to be use dis keyboard

Thisis not a TKinter function its an OS feature. Tkinter will work with
whichever keyboard is present.

If you want to create your own vuirtual keyboard
using Tkinter then thats possible but quite a lot
of work. (More tedious than technically difficult
though)

>  once click on login button regester page open

GUIs don't usually have the content of pages - unless you want a tabbed
notebook metaphor. If so look at the ttk module

But usually I'd expect a pop up dialog box to appear,
or for the login window to disappear ad a new main
window to appear. You need to clarify how it works.

> register page content 1.emply name(entryfld)
>                          2.emply id(entryfld),
>  3.mbil no(entryfld), 4. RFID(entryfld) ,   5.back (button),
> 6.clearbtn(button),  7. ok(button)

Since all you need are entry fields and buttons you should have no
problem putting it together with the help of any Tkinter tutorial.
You probably want to use the grid layout manager for this.

> please i need this code immediatly any one tell me please.

You will need to write it, if you get stuck feel free to ask,
but its all very basic and covered in any tutorial.

-- 
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



From giacomo.boffi at gmail.com  Sat Jan 13 18:35:34 2018
From: giacomo.boffi at gmail.com (giacomo.boffi at gmail.com)
Date: Sun, 14 Jan 2018 00:35:34 +0100
Subject: [Tutor] Installing python and numpy on the Mac (OSX)
References: <5507B0E1-729B-4D70-AD18-7CAA724204FE@gmail.com>
Message-ID: <87zi5h9vsp.fsf@debian.i-did-not-set--mail-host-address--so-tickle-me>

Peter Hodges <designx1000 at gmail.com> writes:

> Hi. I downloaded Python 3.6 from the python site, then followed online
> directions for pip to install numpy (in users? ?user was in the
> example).
> When I start IDLE in the Python 3.6 in Applications and then type
> import numpy as np I get the following:
> import numpy as np
> Traceback (most recent call last):
>   File "<pyshell#0>", line 1, in <module>
>     import numpy as np
> ModuleNotFoundError: No module named ?numpy'
>
> Does this mean I need to set the $PATH with some new pathname?

no

> Or move the numpy directory into the python 3.6 directory?

no

> Or?

----
first, (optional but I'd reccommend to) disinstall numpy using the same
pip script that you used to install it, something like

$ pip uninstall numpy # possibly using sudo
----
next, you must be sure that Python 3.6 has pip, either

$ /path/to/python3.6 -m ensurepip --user

or (if you are installing in a virtual environment)

$ /path/to/python3.6 -m ensurepip

the above is going to install pip if it is not already present in the
environment of Python 3.6 --- please see
    https://docs.python.org/3/library/ensurepip.html
for the gory details
----
finally, install numpy for 3.6

$ /path/to/python3.6 -m pip install --user numpy
----

The command "/path/to/python3.6 -m modulename ..." ensures that the
module and the Python version are matching one with the other.


From steve at pearwood.info  Sat Jan 13 20:09:00 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Sun, 14 Jan 2018 12:09:00 +1100
Subject: [Tutor] question about metaclasses
In-Reply-To: <p35lvd$jp0$1@blaine.gmane.org>
References: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
 <p35lvd$jp0$1@blaine.gmane.org>
Message-ID: <20180114010859.GC1982@ando.pearwood.info>

On Wed, Jan 10, 2018 at 07:29:58PM +0100, Peter Otten wrote:

[...]
>             elif not isinstance(obj, property):
>                 attrs[attr] = property(lambda self, obj=obj: obj)

> PS: If you don't remember why the obj=obj is necessary:
> Python uses late binding; without that trick all lambda functions would 
> return the value bound to the obj name when the for loop has completed.

This is true, but I think your terminology is misleading. For default 
values to function parameters, Python uses *early* binding, not late 
binding: the default value is computed once at the time the function is 
created, not each time it is needed.

So in this case, each of those property objects use a function that sets 
the default value of obj to the current value of obj at the time that 
the property is created.

Without the obj=obj parameter, Python creates a *closure*. A closure is 
a computer-science term for something like a snap shot of the 
environment where the function was created.

If we had written this instead:

    attrs[attr] = property(lambda self: obj)

the name "obj" doesn't refer to a local variable of the lambda function. 
Nor does it refer to a global variable, or a builtin function. It refers 
to a "non-local variable": it belongs to the function that surrounds the 
lambda function, not the lambda itself.

And so Python would create a *closure* for the lambda function so that 
when it eventually gets called, it knows where to find the value of obj.

And *that* process, of looking up the value of obj from a closure, uses 
late binding: all the lambda functions will refer to the same 
environment, which means they will also see the same value for obj.

Namely the last value obj received when the outer function (the one 
that the closure refers back to) completed.

Here's another example to show the difference. Rather than use lambda, 
I'm going to use regular "def" to prove that this has nothing to do with 
lambda itself, the rules apply every time you create a function.

Start with the closure version:

# --- cut here %< ---

def factory_closure():
    # Create many new functions, each of which refer to i in its
    # enclosing scope.
    functions = []
    for i in range(5):
        def f():
            return i  # << this i is a NONLOCAL variable
        functions.append(f)
    return functions

functions = factory_closure()

# All the closures refer to the same thing.
for f in functions:
    print(f.__closure__)

# And the functions all see the same value for i
print([f() for f in functions])

# --- cut here %< ---


And here is a version which avoids the closure issue by using the 
function parameter default value trick:


# --- cut here %< ---

def factory_no_closure():
    # Create many new functions, each of which refer to i using
    # a parameter default value.
    functions = []
    for i in range(5):
        def f(i=i):
            return i  # << this i is a LOCAL variable
        functions.append(f)
    return functions

functions = factory_no_closure()

# None of the functions need a closure.
for g in functions:
    print(g.__closure__)

# And the functions all see different values for i
print([g() for g in functions])

# --- cut here %< ---


In practice, this is generally only an issue when single invocation of a 
factory function creates two or more functions at once, and that 
generally means inside a loop:


def factory():
    for i in something:
        create function referring to i


If your factory only returns one function at a time, like this:


def factory(i):
    create function referring to i

for n in something:
    factory(n)


then each function still uses a closure, but they are *different* 
closures because each one is created on a different invocation of the 
factory. That's another way to avoid this "early/late binding" problem.


-- 
Steve

From __peter__ at web.de  Mon Jan 15 09:40:41 2018
From: __peter__ at web.de (Peter Otten)
Date: Mon, 15 Jan 2018 15:40:41 +0100
Subject: [Tutor] question about metaclasses
References: <HE1PR1001MB13083FB9F9855816CD77155C83110@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
 <p35lvd$jp0$1@blaine.gmane.org> <20180114010859.GC1982@ando.pearwood.info>
Message-ID: <p3iede$bd8$1@blaine.gmane.org>

Steven D'Aprano wrote:

> On Wed, Jan 10, 2018 at 07:29:58PM +0100, Peter Otten wrote:
> 
> [...]
>>             elif not isinstance(obj, property):
>>                 attrs[attr] = property(lambda self, obj=obj: obj)
> 
>> PS: If you don't remember why the obj=obj is necessary:
>> Python uses late binding; without that trick all lambda functions would
>> return the value bound to the obj name when the for loop has completed.
> 
> This is true, but I think your terminology is misleading. For default
> values to function parameters, Python uses *early* binding, not late
> binding: the default value is computed once at the time the function is
> created, not each time it is needed.

You are right; I should have stated clearly where I was talking about the 
closure.


From chris_roysmith at internode.on.net  Mon Jan 15 23:37:17 2018
From: chris_roysmith at internode.on.net (Chris Roy-Smith)
Date: Tue, 16 Jan 2018 15:37:17 +1100
Subject: [Tutor] trouble using tkinter CheckButton
Message-ID: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net>

Hi,

I'm a relative newcomer to object oriented programming.

Operating system Linux (ubuntu 17.10)

Python version 3.6

With the code below, when I click on the "list set & unset" button I get 
the following error. This code is my attempt at debugging a bigger 
program. I have broken things down to what I think is as simple as I can 
get.

Thank you for looking at this,

Regards, Chris Roy-Smith


Error message:

=====================

chris at chris-X451MA:~/Scripts/python3/dvms$ ./debugString.py
Exception in Tkinter callback
Traceback (most recent call last):
 ? File "/usr/lib/python3.6/tkinter/__init__.py", line 1702, in __call__
 ??? return self.func(*args)
 ? File "./debugString.py", line 26, in <lambda>
 ??? Button(cmember, text='list set & unset',command= lambda lines = x : 
SetFin(lines) ).grid(row=x, column=2)
 ? File "./debugString.py", line 7, in SetFin
 ??? SetStatus[x] = var.get(x)
AttributeError: 'list' object has no attribute 'get'

============================================

#!/usr/bin/python3
from tkinter import *

def SetFin(lines):
 ??? SetStatus=[" " for i in range(lines)]
 ??? for x in range(lines):
 ??????? SetStatus[x] = var.get(x)
 ??????? print (SetStatus(x))

master = Tk()


NameList=[(1, 'Vivian', 'Blackwell'), (2, 'Peter ', 'Bromell'), (3, 
'Nev', 'Casey'), (4, 'Claude', 'Chatwin'), (5, 'John ', 'Dennison'), (6, 
'Nicolene', 'Fairbrass'), (7, 'Paul', 'Fairbrass')] #in real situation 
this comes from a database and is of variable length
cmember=Toplevel(master)
x=0
y=0
var=[IntVar() for x in range(8)]
for line in NameList:
 ??? for field in line:
 ??????? Label(cmember, text=field).grid(row=x, column=y)
 ??????? y+=1
 ??? #make checkbox
 ??? cb=Checkbutton(cmember, text='set', variable=var[x]).grid(row=x, 
column=y)
 ??? y=0
 ??? x+=1
Button(cmember, text='list set & unset',command= lambda lines = x : 
SetFin(lines) ).grid(row=x, column=2)
Button(cmember, text='exit', command=cmember.destroy).grid(row=x, column=4)

mainloop()


From alan.gauld at yahoo.co.uk  Tue Jan 16 06:35:59 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Tue, 16 Jan 2018 11:35:59 +0000
Subject: [Tutor] trouble using tkinter CheckButton
In-Reply-To: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net>
References: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net>
Message-ID: <d16048bd-d815-384f-742a-ec48fc078b00@yahoo.co.uk>

On 16/01/18 04:37, Chris Roy-Smith wrote:

>  ? File "./debugString.py", line 7, in SetFin
>  ??? SetStatus[x] = var.get(x)
> AttributeError: 'list' object has no attribute 'get'

> var=[IntVar() for x in range(8)]

Here you create a list of IntVar objects.
The list has no get() method - just as the error message says.
You need to access the individual IntVar for your widget.

I suspect you want

  SetStatus[x] = var[x].get()

-- 
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


From chris_roysmith at internode.on.net  Tue Jan 16 14:47:55 2018
From: chris_roysmith at internode.on.net (Chris Roy-Smith)
Date: Wed, 17 Jan 2018 06:47:55 +1100
Subject: [Tutor] trouble using tkinter CheckButton
In-Reply-To: <d16048bd-d815-384f-742a-ec48fc078b00@yahoo.co.uk>
References: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net>
 <d16048bd-d815-384f-742a-ec48fc078b00@yahoo.co.uk>
Message-ID: <ed0c116d-b5be-5340-5989-12d9ec7f0f28@internode.on.net>

On 16/01/18 22:35, Alan Gauld via Tutor wrote:
> On 16/01/18 04:37, Chris Roy-Smith wrote:
>
>>   ? File "./debugString.py", line 7, in SetFin
>>   ??? SetStatus[x] = var.get(x)
>> AttributeError: 'list' object has no attribute 'get'
>> var=[IntVar() for x in range(8)]
> Here you create a list of IntVar objects.
> The list has no get() method - just as the error message says.
> You need to access the individual IntVar for your widget.
>
> I suspect you want
>
>    SetStatus[x] = var[x].get()
>
Yes, Thank you, that was the problem. other problems in my code, after 
correcting the get() were easy to sort out.

Regards, Chris Roy-Smith


From sjeik_appie at hotmail.com  Thu Jan 18 12:31:24 2018
From: sjeik_appie at hotmail.com (Albert-Jan Roskam)
Date: Thu, 18 Jan 2018 17:31:24 +0000
Subject: [Tutor] question about metaclasses
Message-ID: <HE1PR1001MB1308EE696190CF916EFAE9F983E80@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>


On Jan 10, 2018 18:57, Steven D'Aprano <steve at pearwood.info> wrote:
>
> On Wed, Jan 10, 2018 at 04:08:04PM +0000, Albert-Jan Roskam wrote:
>
> > In another thread on this list I was reminded of
> > types.SimpleNamespace. This is nice, but I wanted to create a bag
> > class with constants that are read-only.
>
> If you expect to specify the names of the constants ahead of time, the
> best solution is (I think) a namedtuple.

Aaah *slaps forehead*, for some reason I didn't think about this, though I use namedtuples quite often. Using a metaclass for the very first time was great fun though :-)

> from collections import namedtuple
> Bag = namedtuple('Bag', 'yes no dunno')
> a = Bag(yes=1, no=0, dunno=42)
> b = Bag(yes='okay', no='no way', dunno='not a clue')
>
> ought to do what you want.
>
> Don't make the mistake of doing this:
>
> from collections import namedtuple
> a = namedtuple('Bag', 'yes no dunno')(yes=1, no=0, dunno=42)
> b = namedtuple('Bag', 'yes no dunno')(yes='okay', no='no way', dunno='not a clue')

But if I do:
Bag = namedtuple('Bag', 'yes no dunno')
... and then I create hundreds of Bag instances, this doesn't have a large memory footprint, right? (Because of __slots__) Or is a regular tuple still (much) less wasteful?

> because that's quite wasteful of memory: each of a and b belong to a
> separate hidden class, and classes are rather largish objects.
>
>
> If you expect to be able to add new items on the fly, but have them
> read-only once set, that's a different story.
>
>
> --
> Steve
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor

From sjeik_appie at hotmail.com  Thu Jan 18 12:14:43 2018
From: sjeik_appie at hotmail.com (Albert-Jan Roskam)
Date: Thu, 18 Jan 2018 17:14:43 +0000
Subject: [Tutor] question about metaclasses
Message-ID: <HE1PR1001MB130822EB7D779B97B63CAFC583E80@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>


On Jan 10, 2018 19:32, Peter Otten <__peter__ at web.de> wrote:
>
> Albert-Jan Roskam wrote:
>
> > Why does following the line (in #3)
>
> > # 3-------------------------------------------------
> > class Meta(type):
> >     def __new__(cls, name, bases, attrs):
> >         for attr, obj in attrs.items():
> >             if attr.startswith('_'):
> >                 continue
> >             elif not isinstance(obj, property):
> >                 import pdb;pdb.set_trace()
> >                 #setattr(cls, attr, property(lambda self: obj))  #
> >                 #incorrect!
> >                 raise ValueError("Only properties allowed")
> >         return super().__new__(cls, name, bases, attrs)
> >
> > class MyReadOnlyConst(metaclass=Meta):
> >     __metaclass__ = Meta
> >     YES = property(lambda self: 1)
> >     NO = property(lambda self: 0)
> >     DUNNO = property(lambda self: 42)
> >     THROWS_ERROR = 666
> >
> >
> > c2 = MyReadOnlyConst()
> > print(c2.THROWS_ERROR)
> > #c2.THROWS_ERROR = 777
> > #print(c2.THROWS_ERROR)
>
> > not convert the normal attribute int > a property?
> >
> > setattr(cls, attr, property(lambda self: obj))  # incorrect!
>
> cls is Meta itself, not MyReadOnlyConst (which is an instance of Meta).
> When the code in Meta.__new__() executes MyReadOnlyConst does not yet exist,
> but future attributes are already there, in the form of the attrs dict.
> Thus to convert the integer value into a read-only property you can
> manipulate that dict (or the return value of super().__new__()):
>
> class Meta(type):
>     def __new__(cls, name, bases, attrs):
>         for attr, obj in attrs.items():
>             if attr.startswith('_'):
>                 continue
>             elif not isinstance(obj, property):
>                 attrs[attr] = property(lambda self, obj=obj: obj)
>
>         return super().__new__(cls, name, bases, attrs)
>
> class MyReadOnlyConst(metaclass=Meta):
>     YES = property(lambda self: 1)
>     NO = property(lambda self: 0)
>     DUNNO = property(lambda self: 42)
>     THROWS_ERROR = 666
>
> c = MyReadOnlyConst()
> try:
>     c.THROWS_ERROR = 42
> except AttributeError:
>     pass
> else:
>     assert False
> assert c.THROWS_ERROR == 666

Thanks all for your replies!

Awesome, this is exactly what I want. I think I'll also override __setattr__  so that each newly added attribute is automatically converted into a property
Is a metaclass the best/preferred/only way of doing this? Or is a class decorator an alternative route?

Is the following analogy for doing stuff when a class is created ('born') correct?
Metaclass --> prenatal surgery
__new__ --> perinatal surgery
Class decorator --> postnatal surgery

> PS: If you don't remember why the obj=obj is necessary:
> Python uses late binding; without that trick all lambda functions would
> return the value bound to the obj name when the for loop has completed.
> A simplified example:
>
> >>> fs = [lambda: x for x in "abc"]
> >>> fs[0](), fs[1](), fs[2]()
> ('c', 'c', 'c')
> >>> fs = [lambda x=x: x for x in "abc"]
> >>> fs[0](), fs[1](), fs[2]()
> ('a', 'b', 'c')
>
>
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor

From devanshr at gmail.com  Thu Jan 18 15:51:18 2018
From: devanshr at gmail.com (Devansh Rastogi)
Date: Thu, 18 Jan 2018 21:51:18 +0100
Subject: [Tutor] Writing to a file
Message-ID: <CAFANrQLo4f-jaHY_uZ7aHjQ94AirH9dQ87q5DvfZgYEHPXc0nw@mail.gmail.com>

Hello,

I'm new to python and programming as such and as an exercise for I/O am
writing a small program that reads data from a .txt file, and analyzes the
text, ie, number of words/characters, avg. length of words, and frequency
of words and characters.

Once the text has been analyzed, the results are then written to a file.

After reading the documentation, and a bit about json, I'm afraid, I've
managed to completely confuse myself.

When do you actually use json or pickle, I understand that with data
written to .json files can be used by programs written in other languages,
and pickle is for python specific objects. So are there specific objects
for which .json is used or pickle is preferred? And if I'm just using
write() then I'm just writing to a file, and has nothing to do with json or
pickle? Also is it possible to append data to a already existing file? So
far it seems that everytime I'm calling my write function, its re-writing
the whole file with just the last variable called.
Ive added my code below, and am currently using json.dump() as  I would
like to send the file to a friend who is writing a similar program but with
a gui, and it would be nice if his program can read the data without
problems.

I realize these are pretty basic questions and am missing some basic
fundamentals. I'd be grateful if someone could point me in the right
direction, any tips would be highly appreciated.

from collections import Counter
import json

class Files:
    def __init__(self, filename):
        with open(filename, 'r', encoding='utf-16') as file_input:
            self.file_input_string = file_input.read().replace('\n', ' ')

    def num_of_words(self):
        """ Return number of words in the file"""
        return str(len(self.file_input_string.split()))

    def num_of_keystrokes(self):
        """ Total number of keystrokes
        # abcde.. = 1 stroke
        # ABCDE.. = 2 strokes
        # '.,-/;[]=\ = 1 stroke
        # !@#$%^&*()_+|}{":?>< = 2 strokes """

        lowercase_letters = sum(1 for c in self.file_input_string if
c.islower())
        uppercase_letters = sum(2 for c in self.file_input_string if
c.isupper())
        one_keystroke_punc = ".,-=[]\;'/ "  # space included
        puncuation_one = sum(1 for c in self.file_input_string if c in
one_keystroke_punc)
        two_keystroke_punc = '!@#$%^&*()_+|}{":?><'
        puncuation_two = sum(2 for c in self.file_input_string if c in
two_keystroke_punc)

        return str(lowercase_letters + uppercase_letters +
puncuation_one + puncuation_two)

    def num_of_char(self):
        """ Return number of characters in the string without spaces"""
        return str(len(self.file_input_string) -
self.file_input_string.count(" "))

    def frequency_of_char(self):
        """ Frequency of characters in the file """
        count = Counter(self.file_input_string)
        dict_count = dict(count)
        print("{:<12} {:<10}".format('Character', 'Frequency'))
        for k, v in dict_count.items():
            print("{:<12} {:<10}".format(k, v))

    def frequency_of_words(self):
        """ Frequency of words in the file"""
        # word_count = Counter()
        # for word in self.file_input_string.replace(' ', '\n'): ###
macht wider char. sollte fuer line funktioniern
        #     word_count.update(word)
        # print("{:<15} {:15}".format("Word", "Frequency"))
        # for k, v in word_count.items():
        #     print("{:<15} {:<15}".format(k, v))

        word_list = self.file_input_string.split()
        word_frequecy = [word_list.count(w) for w in word_list]  ##
funktioniert mit string.count!!
        word_frequecy_dict = dict(zip(word_list, word_frequecy))
        print("{:<15} {:15}".format("Word", "Frequency"))
        for k, v in word_frequecy_dict.items():
            print("{:<15} {:<15}".format(k, v))

    def average_len_of_words(self):
        """ calculate the averge length of the words"""
        word_list = self.file_input_string.split()
        average = sum(len(word) for word in word_list) / len(word_list)
        return str(average)

    def write_to_file(self, data):
        """ collect all data for Morgen_Kinder.txt in a file"""
        with open('data.json', 'w') as f:
            json.dump(data, f, sort_keys=True, indent=4)

#test
x = Files('Morgen_Kinder.txt')
a = Files.num_of_char(x)
Files.write_to_file(x,a)
print(a)
b = Files.num_of_words(x)
Files.write_to_file(x,b)
print(b)
c = Files.frequency_of_char(x)
Files.write_to_file(x,c)
d = Files.frequency_of_words(x)
Files.write_to_file(x,d)
e = Files.average_len_of_words(x)
Files.write_to_file(x,e)
print(e)
g = Files.num_of_keystrokes(x)
Files.write_to_file(x,g)
print(g)

From alan.gauld at yahoo.co.uk  Thu Jan 18 18:11:05 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Thu, 18 Jan 2018 23:11:05 +0000
Subject: [Tutor] Writing to a file
In-Reply-To: <CAFANrQLo4f-jaHY_uZ7aHjQ94AirH9dQ87q5DvfZgYEHPXc0nw@mail.gmail.com>
References: <CAFANrQLo4f-jaHY_uZ7aHjQ94AirH9dQ87q5DvfZgYEHPXc0nw@mail.gmail.com>
Message-ID: <p3r9ea$45f$1@blaine.gmane.org>

On 18/01/18 20:51, Devansh Rastogi wrote:

> When do you actually use json or pickle, I understand that with data
> written to .json files can be used by programs written in other languages,
> and pickle is for python specific objects.

Yes, that's correct.

>  So are there specific objects
> for which .json is used or pickle is preferred? 

No, its more about whether you are just looking to persist
an objects state (pickle) or share the data with another
program(json).

> write() then I'm just writing to a file, 

Correct. write() just send a string to a file.

> Also is it possible to append data to a already existing file? 

Yes open in with mode 'a' instead of 'w'
If no file exists it creates a new one, if one exists
it appends to the end.

> far it seems that everytime I'm calling my write function, its re-writing
> the whole file with just the last variable called.

Presumably because you open it with 'w' as the mode?

> Ive added my code below, and am currently using json.dump() as  I would
> like to send the file to a friend who is writing a similar program but with
> a gui, and it would be nice if his program can read the data without
> problems.

If the GUI is in Python he can use pickle but
otherwise you need json (or some other portable
format like csv or xml.


> I realize these are pretty basic questions and am missing some basic
> fundamentals. I'd be grateful if someone could point me in the right
> direction, any tips would be highly appreciated.

You could try reading the Handling Files topic in my tutorial

http://www.alan-g.me.uk/l2p2/tutfiles.htm

> from collections import Counter
> import json
> 
> class Files:
>     def __init__(self, filename):
>         with open(filename, 'r', encoding='utf-16') as file_input:
>             self.file_input_string = file_input.read().replace('\n', ' ')

Any particular reason you use utf-16 instead of the much more common
utf-8? Just curious...

>     def num_of_words(self):
>         """ Return number of words in the file"""
>         return str(len(self.file_input_string.split()))

Actually you return the string representation of the number not the
actual number.

>     def num_of_keystrokes(self):
>         """ Total number of keystrokes
>         # abcde.. = 1 stroke
>         # ABCDE.. = 2 strokes
>         # '.,-/;[]=\ = 1 stroke
>         # !@#$%^&*()_+|}{":?>< = 2 strokes """
> 
>         lowercase_letters = sum(1 for c in self.file_input_string if
> c.islower())
>         uppercase_letters = sum(2 for c in self.file_input_string if
> c.isupper())
>         one_keystroke_punc = ".,-=[]\;'/ "  # space included
>         puncuation_one = sum(1 for c in self.file_input_string if c in
> one_keystroke_punc)
>         two_keystroke_punc = '!@#$%^&*()_+|}{":?><'
>         puncuation_two = sum(2 for c in self.file_input_string if c in
> two_keystroke_punc)
> 
>         return str(lowercase_letters + uppercase_letters +
> puncuation_one + puncuation_two)

Again you are returning the string not the number.

>     def num_of_char(self):
>         """ Return number of characters in the string without spaces"""
>         return str(len(self.file_input_string) -
> self.file_input_string.count(" "))

And again...

>     def frequency_of_char(self):
>         """ Frequency of characters in the file """
>         count = Counter(self.file_input_string)
>         dict_count = dict(count)
>         print("{:<12} {:<10}".format('Character', 'Frequency'))
>         for k, v in dict_count.items():
>             print("{:<12} {:<10}".format(k, v))

While this prints the valuers you don;t store them
since dict_count is a local variable that gets thrown
away. It might be better to store it as a classs attribute?

>     def frequency_of_words(self):
>         """ Frequency of words in the file"""
>         # word_count = Counter()
>         # for word in self.file_input_string.replace(' ', '\n'): ###
> macht wider char. sollte fuer line funktioniern
>         #     word_count.update(word)
>         # print("{:<15} {:15}".format("Word", "Frequency"))
>         # for k, v in word_count.items():
>         #     print("{:<15} {:<15}".format(k, v))
> 
>         word_list = self.file_input_string.split()
>         word_frequecy = [word_list.count(w) for w in word_list]  ##
> funktioniert mit string.count!!
>         word_frequecy_dict = dict(zip(word_list, word_frequecy))
>         print("{:<15} {:15}".format("Word", "Frequency"))
>         for k, v in word_frequecy_dict.items():
>             print("{:<15} {:<15}".format(k, v))
> 
>     def average_len_of_words(self):
>         """ calculate the averge length of the words"""
>         word_list = self.file_input_string.split()
>         average = sum(len(word) for word in word_list) / len(word_list)
>         return str(average)

Once again you return the string rather than the value.

>     def write_to_file(self, data):
>         """ collect all data for Morgen_Kinder.txt in a file"""
>         with open('data.json', 'w') as f:
>             json.dump(data, f, sort_keys=True, indent=4)

Here you create the file with 'w' mode so it always
overwrites the previous copy.


> 
> #test
> x = Files('Morgen_Kinder.txt')
> a = Files.num_of_char(x)
> Files.write_to_file(x,a)
> print(a)
> b = Files.num_of_words(x)
> Files.write_to_file(x,b)
> print(b)

Note that here you are writing strings to the files
albeit using JSON. But there really is no need for
JSON here, the format is simply strings.

The pooint of complex formats like pickle and JSON
is to save complex data structures all at once. You
are getting the worst of both worlds. You are doing
all the work to break down the complexity to single
strings and then writing them out with the complexity
of JSON.

-- 
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



From steve at pearwood.info  Thu Jan 18 22:52:08 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Fri, 19 Jan 2018 14:52:08 +1100
Subject: [Tutor] question about metaclasses
In-Reply-To: <HE1PR1001MB1308EE696190CF916EFAE9F983E80@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB1308EE696190CF916EFAE9F983E80@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <20180119035207.GI22500@ando.pearwood.info>

On Thu, Jan 18, 2018 at 05:31:24PM +0000, Albert-Jan Roskam wrote:

> > Don't make the mistake of doing this:
> >
> > from collections import namedtuple
> > a = namedtuple('Bag', 'yes no dunno')(yes=1, no=0, dunno=42)
> > b = namedtuple('Bag', 'yes no dunno')(yes='okay', no='no way', dunno='not a clue')
> 
> But if I do:
> Bag = namedtuple('Bag', 'yes no dunno')
> ... and then I create hundreds of Bag instances, this doesn't have a 
> large memory footprint, right? (Because of __slots__) Or is a regular 
> tuple still (much) less wasteful?

Correct.

namedtuple instances are *nearly* as compact as regular tuples. Making 
many instances of the one named tuple class is efficient; making many 
named tuple classes, with one instance each, is slow and wasteful of 
memory.



-- 
Steve

From renukeshnk15 at gmail.com  Fri Jan 19 01:54:56 2018
From: renukeshnk15 at gmail.com (renukesh nk)
Date: Fri, 19 Jan 2018 12:24:56 +0530
Subject: [Tutor] CSV row and column width automation
In-Reply-To: <CAO2EJjjztAO3m5U=FDDCNy_WA3=UrJpViYxzFx+DpJLji40ctQ@mail.gmail.com>
References: <CAO2EJjjztAO3m5U=FDDCNy_WA3=UrJpViYxzFx+DpJLji40ctQ@mail.gmail.com>
Message-ID: <CAO2EJjjZ3PwCt6vR8xuRBSp3xFe_W2JSgb780Zrg91-No7Ws1A@mail.gmail.com>

Hi,

Does  Web2py framework supports Python version 3.6 ?

On Wed, Jan 3, 2018 at 11:01 AM, renukesh nk <renukeshnk15 at gmail.com> wrote:

> Hi,
>
> Is there any way to automatically set the column and row width in a CSV
> file through python script
>
>
>

From bgailer at gmail.com  Fri Jan 19 12:58:10 2018
From: bgailer at gmail.com (Bob Gailer)
Date: Fri, 19 Jan 2018 12:58:10 -0500
Subject: [Tutor] Writing to a file
In-Reply-To: <CAFANrQLo4f-jaHY_uZ7aHjQ94AirH9dQ87q5DvfZgYEHPXc0nw@mail.gmail.com>
References: <CAFANrQLo4f-jaHY_uZ7aHjQ94AirH9dQ87q5DvfZgYEHPXc0nw@mail.gmail.com>
Message-ID: <CAP1rxO5PVzPW2VZCJxb1GrLxHOuDq6gq+5=eP=Wai-FHDLer4g@mail.gmail.com>

=

On Jan 18, 2018 5:45 PM, "Devansh Rastogi" <devanshr at gmail.com> wrote:
>
> Hello,
>
> I'm new to python and programming as
>
> from collections import Counter
> import json
>
I don't see any value for having a class. All you need are functions and
global variables

> class Files:
>     def __init__(self, filename):

I don't see any need for a function or"with". Just write file_input_string
= open(filename, 'r', encoding='utf-16').read().replace('\n', ' ')


>         with open(filename, 'r', encoding='utf-16') as file_input:
>             self.file_input_string = file_input.read().replace('\n', ' ')
>
You are assuming that all words are separated by blanks which is rarely the
case in natural language.

>     def num_of_words(self):
>         """ Return number of words in the file"""
>         return str(len(self.file_input_string.split()))
>
Several comments on Counting:


Your program is creating lists of ones. Rather than counting them all you
need to do is take the length of each list.. e;g;: lowercase_letters =
len(1 for c in self.file_input_string if c.islower())

However there is a much better way to do the counting: translate the text
using the string translate method into various characters that identify the
class of each letter in the file. Then count the occurrences of each of
those characters. Example: counting Upper Lower, Nunber, and punctuation
Single, Double stroke):

txt=  "THIS is 123 ,./ :*(" # input file text

transtable =
str.maketrans("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
,./:*(",
  "L"*26 + "U"*26 + "N"*10 + "S"*4 + "D"*3) # maps input characters to
corresponding class characters

xlation = txt.translate(transtable) # 'UUUUSLLSNNNSSSSSDDD' # creates
string of class characters

counts =dict(Counter(xlation) # {'S': 7, 'U': 4, 'N': 3, 'L': 2, 'D': 3}

>     def num_of_keystrokes(self):
>         """ Total number of keystrokes
>         # abcde.. = 1 stroke
>         # ABCDE.. = 2 strokes
>         # '.,-/;[]=\ = 1 stroke
>         # !@#$%^&*()_+|}{":?>< = 2 strokes """
>
>         lowercase_letters = sum(1 for c in self.file_input_string if
> c.islower())
>         uppercase_letters = sum(2 for c in self.file_input_string if
> c.isupper())
>         one_keystroke_punc = ".,-=[]\;'/ "  # space included
>         puncuation_one = sum(1 for c in self.file_input_string if c in
> one_keystroke_punc)
>         two_keystroke_punc = '!@#$%^&*()_+|}{":?><'
>         puncuation_two = sum(2 for c in self.file_input_string if c in
> two_keystroke_punc)
>
>         return str(lowercase_letters + uppercase_letters +
> puncuation_one + puncuation_two)
>
>     def num_of_char(self):
>         """ Return number of characters in the string without spaces"""
>         return str(len(self.file_input_string) -
> self.file_input_string.count(" "))
>
>     def frequency_of_char(self):
>         """ Frequency of characters in the file """
>         count = Counter(self.file_input_string)

There is no need to apply dict to count. Counters have an items method.

>         dict_count = dict(count)
>         print("{:<12} {:<10}".format('Character', 'Frequency'))
>         for k, v in dict_count.items():
>             print("{:<12} {:<10}".format(k, v))
>
>     def frequency_of_words(self):
>         """ Frequency of words in the file"""
>         # word_count = Counter()
>         # for word in self.file_input_string.replace(' ', '\n'): ###
> macht wider char. sollte fuer line funktioniern
>         #     word_count.update(word)
>         # print("{:<15} {:15}".format("Word", "Frequency"))
>         # for k, v in word_count.items():
>         #     print("{:<15} {:<15}".format(k, v))
>
>         word_list = self.file_input_string.split()
>         word_frequecy = [word_list.count(w) for w in word_list]  ##
> funktioniert mit string.count!!
>         word_frequecy_dict = dict(zip(word_list, word_frequecy))
>         print("{:<15} {:15}".format("Word", "Frequency"))
>         for k, v in word_frequecy_dict.items():
>             print("{:<15} {:<15}".format(k, v))
>
>     def average_len_of_words(self):
>         """ calculate the averge length of the words"""
>         word_list = self.file_input_string.split()
>         average = sum(len(word) for word in word_list) / len(word_list)
>         return str(average)
>
>     def write_to_file(self, data):
>         """ collect all data for Morgen_Kinder.txt in a file"""
>         with open('data.json', 'w') as f:
>             json.dump(data, f, sort_keys=True, indent=4)
>
> #test
> x = Files('Morgen_Kinder.txt')
> a = Files.num_of_char(x)
> Files.write_to_file(x,a)
> print(a)
> b = Files.num_of_words(x)
> Files.write_to_file(x,b)
> print(b)
> c = Files.frequency_of_char(x)
> Files.write_to_file(x,c)
> d = Files.frequency_of_words(x)
> Files.write_to_file(x,d)
> e = Files.average_len_of_words(x)
> Files.write_to_file(x,e)
> print(e)
> g = Files.num_of_keystrokes(x)
> Files.write_to_file(x,g)
> print(g)
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor

From steve at pearwood.info  Sat Jan 20 02:09:46 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Sat, 20 Jan 2018 18:09:46 +1100
Subject: [Tutor] Writing to a file
In-Reply-To: <CAP1rxO5PVzPW2VZCJxb1GrLxHOuDq6gq+5=eP=Wai-FHDLer4g@mail.gmail.com>
References: <CAFANrQLo4f-jaHY_uZ7aHjQ94AirH9dQ87q5DvfZgYEHPXc0nw@mail.gmail.com>
 <CAP1rxO5PVzPW2VZCJxb1GrLxHOuDq6gq+5=eP=Wai-FHDLer4g@mail.gmail.com>
Message-ID: <20180120070945.GM22500@ando.pearwood.info>

On Fri, Jan 19, 2018 at 12:58:10PM -0500, Bob Gailer wrote:
> =
> 
> On Jan 18, 2018 5:45 PM, "Devansh Rastogi" <devanshr at gmail.com> wrote:
> >
> > Hello,
> >
> > I'm new to python and programming as
> >
> > from collections import Counter
> > import json
> >
> I don't see any value for having a class. All you need are functions and
> global variables

Except for the simplest scripts, global variables are a good way to 
have fragile, buggy, hard to debug code.

If there's ever a chance that you will need to read two or more files at 
the same time, a class is a much better solution than trying to juggle 
global variables.

If I never have to do the:

    old_foo = foo
    calculate_foo()
    print(foo)
    foo = old_foo

dance again, it won't be too soon.


> > class Files:
> >     def __init__(self, filename):
> 
> I don't see any need for a function or"with". Just write file_input_string
> = open(filename, 'r', encoding='utf-16').read().replace('\n', ' ')

Again, that doesn't scale beyond quick and dirty scripts. Best practice 
(even when not strictly needed) is to use

with open(filename) as f:
    do_something_with(f.read())

in order to guarantee that even if an error occurs while reading, the 
file will be closed. Otherwise, you run the risk of running out of file 
handles in a long-running program.


> >         with open(filename, 'r', encoding='utf-16') as file_input:
> >             self.file_input_string = file_input.read().replace('\n', ' ')
> >
> You are assuming that all words are separated by blanks which is rarely the
> case in natural language.

Surelyyoumeanthatitisusuallythecasethatwordsareseparatedbyblanksinmostnaturallanguages?

I think that Thai is one of the few exceptions to the rule that most 
languages separate words with a blank space.

In English, there are a small number of compound words that contain 
spaces (as opposed to the far more common hyphen), such as "ice cream" 
(neither a form of ice, nor cream) or "attorney general" but most people 
don't bother distinguishing such compound words and just treating them 
as a pair of regular words. But I can't think of any English grammatical 
construct where words are run together while still treating them as 
separate words (apart from simple mistakes, e.g. accidentally writing 
"runtogether" as a typo).


> Your program is creating lists of ones. Rather than counting them all you
> need to do is take the length of each list.. e;g;: lowercase_letters =
> len(1 for c in self.file_input_string if c.islower())

That won't work. You are trying to take the length of a generator 
expression:

py> len(1 for c in "abcDe" if c.islower())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()

 
> However there is a much better way to do the counting: translate the text
> using the string translate method into various characters that identify the
> class of each letter in the file. Then count the occurrences of each of
> those characters. Example: counting Upper Lower, Nunber, and punctuation
> Single, Double stroke):
> 
> txt=  "THIS is 123 ,./ :*(" # input file text
> 
> transtable =
> str.maketrans("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
> ,./:*(",
>   "L"*26 + "U"*26 + "N"*10 + "S"*4 + "D"*3) # maps input characters to
> corresponding class characters

That lists only 68 out of the many, many thousands of characters 
supported by Python. It doesn't scale very well beyond ASCII.


-- 
Steve

From DerekSmith at racksquared.com  Sat Jan 20 13:26:31 2018
From: DerekSmith at racksquared.com (Derek Smith)
Date: Sat, 20 Jan 2018 18:26:31 +0000
Subject: [Tutor] Fwd: print a for loop system call
In-Reply-To: <BN6PR1201MB24833AC6C34A7429C8A1415CDDEF0@BN6PR1201MB2483.namprd12.prod.outlook.com>
References: <BN6PR1201MB24833AC6C34A7429C8A1415CDDEF0@BN6PR1201MB2483.namprd12.prod.outlook.com>
Message-ID: <17498D60-75A7-4CBE-91F3-A1B3348C644E@racksquared.com>



Sent from my iPhone

Begin forwarded message:

From: Derek Smith <DerekSmith at racksquared.com<mailto:DerekSmith at racksquared.com>>
Date: January 19, 2018 at 4:01:58 PM EST
To: "tutor-request at python.org<mailto:tutor-request at python.org>" <tutor-request at python.org<mailto:tutor-request at python.org>>
Subject: print a for loop system call

Why does A work but B does not?


#!/usr/bin/env python3

import os
import sys
from subprocess import Popen, PIPE

pipe = Popen('lsdev -c tape', shell=True, stdout=PIPE)

for dev in pipe.stdout :
    print ( dev.strip().split()[0].decode() )    ## A ##
    # print ( dev.strip().split().decode()[0] ) ## B ##


And if I try to store in an array using

rmts = [ dev.strip().split()[0].decode() ]

it only stores the last line when there are over 100 lines.

Sample line looks like

rmt144 Available 04-T1-01 LTO Ultrium Tape Drive (FCP)

thank you!

Derek Smith  |  Unix/TSM Administrator  | Racksquared Data Centers
':  614-437-4983 * 325 East Spring Street, Columbus, OH 43215
::  dereksmith at racksquared.com<mailto:dereksmith at racksquared.com>  *: www.racksquared.com<http://www.racksquared.com/> |  www.racksquared.jobs<http://www.racksquared.jobs/>

[cid:image003.png at 01D2E9AA.1B9CF8F0]


From alan.gauld at yahoo.co.uk  Sat Jan 20 18:39:56 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Sat, 20 Jan 2018 23:39:56 +0000
Subject: [Tutor] Fwd: print a for loop system call
In-Reply-To: <17498D60-75A7-4CBE-91F3-A1B3348C644E@racksquared.com>
References: <BN6PR1201MB24833AC6C34A7429C8A1415CDDEF0@BN6PR1201MB2483.namprd12.prod.outlook.com>
 <17498D60-75A7-4CBE-91F3-A1B3348C644E@racksquared.com>
Message-ID: <p40jse$3or$1@blaine.gmane.org>

On 20/01/18 18:26, Derek Smith wrote:

> import os
> import sys
> from subprocess import Popen, PIPE
> 
> pipe = Popen('lsdev -c tape', shell=True, stdout=PIPE)
> 
> for dev in pipe.stdout :
>     print ( dev.strip().split()[0].decode() )    ## A ##

This is OK

>     # print ( dev.strip().split().decode()[0] ) ## B ##

This tries to decode a list which won't work.
split() returns a list.
You want to apply decode to a string,
specifically the first string that split produces,
so it is correct as in option A.

If in doubt split the line up and print each
component as you create it:

for dev in pipe.stdout :
    print( dev.strip() )
    print( dev.strip().split())
    print( devb.strip().split()[0])
    print( dev.strip().split()[0].decode() )



> And if I try to store in an array using
> 
> rmts = [ dev.strip().split()[0].decode() ]
> 
> it only stores the last line when there are over 100 lines.

Wrong, it stores every line as it comes to it.
But, since you create a new list each time you
throw way the previous one. Only the last list
is preserved, but they were all stored, albeit
briefly...

You need to append() to a list, something like:

aList = []
for dev in....
   process dev
   aList.append(result)

Or as a list comprehension:

aList = [process(dev) for dev in ....]

-- 
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



From steve at pearwood.info  Sun Jan 21 05:15:32 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Sun, 21 Jan 2018 21:15:32 +1100
Subject: [Tutor] question about metaclasses
In-Reply-To: <HE1PR1001MB130822EB7D779B97B63CAFC583E80@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
References: <HE1PR1001MB130822EB7D779B97B63CAFC583E80@HE1PR1001MB1308.EURPRD10.PROD.OUTLOOK.COM>
Message-ID: <20180121101531.GP22500@ando.pearwood.info>

On Thu, Jan 18, 2018 at 05:14:43PM +0000, Albert-Jan Roskam wrote:

> Is a metaclass the best/preferred/only way of doing this? Or is a 
> class decorator an alternative route?

I haven't thought deeply about this, but I suspect a class decorator 
should do the job too.

The general advice is to use the simplest thing that does the job. The 
deeper you have to go into Python's scary internals, the better reason 
you should have:

- ordinary Python code is simpler than...
- code using decorators, which is simpler than...
- classes using custom descriptors, which is simpler than...
- classes with __init_subclass__, which is simpler than...
- code with metaclasses.

So in general you should pick the first technique (starting at the top) 
which solves your problem in a satisfactory manner.

The __init_subclass__ method is new to Python 3.6:

https://docs.python.org/3/reference/datamodel.html#object.__init_subclass__


Remember the excellent advice:

Debugging is harder than programming, so if you write the trickiest and 
most clever code you are capable of, by definition you won't be able to 
debug it.

Having said that, I applaud you for investigating metaclasses!


> Is the following analogy for doing stuff when a class is created ('born') correct?
> Metaclass --> prenatal surgery
> __new__ --> perinatal surgery
> Class decorator --> postnatal surgery


The last one is certainly correct: a class decorator gets called with 
the fully created class object, and then has the opportunity to modify 
it as needed.

It isn't clear to me what you mean by __new__. Do you mean the *class* 
__new__ method or the *metaclass* __new__ method?

If I write this:

class MetaC(type):
    def __new__(meta, *args):
        # pretend this does something useful

class C(metaclass=MetaC):
    def __new__(cls, *args):
        ...


then MetaC.__new__ and C.__new__ are called at very different times.

MetaC.__new__ is called as part of the process of creating C in the 
first place; so at the beginning of MetaC.__new__, C does not exist. 

C.__new__ on the other hand doesn't get called when creating C, it gets 
called when creating instances of C. Think of __new__ as the twin of 
__init__, with the following differences:

* __new__ is called before the instance ("self") exists, 
  and gets to customise the creation of the instance;

* __init__ is called after the instance is created, and
  gets to modify self provided self is mutable.


So writing an __init__ method for (say) a string subclass is usually a 
waste of time, since the string is already set and cannot be changed. 
This does not work:

class UpperString(str):
    # make strings uppercase
    def __init__(self):
        self = self.upper()

But this does:

class UpperString(str):
    def __new__(cls, arg):
        arg = str(arg).upper()
        return super().__new__(cls, arg)


Metaclasses are both extremely powerful *and* mind-blowing (back in 
Python 1.5, they were known as "the Killer Joke") because they can 
customise (nearly?) any part of the class operation. So you can think of 
a metaclass as all of the following:

- prenatal surgery (metaclass.__new__);

- postnatal surgery (metaclass.__init__);

- cybernetic implants (metaclass.__getattribute__, __getattr__ etc);

- mind-meld or telepathy between otherwise unrelated classes 
  (define methods in the metaclass as a kind of alternative to
  inheritence);

- gene therapy (all of the above?);

- (I can't think of a good analogy for this one): metaclass.__call__
  lets you customized what happens when you call your class, allowing 
  you to manipulate the arguments or the returned instance.

For example:

class Meta(type):
    def __call__(self, *args):
        print("called by", self)
        instance = super().__call__(*args)
        instance.foo = 1
        return instance


prints a message and adds a "foo" attribute to every instance of every 
class that belongs to it.

Oh, and just to make it more fun... metaclasses don't have to be a 
class! See if you can predict what this will do:


def meta(*args):
    print("Hi there, I'm your metaclass for today, how can I blow your mind?")
    return 42

class A(metaclass=meta):
    pass


See also The Killer Joke:
https://www.python.org/doc/essays/metaclasses/

That was written back in Python 1.5 days, so a lot of the information in 
it is now obsolete. But the basic techniques should more or less work 
today.



-- 
Steve

From alan.gauld at yahoo.co.uk  Tue Jan 23 11:25:11 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Tue, 23 Jan 2018 16:25:11 +0000
Subject: [Tutor] Updates to web tutor
In-Reply-To: <cfed362f-03d8-4402-958a-e271a2f4960f@yahoo.co.uk>
References: <cfed362f-03d8-4402-958a-e271a2f4960f@yahoo.co.uk>
Message-ID: <p47nh8$2d3$1@blaine.gmane.org>

On 15/11/17 17:41, Alan Gauld via Tutor wrote:
> I've been doing some much needed maintenance to my web tutor. 

Many thanks for all the feedback received.
I know there are at least a couple of minor glitches still
to fix - especially on iPhones...

However, the rewrite of the material has been done and the
presentation stuff seems to be close enough to be usable on
any device. As a result I have now launched it as the
official V3 version of my tutorial.

The front page (link in .sig) has been updated to reflect
that, but I plan on major rework there too eventually.

Once more, thanks to all who sent comments, and if there
are any more I will happily incorporate them in future
updates.

PS.
The old V3 tutor is still there in the background so anyone
with bookmarks should not be affected.

-- 
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



From jimmyjconnelly at gmail.com  Fri Jan 26 07:31:30 2018
From: jimmyjconnelly at gmail.com (jimmy connelly)
Date: Fri, 26 Jan 2018 12:31:30 +0000
Subject: [Tutor] Simple flask app querying twitter keeps crashing.
Message-ID: <CABxypv8Je64M8-sLQXP0XVpuuAOMTwbp_QivZq_eRJ+CDS_LOg@mail.gmail.com>

Hello I have a very simple Flask app for fetching tweets from twitter...

Its very simple
https://twitter-happy-or-sad-b.herokuapp.com/ outputs the word "hello" and
nothing else,

https://twitter-happy-or-sad-b.herokuapp.com/subject-tweets/any text
returns 100 tweets containg 'any text' or 100 tweets containing whatever
text you insert as a query string.

It runs great for a number of hours then crashes.

The / endpoint still outputs hello but the api for fetcing tweets is
completly broken after the crash.

The app works fine again for a few hours after restarting the dynos
manually then it crashes again.

I thought maybe it was because the dyno was going to sleep so I upgraded to
'hobby' service., but it doesn't help matters except it seems to run for a
little longer before crashing.

There is nothing in the logs at the moment because the logs don't go back
far enough to the time of the error.

I'm really stuck and don't know what to do.

Below is the entire code for the app - told you it was simple!


import tweepy
import json
import sys
from objdict import ObjDict
from flask import Flask
from flask import request

from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
from flask_cors import CORS

app = Flask(__name__)


CORS(app)

@app.route("/")
def helloWorld():
return "Hello"


# Enter authorisations
consumer_key = "my-consumer-key"
consumer_secret = "my-consumer-secret"
access_key = "my-access-key"
access_secret = "my-access-secret"

# Set up your authorisations
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)

# Set up API call
api = tweepy.API(auth, parser = tweepy.parsers.JSONParser())
#Make another app.route() decorator here that takes in an integer id in the
@app.route('/subject-tweets/<string:query>')
def getTweetsofQuery(query):
if request.method == 'GET':
# Set search query
searchquery = query + '-filter:retweets'
sentences = []
data = api.search(q = searchquery, count = 100, lang = 'en', result_type =
'mixed')
print 'size of data is ' + str(sys.getsizeof(data))
emptyData = False

#gotdata = None
try:
#gotdata = data.values()[1][10]['text']
for x in range(1, 99):
sentences.append(data.values()[1][x]['text'])
except IndexError:
sentences.append('no tweets for ' + query + ' - sorry')
emptyData = True
except Exception as e:
# do something with your exception
print(str(e))



# OLD CODE
#try:
# gotdata = data.values()[1][10]['text']
# for x in range(1, 99):
# sentences.append(data.values()[1][x]['text'])
#except IndexError:
# sentences.append('no tweets for ' + query + ' - sorry')
# emptyData = True




analyzer = SentimentIntensityAnalyzer()
compoundScores = []
for sentence in sentences:
vs = analyzer.polarity_scores(sentence)
compoundScores.append(vs['compound'])
#print(str(vs['compound']))

def mean(compoundScores ):
return float(sum(compoundScores )) / max(len(compoundScores ), 1)
data = ObjDict()
data.subject = query
if emptyData == True:
data.sentiment = 'sorry we dont have a score for ' + query
data.score = "It was impossible to measure sentiment for " + query + " this
time because no one tweeted that phrase in the last 7 days"
data.tweets = ["Sorry we don't have any tweets for " + query ]
else :
data.score = mean(compoundScores)
data.scoreString = ' The sentiment score for ' + query + ' is ' + str
(mean(compoundScores))
if data.score >= 0.5:
#data.sentiment = 'The sentiment rating for '+ query + ' is positive'
data.sentiment = 'Positive'
elif data.score > -0.5 and data.score < 0.5 :
#data.sentiment = 'The sentiment rating for '+ query + ' is neutral'
data.sentiment = 'Neutral'
elif data.score <= -0.5 :
#data.sentiment = 'The sentiment rating for '+ query + ' is negative'
data.sentiment = 'Negative'
data.tweets = sentences
json_data = data.dumps()
return json.dumps(data)

if __name__ == '__main__':
app.debug = True
app.run(host='0.0.0.0', port=5000)

From alan.gauld at yahoo.co.uk  Fri Jan 26 07:50:15 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Fri, 26 Jan 2018 12:50:15 +0000
Subject: [Tutor] Simple flask app querying twitter keeps crashing.
In-Reply-To: <CABxypv8Je64M8-sLQXP0XVpuuAOMTwbp_QivZq_eRJ+CDS_LOg@mail.gmail.com>
References: <CABxypv8Je64M8-sLQXP0XVpuuAOMTwbp_QivZq_eRJ+CDS_LOg@mail.gmail.com>
Message-ID: <p4f827$4pj$1@blaine.gmane.org>

On 26/01/18 12:31, jimmy connelly wrote:
> Hello I have a very simple Flask app for fetching tweets from twitter...
> ...
> It runs great for a number of hours then crashes.

Caveat, I'm in a hurry and haven't looked at your code.
But when things run fine for a long time then crash my
first instinct is to think "memory leak".

You don't specify OS but if it is *nix like then it
probably has vmstat so try running it with, say, a 1 minute
delay and log the output to a file. Then see if the memory
is being consumed.

Or use top or ps whatever other memory monitor you have.

Just a thought.

-- 
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



From robertvstepp at gmail.com  Fri Jan 26 21:56:31 2018
From: robertvstepp at gmail.com (boB Stepp)
Date: Fri, 26 Jan 2018 20:56:31 -0600
Subject: [Tutor] Do _all_ Python builtin methods/functions return "None" IF
 ...
Message-ID: <CANDiX9+zNLXy1NVaec7k_yYu=2eS_Op5D+VqzqP1UgHu_0BdPw@mail.gmail.com>

... they are not designed to explicitly return something else?

The reason I ask is that I almost fell into the following trap:

<GCE trap>
py3: a_lst = [0, 1, 2]
py3: b_lst = a_lst.append(3)
py3: a_lst, b_lst
([0, 1, 2, 3], None)

Instead of "None" I was expecting "[0, 1, 2, 3]".  Obviously I have a
GCE (Gross Conceptual Error).
</GCE trap>

I almost sent the above as my question, but then I realized (Finally!)
that lst.append() performs an append operation on lst and returns
None.  Just like print() returns None.

So my actual question is:  For these types of methods/functions, is
Python Both versions 2 and 3) consistent throughout and *always*
returns None?

TIA!

-- 
boB

From steve at pearwood.info  Fri Jan 26 23:32:33 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Sat, 27 Jan 2018 15:32:33 +1100
Subject: [Tutor] Do _all_ Python builtin methods/functions return "None"
 IF ...
In-Reply-To: <CANDiX9+zNLXy1NVaec7k_yYu=2eS_Op5D+VqzqP1UgHu_0BdPw@mail.gmail.com>
References: <CANDiX9+zNLXy1NVaec7k_yYu=2eS_Op5D+VqzqP1UgHu_0BdPw@mail.gmail.com>
Message-ID: <20180127043233.GF22500@ando.pearwood.info>

On Fri, Jan 26, 2018 at 08:56:31PM -0600, boB Stepp wrote:

> ... they are not designed to explicitly return something else?

Yes. In the absence of an explicit return, all Python functions will 
return None.


> The reason I ask is that I almost fell into the following trap:
> 
> <GCE trap>
> py3: a_lst = [0, 1, 2]
> py3: b_lst = a_lst.append(3)
> py3: a_lst, b_lst
> ([0, 1, 2, 3], None)
> 
> Instead of "None" I was expecting "[0, 1, 2, 3]".  Obviously I have a
> GCE (Gross Conceptual Error).
> </GCE trap>
> 
> I almost sent the above as my question, but then I realized (Finally!)
> that lst.append() performs an append operation on lst and returns
> None.  Just like print() returns None.
> 
> So my actual question is:  For these types of methods/functions, is
> Python Both versions 2 and 3) consistent throughout and *always*
> returns None?

Mostly. Python's policy is that functions and methods which operate by 
side-effect, or modify the object in place (such as list.append, insert, 
sort, reverse, etc, or dict.update, clear etc), return None. That is to 
prevent the sort of error where you do this:

alist = [4, 1, 2, 5, 3]
blist = alist.sort()
assert blist == [1, 2, 3, 4, 5]
assert alist == [4, 1, 2, 5, 3]  # this will fail


thinking that list.sort returns a copy.

So in general, such functions all return None. However, there have been 
a few changes, such as file.write method, which used to return None in 
Python 2 but in Python 3 returns the number of characters actually 
written.


-- 
Steve

From alan.gauld at yahoo.co.uk  Sat Jan 27 04:18:38 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Sat, 27 Jan 2018 09:18:38 +0000
Subject: [Tutor] Do _all_ Python builtin methods/functions return "None"
 IF ...
In-Reply-To: <CANDiX9+zNLXy1NVaec7k_yYu=2eS_Op5D+VqzqP1UgHu_0BdPw@mail.gmail.com>
References: <CANDiX9+zNLXy1NVaec7k_yYu=2eS_Op5D+VqzqP1UgHu_0BdPw@mail.gmail.com>
Message-ID: <p4hg1f$6qo$1@blaine.gmane.org>

On 27/01/18 02:56, boB Stepp wrote:

> So my actual question is:  For these types of methods/functions, is
> Python Both versions 2 and 3) consistent throughout and *always*
> returns None?

Mostly, but only for mutable objects.
So the string methods return a new string with the modifications
because the original string is immutable and cannot be changed.

So superficially, list handling methods return none on
modification but string methods return the modified string.
You need to bear in mind whether the object is mutable or
not to understand the expected result.

So if you come from SmallTalk, Python is horribly inconsistent.
If you come from C then its wonderfully consistent :-)

As with all languages you just get used to the foibles.

-- 
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



From cs at cskk.id.au  Sat Jan 27 05:54:39 2018
From: cs at cskk.id.au (Cameron Simpson)
Date: Sat, 27 Jan 2018 21:54:39 +1100
Subject: [Tutor] Do _all_ Python builtin methods/functions return "None"
 IF ...
In-Reply-To: <p4hg1f$6qo$1@blaine.gmane.org>
References: <p4hg1f$6qo$1@blaine.gmane.org>
Message-ID: <20180127105439.GA98555@cskk.homeip.net>

On 27Jan2018 09:18, Alan Gauld <alan.gauld at yahoo.co.uk> wrote:
>On 27/01/18 02:56, boB Stepp wrote:
>> So my actual question is:  For these types of methods/functions, is
>> Python Both versions 2 and 3) consistent throughout and *always*
>> returns None?
>
>Mostly, but only for mutable objects.
>So the string methods return a new string with the modifications
>because the original string is immutable and cannot be changed.
>
>So superficially, list handling methods return none on
>modification but string methods return the modified string.
>You need to bear in mind whether the object is mutable or
>not to understand the expected result.

For a big more context, the general rule is: if the method fetches a value from 
the object eg its length, of course it returns something other than None. But 
if a method _modifies_ the object (append an element to a list, close a file), 
just affecting its internal state, then the method will usually return None.

These modification methods _could_ return a value, but the general practice is 
not to.

Cheers,
Cameron Simpson <cs at cskk.id.au> (formerly cs at zip.com.au)

From chris_roysmith at internode.on.net  Sat Jan 27 21:58:30 2018
From: chris_roysmith at internode.on.net (Chris Roy-Smith)
Date: Sun, 28 Jan 2018 13:58:30 +1100
Subject: [Tutor] thinter: can't figure out how to update a window instead of
 creating a new on
Message-ID: <4937c0a6-38b4-25e9-cef0-7cb677529980@internode.on.net>

Hi,

system: Python 3.6, LInux

I have been playing around with the following code which I want to 
update the window, but I creates a new window (with the correct 
display), but I have not been able to find the solution. Perhaps I'm 
using the wrong key words in my searches.

Thank you for any assistance, I'm hoping to learn something from this 
experience

Regards, Chris Roy-Smith

#!/usr/bin/python3

import mysql.connector
from tkinter import *
import pickle
master = Tk()

def getCfg():
 ??? fobj = open('members.pkl', 'rb')
 ??? cfg = pickle.load(fobj)
 ??? fobj.close()
 ??? return cfg


def editmember(page=1):
 ??? form=Toplevel(master)
 ??? form.title('test form')
 ??? cfg=getCfg()
 ??? QrySelectMembers='select ident, concat_ws(" " ,`given`, `surname`) 
as `fullname` from `details` where 1 order by `surname` asc, `given` asc 
limit '+str(page)+', 10'
 ??? db=mysql.connector.connect(user = cfg['user'], password = 
cfg['password'], database = cfg['database'])
 ??? cursor=db.cursor()
 ??? cursor.execute(QrySelectMembers) #,(page))
 ??? MemberList=list(cursor)
 ??? cursor.close()
 ??? db.close
 ??? ro=0
 ??? for Member in MemberList:
 ??????? ident=Member[0]
 ??????? msg='edit '+Member[1]
 ??????? Button(form, text=msg, command= lambda tmp=ident : 
EdForm(tmp)).grid(sticky=(W, E), row=ro, column=0)
 ??????? ro+=1
 ??? Button(form, text='exit', command=form.destroy).grid(row=ro+1, 
column=2)
 ??? Button(form, text='next 10', command= lambda p=page+10 : 
editmember(p)).grid(row=ro, column=1)
 ??? Button(form, text="previous 10", command= lambda p=page-10 : 
editmember(p)).grid(row=ro, column=0)


Button(master, text='click to test', command=editmember).grid(row=0, 
column=0)
Button(master, text='quit', command=master.destroy).grid(row=1, column=0)
master.mainloop()


From alan.gauld at yahoo.co.uk  Sun Jan 28 08:01:59 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Sun, 28 Jan 2018 13:01:59 +0000
Subject: [Tutor] thinter: can't figure out how to update a window
 instead of creating a new on
In-Reply-To: <4937c0a6-38b4-25e9-cef0-7cb677529980@internode.on.net>
References: <4937c0a6-38b4-25e9-cef0-7cb677529980@internode.on.net>
Message-ID: <p4khg8$1t7$1@blaine.gmane.org>

On 28/01/18 02:58, Chris Roy-Smith wrote:

> I have been playing around with the following code which I want to 
> update the window, but I creates a new window

Yes, you are creating a new window each time.
You really need to have a separate unction create the
window once and store it (or the widgets of interest)
in a variable somewhere.

Then your other functions can simply update the widgets
through the variable(s)

Remember that anything you create inside a function
gets thrown away as soon as the function exits. To make
it persist you need to move it into global storage
(or start using objects, but thats a whole other discussion)

-- 
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



From hancock.g at gmail.com  Sun Jan 28 08:36:58 2018
From: hancock.g at gmail.com (Geoff Hancock)
Date: Sun, 28 Jan 2018 08:36:58 -0500
Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for a
 class
In-Reply-To: <CAJFTz1WdoRY5DteE+MRrBqGw=Nd=S-4QCvn8UbreQ7WSRdG1LA@mail.gmail.com>
References: <CAJFTz1WdoRY5DteE+MRrBqGw=Nd=S-4QCvn8UbreQ7WSRdG1LA@mail.gmail.com>
Message-ID: <CAJFTz1XKTMbfheS1-a9ZjQgJ+dCPYX6NR5C5jMzqVv5X2cgvpw@mail.gmail.com>

Good day-
I'm in a difficult situation.
I have been asked to help teach students how to clean up a CSV file in
Python.
The job has fallen to me because the teacher of the course is out on
emergency leave and I just found out.
Tomorrow I have to show students how to get a CSV file and write code to
clean and parse it.

I understand the process--BUT I don't know how to do it!
What I'm looking for is a simple
Step 1
Step 2
Step 3 etc
I'm running the latest version of Python and am running on Windows
Can anyone assist?

Much appreciate the time
JGH

From leamhall at gmail.com  Sun Jan 28 09:20:30 2018
From: leamhall at gmail.com (leam hall)
Date: Sun, 28 Jan 2018 09:20:30 -0500
Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for
 a class
In-Reply-To: <CAJFTz1XKTMbfheS1-a9ZjQgJ+dCPYX6NR5C5jMzqVv5X2cgvpw@mail.gmail.com>
References: <CAJFTz1WdoRY5DteE+MRrBqGw=Nd=S-4QCvn8UbreQ7WSRdG1LA@mail.gmail.com>
 <CAJFTz1XKTMbfheS1-a9ZjQgJ+dCPYX6NR5C5jMzqVv5X2cgvpw@mail.gmail.com>
Message-ID: <CACv9p5rPO6va_MY6HZzhxAu53T6cKFLAC7T_6U5KiwdkOaqsNw@mail.gmail.com>

On Sun, Jan 28, 2018 at 8:36 AM, Geoff Hancock <hancock.g at gmail.com> wrote:
> Good day-
> I'm in a difficult situation.
> I have been asked to help teach students how to clean up a CSV file in
> Python.
> The job has fallen to me because the teacher of the course is out on
> emergency leave and I just found out.
> Tomorrow I have to show students how to get a CSV file and write code to
> clean and parse it.
>
> I understand the process--BUT I don't know how to do it!
> What I'm looking for is a simple
> Step 1
> Step 2
> Step 3 etc
> I'm running the latest version of Python and am running on Windows
> Can anyone assist?
>
> Much appreciate the time
> JGH


Geoff, I'm not that great a coder but here's where I would start.
Assume a file name "gang_draft.csv" that is colon delimited since I'm
working on stuff for an RPG session.  :)

####

file = open('gang_draft.csv', 'r')
for line in file:
  line = line.strip()
  line_array = line.split(':')
  print(line_array[1])

####

Where I have print you can do whatever cleanup you like. Then either
print specific columns or join them back into a string.

Hope that helps start you in the right direction. Others here will
likely come up with better solutions.

Leam

From alan.gauld at yahoo.co.uk  Sun Jan 28 09:35:51 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Sun, 28 Jan 2018 14:35:51 +0000
Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for
 a class
In-Reply-To: <CAJFTz1XKTMbfheS1-a9ZjQgJ+dCPYX6NR5C5jMzqVv5X2cgvpw@mail.gmail.com>
References: <CAJFTz1WdoRY5DteE+MRrBqGw=Nd=S-4QCvn8UbreQ7WSRdG1LA@mail.gmail.com>
 <CAJFTz1XKTMbfheS1-a9ZjQgJ+dCPYX6NR5C5jMzqVv5X2cgvpw@mail.gmail.com>
Message-ID: <p4kn08$eu1$1@blaine.gmane.org>

On 28/01/18 13:36, Geoff Hancock wrote:
> Good day-

> I have been asked to help teach students how to clean up a CSV file in
> Python.

I'm not sure what you mean by "clean up" a CSV file.
If the file is malformed then turning it into a well
formed CSV file is a non trivial text processing task.

> Tomorrow I have to show students how to get a CSV file and write code to
> clean and parse it.

Parsing it is easy, and the python.org CSV module documentation
includes many examples, so I'd start there. (I'd also show your
students that page as a starter too, since learning to go to the
documentation is a good thing.)

Maybe structure the class around analyzing those examples
then trying some of your own?

The easiest way to generate a non trivial CSV file is probably
to save a spreadsheet from Excel...

> I understand the process--BUT I don't know how to do it!
> What I'm looking for is a simple
> Step 1
> Step 2
> Step 3 etc

Umm, I'm not sure what you need here.
A CSV file is opened as per a normal file - do you know how to do that?

Don't forget to include the DictReader too because it is often
better for extracting a sub set of the CSV fields.

If you are covering writing CSV files too - although thats
less common from Python, you also have the writer and
DictWriter classes, and although they do have examples
there isn't as much there.

Finally a fun thing todo in a classroom environment is to
get the students to buddy up and create a CSV file, then
pass it to their buddy and get them to decode it.

You could also try getting them to read a CSV file the hard
way using string handling methods alone, that way the advantages
of the CSV tools are more obvious to them!

It depends how much time you have. FOr a single study session
I'd go with reviewing the CSV module plus a "real world" example.

This assumes they even know what a CSV file is. If not, half
the lesson could be taken up on the file structure etc before
you even get to the code stuff.


-- 
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



From ebroukhim at hotmail.com  Sun Jan 28 17:06:05 2018
From: ebroukhim at hotmail.com (Edna Broukhim)
Date: Sun, 28 Jan 2018 22:06:05 +0000
Subject: [Tutor] program not doing what I need it to do
Message-ID: <CY1PR0301MB2092C9614999C65CC4B551CAA7E60@CY1PR0301MB2092.namprd03.prod.outlook.com>

I have the following program. It needs to say the user's name, average and the letter grade of each user. I don't know how to fix it so it gives the average of all users. It only gives the average of the last user.

user=int(input("How many students?"))
Score1=[]
Score2=[]
Score3=[]

name=[]
for i in range (0, user):
    name.insert(user, input("What is your name?"))

for i in range (0, user):
    ExamGrades=['exam1','exam2','exam3']
    Score1.append(float(input(str(name[i])+ ":What is your score on your first exam?")))
    Score2.append(float(input(str(name[i])+ ":What is your score on your second exam?")))
    Score3.append(float(input(str(name[i])+ ":What is your score on your third exam?")))

def Average():
    global average
    global grade
    for i in range (0, user):
        for j in range(len(Score1)):
            average=(Score1[j]+ Score2[j]+Score3[j])/3

        if(average>=90):
            grade = "A"
        elif(average>=80 and average<90):
            grade="B"
        elif(average>=70 and average<80):
            grade="C"
        elif(average>=60 and average<70):
            grade="D"
        else:
            grade = "F"

        return average

finalAverage=[]
for i in range (0, user):
        finalAverage.append(Average())

print(name[i]+ ":Your average is: "+str(finalAverage[i])+ ", which is " + grade)



From alan.gauld at yahoo.co.uk  Sun Jan 28 19:45:15 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Mon, 29 Jan 2018 00:45:15 +0000
Subject: [Tutor] program not doing what I need it to do
In-Reply-To: <CY1PR0301MB2092C9614999C65CC4B551CAA7E60@CY1PR0301MB2092.namprd03.prod.outlook.com>
References: <CY1PR0301MB2092C9614999C65CC4B551CAA7E60@CY1PR0301MB2092.namprd03.prod.outlook.com>
Message-ID: <p4lqms$80c$1@blaine.gmane.org>

On 28/01/18 22:06, Edna Broukhim wrote:

You have tried to give the variables sensible names but
a little bit more work will make your code more readable
and therefore easier to debug. You need to  rethink your
data model slightly.

You have a number of users (which you don't explicitly
store at present).

For each user you have 3 exam results.

The average is (exam1+exam2+exam3)/3

Instead of storing 3 lists of N results why not
store N lists of 3 results? That allows you to
leverage Pythons sum() function so your code
becomes something like:

for user_id in range(num_users):
    average = sum(scores[user_id])/3

Which I think you will agree is easier to read
than the code you currently have?

Here are some other general comments:

> user=int(input("How many students?"))

This is not really the user, it is the number of
users so call it something like

user_count or num_users

or just count.

> Score1=[]
> Score2=[]
> Score3=[]

Again these are lists so not single scores,
Call them scores1..3 or maybe better still
create a list of lists:

scores = []  # three sets of scores.

> name=[]

Again this is not a single name so call it names.

> for i in range (0, user):

This then becomes:

for user_id in range(num_users)

>     name.insert(user, input("What is your name?"))

Here we have a more serious problem.

Your name list has no entries so the first inserts
will ignore the user_num and just insert the name
at the end, so you might as well just use append()
instead. insert is really for use in a populated list.

The other issue is that while you loop over the numbers
up to num_users you always insert at num_users not at i.
In fact you ignore i. (or, as I called it, user_id)

Instead try

for user_id in range(num_users):
    names.append(input(....))

But why only store the names? Why not add the users scores too?

users = []
for user_id in range(num_users):
    user = [input(....),[]]  # empty list for scores
    users.append(user)

> for i in range (0, user):

Again this might be clearer as

for user_id in range(num_users):

>     ExamGrades=['exam1','exam2','exam3']

Notice that you assign this every time you go round the
loop. You probably only need to do it once before the loop.
And again the name is not really reflecting the values.
It is not grades but exam names, so the variable should be
something like:

ExamNames

Although by convention we reserve capitalised names for
classes so better would be:

examNames or exam_names

But to be honest I don't think you really need it!

>     Score1.append(float(input(str(name[i])+ ":What is your score on your first exam?")))

We need to decompose this a bit to see what is happening:

       prompt = names[user_id] + ":What is your score on exam" +
                str(exam)
       value = float(input(prompt))
       Score1.append(value)

Breaking things into smaller chinks makes it easier to read
and you can print the intermediate values if it goes wrong.
Putting too much in one line is usually a bad idea.

However, with the restructuring I suggested above it could
be written as

for user in users:
   print("For user: ",user[0])  # print name as prompt
   for exam in range(1,4):
      score = float(input("Score for exam " + str(exam))
      user[1].append(score)   # add it to the users scores list

> def Average():
>     global average
>     global grade

Its conventional to initialise global variables outside
the function, otherwise they are hard to find when you
come to debug another function that uses them.

>     for i in range (0, user):
>         for j in range(len(Score1)):
>             average=(Score1[j]+ Score2[j]+Score3[j])/3

Using my model this becomes:

for user in users):
    average = sum(user[1])/3

>         if(average>=90):
>             grade = "A"
>         elif(average>=80 and average<90):
>             grade="B"
>         elif(average>=70 and average<80):
>             grade="C"
>         elif(average>=60 and average<70):
>             grade="D"
>         else:
>             grade = "F"
> 
>         return average

That bit is OKI although you can tidy it slightly
with a Python trick:

         if(average>=90):
             grade = "A"
         elif(80 <= average < 90):
             grade="B"
         elif(70 <= average < 80):
             grade="C"
etc


> finalAverage=[]
> for i in range (0, user):
>         finalAverage.append(Average())

Rather than create another list why not add the average
(and grade?) to each users record within the loop above?

user.append( Average() )

You would needto modify the function to return the grade
too - otherwise you just throw it away...

    return (average, grade)    # a tuple of ave and grade

> print(name[i]+ ":Your average is: "+str(finalAverage[i])+ ", which is " + grade)

Since this is outside the loop it only prints the lsat entry...

for user in users:
   print(user[0], "Your average is: ",
         user[2][0], " and your grade is: "
         user[2][1] )

I hope that makes sense.

The data model you choose has a huge impact on how easy
it is to code things. And the names you choose have a
big impact on readability. Make lists plural and numbers
numbers etc.

-- 
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



From alan.gauld at yahoo.co.uk  Sun Jan 28 20:37:00 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Mon, 29 Jan 2018 01:37:00 +0000
Subject: [Tutor] program not doing what I need it to do
In-Reply-To: <p4lqms$80c$1@blaine.gmane.org>
References: <CY1PR0301MB2092C9614999C65CC4B551CAA7E60@CY1PR0301MB2092.namprd03.prod.outlook.com>
 <p4lqms$80c$1@blaine.gmane.org>
Message-ID: <p4ltns$dl$1@blaine.gmane.org>

On 29/01/18 00:45, Alan Gauld via Tutor wrote:

> scores = []  # three sets of scores.

Oops, sorry that line shouldn't be there.
It came from my first pass through the code,
before I saw how you were storing the data lower down.


-- 
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



From bhaskaran.vinod at gmail.com  Mon Jan 29 01:42:57 2018
From: bhaskaran.vinod at gmail.com (vinod bhaskaran)
Date: Mon, 29 Jan 2018 12:12:57 +0530
Subject: [Tutor] doubt in a program
Message-ID: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>

Hi,

I am a new beginner in programming.
I saw a code (given below) to reverse  string.

newstring = ''
oldstring = 'Newton'
for char in oldstring:
   newstring = char + newstring
print(newstring)



Could someone explain how it is traversing to get the string reversed?

As the new character is adding the char in the new string but how is it
getting reversed without any line giving the char number to be traversed in
reverse order.

Thanks,
Vinod

From alan.gauld at yahoo.co.uk  Mon Jan 29 04:25:52 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Mon, 29 Jan 2018 09:25:52 +0000
Subject: [Tutor] doubt in a program
In-Reply-To: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>
References: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>
Message-ID: <p4mp70$p7r$1@blaine.gmane.org>

On 29/01/18 06:42, vinod bhaskaran wrote:

> newstring = ''
> oldstring = 'Newton'
> for char in oldstring:
>    newstring = char + newstring
> print(newstring)
> 
> Could someone explain how it is traversing to get the string reversed?

print statements are your friend.
Add print statements everywhere that a variable changes value:

 newstring = ''
 oldstring = 'Newton'
 for char in oldstring:
    print ("char=",char)
    newstring = char + newstring
    print(newstring=",newstring)
 print(newstring)

That will let you see how the newstring gets built
up inside the loop.

You could do the same thing using a paper and pen,
just walk through the code in your mind and write
down the values each time, like so:

char	newstring
N	N
e	e = N -> eN
w	w + eN -> weN
etc...

> As the new character is adding the char in the new string but how is it
> getting reversed without any line giving the char number to be traversed in
> reverse order.

As you will see if you do either of the suggested
exercises the addition always puts the latest char
at the front of the newstring.

-- 
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



From bhaskaran.vinod at gmail.com  Mon Jan 29 04:41:02 2018
From: bhaskaran.vinod at gmail.com (vinod bhaskaran)
Date: Mon, 29 Jan 2018 09:41:02 +0000
Subject: [Tutor] doubt in a program
In-Reply-To: <4A70D6F1-AE81-4246-B649-CB095AC620C1@g.clemson.edu>
References: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>
 <4A70D6F1-AE81-4246-B649-CB095AC620C1@g.clemson.edu>
Message-ID: <CAKS=jrC01Xk8jxUdp30X4JfmvVh-mnVzvC_Hh80=eAn5W_d-KQ@mail.gmail.com>

Thanks a lot Nitin. I misunderstood the "char + newstring".
As a newbie to programming as well as newbie to Python trying to grasp
basics. Sure will need the built in functions present for different things
in Python.
Any suggestion good book for python?

Thanks,
Vinod Bhaskaran

On Mon, Jan 29, 2018, 2:47 PM Nitin Madhok <nmadhok at g.clemson.edu> wrote:

> Vinod,
>
> First time it loops,
> newstring = ??
> oldstring = ?Newton?
> char = ?N?
> char + newstring = ?N? + ?? = ?N?
>
> Second time it loops,
> newstring = ?N?
> oldstring = ?Newton?
> char = ?e?
> char + newstring = ?e? +?N? = ?eN?
>
> Third time it loops,
> newstring = ?eN?
> oldstring = ?Newton?
> char = ?w?
> char + newstring = ?w? +?eN? = ?weN?
>
> Fourth time it loops,
> newstring = ?weN?
> oldstring = ?Newton?
> char = ?t?
> char + newstring = ?t? +?weN? = ?tweN?
>
> Fifth time it loops,
> newstring = ?tweN?
> oldstring = ?Newton?
> char = ?o?
> char + newstring = ?o? +?tweN? = ?otweN?
>
> Sixth/Final time it loops:
> newstring = ?otweN?
> oldstring = ?Newton?
> char = ?n?
> char + newstring = ?n? +?otweN? = ?notweN?
>
> newstring after loop finishes will be ?notweN? which is the reverse of
> ?Newton?
>
> Let me know if that explanation helps you understand it better. There are
> built in functions to reverse a string that are more efficient than this
> approach that you should be using to reverse a string.
>
> --
>
> Thanks,
> Nitin Madhok
> Clemson University
>
> CONFIDENTIALITY NOTICE
> This e-mail, and any attachments thereto, is intended only for use by the
> addressee(s) named herein and may contain privileged and/or confidential
> information. If you are not the intended recipient of this e-mail, any
> dissemination, distribution or copying of this e-mail, and any attachments
> thereto, is strictly prohibited. If you have received this e-mail in error,
> please immediately notify the sender by e-mail or telephone and permanently
> delete all copies of this e-mail and any attachments.
>
> > On Jan 29, 2018, at 1:42 AM, vinod bhaskaran <bhaskaran.vinod at gmail.com>
> wrote:
> >
> > Hi,
> >
> > I am a new beginner in programming.
> > I saw a code (given below) to reverse  string.
> >
> > newstring = ''
> > oldstring = 'Newton'
> > for char in oldstring:
> >   newstring = char + newstring
> > print(newstring)
> >
> >
> >
> > Could someone explain how it is traversing to get the string reversed?
> >
> > As the new character is adding the char in the new string but how is it
> > getting reversed without any line giving the char number to be traversed
> in
> > reverse order.
> >
> > Thanks,
> > Vinod
> > _______________________________________________
> > Tutor maillist  -  Tutor at python.org
> > To unsubscribe or change subscription options:
> > https://mail.python.org/mailman/listinfo/tutor
>

From nmadhok at g.clemson.edu  Mon Jan 29 04:17:23 2018
From: nmadhok at g.clemson.edu (Nitin Madhok)
Date: Mon, 29 Jan 2018 04:17:23 -0500
Subject: [Tutor] doubt in a program
In-Reply-To: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>
References: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>
Message-ID: <4A70D6F1-AE81-4246-B649-CB095AC620C1@g.clemson.edu>

Vinod,

First time it loops, 
newstring = ??
oldstring = ?Newton?
char = ?N?
char + newstring = ?N? + ?? = ?N?

Second time it loops,
newstring = ?N?
oldstring = ?Newton?
char = ?e?
char + newstring = ?e? +?N? = ?eN?

Third time it loops,
newstring = ?eN?
oldstring = ?Newton?
char = ?w?
char + newstring = ?w? +?eN? = ?weN?

Fourth time it loops,
newstring = ?weN?
oldstring = ?Newton?
char = ?t?
char + newstring = ?t? +?weN? = ?tweN?

Fifth time it loops,
newstring = ?tweN?
oldstring = ?Newton?
char = ?o?
char + newstring = ?o? +?tweN? = ?otweN?

Sixth/Final time it loops:
newstring = ?otweN?
oldstring = ?Newton?
char = ?n?
char + newstring = ?n? +?otweN? = ?notweN?

newstring after loop finishes will be ?notweN? which is the reverse of ?Newton?

Let me know if that explanation helps you understand it better. There are built in functions to reverse a string that are more efficient than this approach that you should be using to reverse a string.

--

Thanks,
Nitin Madhok
Clemson University

CONFIDENTIALITY NOTICE
This e-mail, and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain privileged and/or confidential information. If you are not the intended recipient of this e-mail, any dissemination, distribution or copying of this e-mail, and any attachments thereto, is strictly prohibited. If you have received this e-mail in error, please immediately notify the sender by e-mail or telephone and permanently delete all copies of this e-mail and any attachments.

> On Jan 29, 2018, at 1:42 AM, vinod bhaskaran <bhaskaran.vinod at gmail.com> wrote:
> 
> Hi,
> 
> I am a new beginner in programming.
> I saw a code (given below) to reverse  string.
> 
> newstring = ''
> oldstring = 'Newton'
> for char in oldstring:
>   newstring = char + newstring
> print(newstring)
> 
> 
> 
> Could someone explain how it is traversing to get the string reversed?
> 
> As the new character is adding the char in the new string but how is it
> getting reversed without any line giving the char number to be traversed in
> reverse order.
> 
> Thanks,
> Vinod
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor

From lists at mostrom.pp.se  Mon Jan 29 08:25:04 2018
From: lists at mostrom.pp.se (Jan Erik =?utf-8?q?Mostr=C3=B6m?=)
Date: Mon, 29 Jan 2018 14:25:04 +0100
Subject: [Tutor] doubt in a program
In-Reply-To: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>
References: <CAKS=jrBh1RKi-pyKwg1O9CAcSdochQ+Jcyi3SOAgQrX+C+kmWw@mail.gmail.com>
Message-ID: <8EE77C00-BB22-4BE2-BAE9-DF5726E5AA9E@mostrom.pp.se>

On 29 Jan 2018, at 7:42, vinod bhaskaran wrote:

> As the new character is adding the char in the new string but how is 
> it
> getting reversed without any line giving the char number to be 
> traversed in
> reverse order.

You don't need that, think about this example

newstring = ''
oldstring = "Newton"

now you go through each char in oldstring, so you get first N which you 
add to newstring and you get

newstring = 'N'

next char is 'e' and then you do 'e' + 'N' and get 'eN'

newstring = 'eN'

next char the same way

newstring = 'weN'

etc

until you get 'notweN'

Remember that the for-loop will step through each char in oldstring so 
when you come to the end the loop will stop.

= jem

From neilc at norwich.edu  Mon Jan 29 08:48:33 2018
From: neilc at norwich.edu (Neil Cerutti)
Date: Mon, 29 Jan 2018 13:48:33 +0000 (UTC)
Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for
 a class
References: <CAJFTz1WdoRY5DteE+MRrBqGw=Nd=S-4QCvn8UbreQ7WSRdG1LA@mail.gmail.com>
 <CAJFTz1XKTMbfheS1-a9ZjQgJ+dCPYX6NR5C5jMzqVv5X2cgvpw@mail.gmail.com>
Message-ID: <p4n8nh$tes$1@blaine.gmane.org>

On 2018-01-28, Geoff Hancock <hancock.g at gmail.com> wrote:
> Good day-
> I'm in a difficult situation.
> I have been asked to help teach students how to clean up a CSV
> file in Python.

Can you give an example of the kind of thing you need to teach?

It is malformed csv that has to be changed into well-formed?

That's sounds like a fun and challenging problem.

-- 
Neil Cerutti


From sa.testinggeek at gmail.com  Mon Jan 29 11:30:12 2018
From: sa.testinggeek at gmail.com (Dragan Mestrovik)
Date: Mon, 29 Jan 2018 22:00:12 +0530
Subject: [Tutor] Python GUI Grid like view with checkboxes in first column
Message-ID: <CAKtn2oP4X1ri3aa_uZh+EbQbc_qxGJRxve8iLkBSR0VL8ei6Lg@mail.gmail.com>

Hi,

I need some suggestions/help in showing large amount of data in grid like
view with first column having checkboxes. Please see the image attached.
How can i achieve this in Python GUI?
[image: Inline image 1]http://oi39.tinypic.com/28vq6wn.jpg

From alan.gauld at yahoo.co.uk  Mon Jan 29 16:07:38 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Mon, 29 Jan 2018 21:07:38 +0000
Subject: [Tutor] Python GUI Grid like view with checkboxes in first
 column
In-Reply-To: <CAKtn2oP4X1ri3aa_uZh+EbQbc_qxGJRxve8iLkBSR0VL8ei6Lg@mail.gmail.com>
References: <CAKtn2oP4X1ri3aa_uZh+EbQbc_qxGJRxve8iLkBSR0VL8ei6Lg@mail.gmail.com>
Message-ID: <p4o2aq$kl0$1@blaine.gmane.org>

On 29/01/18 16:30, Dragan Mestrovik wrote:

> I need some suggestions/help in showing large amount of data in grid like
> view with first column having checkboxes. Please see the image attached.
> How can i achieve this in Python GUI?
> [image: Inline image 1]http://oi39.tinypic.com/28vq6wn.jpg

The first thing I'd suggest is do not use Tkinter as the GUI.
There are other GUI frameworks with a native grid or table
control which will be much more suitable. Whether or not
they can put a checkbox in the first column is something
you will need to investigate.

As an example the wxPython framework has a grid component,
and it can use custom renderers so I suspect a checkbox
would be one such. But for the details I'd ask on the
wxPython mailing list.

Other frameworks such as GTk and Qt probably have grids too.

-- 
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



From joseph.slater at wright.edu  Wed Jan 31 08:06:20 2018
From: joseph.slater at wright.edu (Slater, Joseph C.)
Date: Wed, 31 Jan 2018 13:06:20 +0000
Subject: [Tutor] python gui Tkinter
In-Reply-To: <p3d4cc$gs6$1@blaine.gmane.org>
References: <CAGZNpHr3GE+KY_5fTjv=r_yfWBZ2coAKhsnKx=dN65p71sk1Ew@mail.gmail.com>
 <p3d4cc$gs6$1@blaine.gmane.org>
Message-ID: <3C930624-5B77-4C96-BFB1-7F2A636EAEB7@wright.edu>



> On Jan 13, 2018, at 9:18 AM, Alan Gauld via Tutor <tutor at python.org> wrote:
> 
> On 13/01/18 12:05, mamatha n wrote:
>> please any one give me the code for
> 
> We don't write code for you (unless you want to pay
> one of us as a contractor) But we can point you at
> some examples:
> 
>> username (entryfld)-----
>> pwrd (entryfld)----
>> login(button),    changepwrd(button)
> 
> So far very basic Tkinter, any tutorial would cover it.
> You could try mine at:
> 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.alan-2Dg.me.uk_tutgui.htm&d=DwICAg&c=3buyMx9JlH1z22L_G5pM28wz_Ru6WjhVHwo-vpeS0Gk&r=rEyLMZFJ7eh_1iNO7KnqQcXbAnZbNOjKNJqN1v2jbrM&m=TDPz4iOXs_iLt1rddlS505soW8LnHYNnzm_S0Uj51wA&s=gdu771QaCyO11Mgznt3NAgOscLvo5o-1tbFh5mrRPl8&e= 
> 
> 


I found that link failing, but found this instead:
http://www.alan-g.me.uk/l2p2/index.htm

The l2p2 was missing. 

Best Regards- Joe



From megan.zirger at gmail.com  Wed Jan 31 12:42:30 2018
From: megan.zirger at gmail.com (Megan Zirger)
Date: Wed, 31 Jan 2018 18:42:30 +0100
Subject: [Tutor] unable to locate python on mac
Message-ID: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com>

Hi there, 

I am completely new to python and trying to learn how to set up and get going. The one problem is that I?ve supposedly downloaded the new version. When I run it in the terminal I see that I have the version but I can?t find it anywhere in the applications or anywhere on my computer as to make modifications and be able to work with sublime text. 

Your help is appreciated. 

Thank you, 

Megan

From alan.gauld at yahoo.co.uk  Wed Jan 31 14:44:07 2018
From: alan.gauld at yahoo.co.uk (Alan Gauld)
Date: Wed, 31 Jan 2018 19:44:07 +0000
Subject: [Tutor] unable to locate python on mac
In-Reply-To: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com>
References: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com>
Message-ID: <p4t667$l8g$1@blaine.gmane.org>

On 31/01/18 17:42, Megan Zirger wrote:

> I am completely new to python and trying to learn how to set up and get going. 

I'm not a Mac expert but v2.7 is usually installed on a Mac by default
(although its just a basic version its fine for learning)

If you have downloaded v3.6 9the latest version) then it will say so at
the banner message that comes up when you run it.

AS to where it is located you can find that out at the Terminal OS
prompt by typing

$ which python3

However you should never need to modify it or do anything to it.

> I can?t find it anywhere in the applications

You probably won't see it in finder unless you navigate the file system.
It is not like a normal GUI style app.

>  able to work with sublime text. 

I think that's a text editor right?
Or is it more of an IDE? Can you run the code inside sublime?
Is that what you are trying to set up?

If that's the case you probably need to type in the path to the pyhon3
interpreter in Sublime's settings somewhere. Thats the same path you
got from 'which python3' above.

If you need more details you will need to ask more specific questions.
Bear in mind that although some folks here use Macs most of us don't.

-- 
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



From david at graniteweb.com  Wed Jan 31 15:59:18 2018
From: david at graniteweb.com (David Rock)
Date: Wed, 31 Jan 2018 14:59:18 -0600
Subject: [Tutor] unable to locate python on mac
In-Reply-To: <p4t667$l8g$1@blaine.gmane.org>
References: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com>
 <p4t667$l8g$1@blaine.gmane.org>
Message-ID: <C67ACC0D-9D5C-4D6F-A5CE-635A0A2051B1@graniteweb.com>


> On Jan 31, 2018, at 13:44, Alan Gauld via Tutor <tutor at python.org> wrote:
> 
> If you need more details you will need to ask more specific questions.
> Bear in mind that although some folks here use Macs most of us don't.
> 

Another pertinent question is what python did you actually install (i.e., where did you get it from)?  Different bundles install differently, so knowing exactly what you downloaded will help identify some of the other questions.


? 
David Rock
david at graniteweb.com





From cs at cskk.id.au  Wed Jan 31 17:10:05 2018
From: cs at cskk.id.au (Cameron Simpson)
Date: Thu, 1 Feb 2018 09:10:05 +1100
Subject: [Tutor] unable to locate python on mac
In-Reply-To: <p4t667$l8g$1@blaine.gmane.org>
References: <p4t667$l8g$1@blaine.gmane.org>
Message-ID: <20180131221005.GA9239@cskk.homeip.net>

On 31Jan2018 19:44, Alan Gauld <alan.gauld at yahoo.co.uk> wrote:
>On 31/01/18 17:42, Megan Zirger wrote:
>> I am completely new to python and trying to learn how to set up and get 
>> going.
>
>I'm not a Mac expert but v2.7 is usually installed on a Mac by default
>(although its just a basic version its fine for learning)

Yes, the system Python is 2.7:

  [~]fleet*> /usr/bin/python
  Python 2.7.10 (default, Oct 23 2015, 19:19:21)
  [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
  Type "help", "copyright", "credits" or "license" for more information.
  >>>

That's from El Capitan, a few OS releases behind.

[...]
>>  able to work with sublime text.
>
>I think that's a text editor right?
>Or is it more of an IDE? Can you run the code inside sublime?
>Is that what you are trying to set up?

Subblime Text is just an editor. It's got lots of nice stuff but it isn't an 
IDE.

>If that's the case you probably need to type in the path to the pyhon3
>interpreter in Sublime's settings somewhere. Thats the same path you
>got from 'which python3' above.

My Sublime text seems to be associated as the default app for opening .py files 
already. A little surprised here, I use vim mostly and thought I'd bound MacVim 
(the GUI form of vim on a Mac) for .py files.

>If you need more details you will need to ask more specific questions.
>Bear in mind that although some folks here use Macs most of us don't.

I live on a Mac, I'll watch this thread.

But yes, Alan's remark that Python isn't an "app" in the sense of a GUI tool is 
probably very pertinent.

Megan, you may be expecting Python to be a GUI app. It isn't, though it can be 
used to write them. You also need some sort of arrangement to edit python code 
and run it.

Such arrangements tend to come in 2 basic forms: an IDE (integrated development 
environment) which is usually a GUI app with both editing and running 
capabilities, or separate editor and run arrangements.

Sublime Text, which I gather you use, is, I thought, just an editor. You also 
need somewhere to run Python from. Those of use not using IDEs generally run 
the programmes from a terminal. Personally I use iterm3 for my terminals, lots 
of nice features.

Cheers,
Cameron Simpson <cs at cskk.id.au> (formerly cs at zip.com.au)

From steve at pearwood.info  Wed Jan 31 21:15:40 2018
From: steve at pearwood.info (Steven D'Aprano)
Date: Thu, 1 Feb 2018 13:15:40 +1100
Subject: [Tutor] unable to locate python on mac
In-Reply-To: <p4t667$l8g$1@blaine.gmane.org>
References: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com>
 <p4t667$l8g$1@blaine.gmane.org>
Message-ID: <20180201021529.GK26553@ando.pearwood.info>

On Wed, Jan 31, 2018 at 07:44:07PM +0000, Alan Gauld via Tutor wrote:

> AS to where it is located you can find that out at the Terminal OS
> prompt by typing
> 
> $ which python3

You can also run:

sys.executable

from Python itself. For example, on my system:

py> sys.executable
'/usr/local/bin/python3.5'

It will probably be somewhere different on Mac OS.



-- 
Steve