Re: Best way to determine user's screensize?

2020-10-30 Thread jfong
What's wrong the OP's question? Why can't just answer it?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: GUI (tkinter) popularity and job prospects for

2020-10-22 Thread jfong
Lammie Jonson於 2020年10月23日星期五 UTC+8上午5時20分45秒寫道:
> Thanks,
> 
>  Yes, I have some sense about how to do job interviews and market myself 
> which is always an ongoing process. 
> 
> I also just have an interest in different technologies that I may want to 
> investigate as I can get bored with certain things a little at times. If some 
> technology seems a little interesting to me but I don't see that there are a 
> lot of job listings for it however, then I sometimes wonder why that is etc

A job listing shows the interest of the society, how it connects with your 
interest?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Any timeline for PIL for Python 3.4

2020-08-10 Thread jfong
dn於 2020年8月11日星期二 UTC+8下午1時29分47秒寫道:
> On 11/08/2020 16:35, Martin wrote:
> > I am running Python 3.4.4, and would like to
> > use the Python Imaging Library (PIL).  This
> > is currently not available for Python
> > Version 3.  Does anybody know when it will
> > become available?
> > 
> > Plan B is to install Python 2.7.18.  I just
> > need an idea of how long I would need to
> > wait for Plan A.
> 
> 
> 1 PIL was discontinued about a decade back. Please use "Pillow" (a fork 
> - note first three letters), which is available from PyPI (pip3)
> 
> 2 Bad news though, IIRC it requires Python 3.5+
> 
> 3 Don't degrade to Py2 if you can at all avoid doing-so!
> -- 
> Regards =dn

Pillow for Python 3.4 can be downloaded at this moment in time:-)

https://www.lfd.uci.edu/~gohlke/pythonlibs/#pillow

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Function to avoid a global variable

2020-04-27 Thread jfong
bvdp於 2020年4月28日星期二 UTC+8上午9時46分35秒寫道:
> Oh my, that is very cool! So, I can do this:
> 
> def foo(i):
> if not 'bar' in foo.__dict__:
> foo.bar = 5
> foo.bar += i

You can have function attribute created this way if you like:

def foo(i):
foo.bar += i
foo.bar = 5

--Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Tkinter layout designer

2020-02-25 Thread jfong
mm0fmf於 2020年2月25日星期二 UTC+8上午5時29分33秒寫道:
> Can anyone recommend a graphic layout designer for Tkinter programs. I 
> have a number of older C# Windows Forms apps that need porting so they 
> can run on Linux and Windows and this is the chance to re-write them in 
> Python. However, after using the forms designer in Visual Studio, 
> manually coding up the widget positions etc. is a real pain in the 
> backside.
> 
> So please, recommendations for a designer that is usable and functional 
> please to save me working through everything a Google search throws up.
> 
> Thanks,
> Andy

Download PAGE here:
https://sourceforge.net/projects/page/

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


How to decide which module is in charge of this error? cx-Freeze or pynput or six?

2020-01-09 Thread jfong
Takes the simple\hello.py file in the cx_Freeze\samples directory as an 
example, I insert this line into hello.py:

from pynput.keyboard import Key, Controller

then build the executable using "py setup.py build" command, the on-screen 
message shows this missing module warning:

...
Missing modules:
...
? six.moves imported from pynput._util
...

Run the created hello.exe will cause this error:

...
from pynput._util import Events
  File "C:\Users\jfong\AppData\Local\Programs\Python\Python36-32\lib\site-
packages\pynput\_util\__init__.py", line 33, in 
from six.moves import queue
  File 
"C:\Users\jfong\AppData\Local\Programs\Python\Python36-32\lib\site-packages\six.py",
 line 92, in __get__
result = self._resolve()
  File 
"C:\Users\jfong\AppData\Local\Programs\Python\Python36-32\lib\site-packages\six.py",
 line 115, in _resolve
return _import_module(self.mod)
  File 
"C:\Users\jfong\AppData\Local\Programs\Python\Python36-32\lib\site-packages\six.py",
 line 82, in _import_module
__import__(name)
ModuleNotFoundError: No module named 'queue'

If I change line 33 in file pynput\_util\__init__.py
from six.moves import queue
to
import queue
and re-build, then that missing warning is gone and hello.exe excutes correctly.

My question is how to decide which module causes this problem?

PS. My environment is Windows 8.1, Python 3.6.8, cx-Freeze 5.1.1, pynput 1.6.5, 
six 1.13.0. I had try to upgrade the cx-Freeze to the latest v6.1 but result is 
the same.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Does the argparse generate a wrong help message?

2020-01-01 Thread jfong
Random832於 2020年1月2日星期四 UTC+8上午5時04分36秒寫道:
> On Fri, Dec 27, 2019, at 23:08, jf...@ms4.hinet.net wrote:
> > > > optional arguments:
> > > >   -h, --help   show this help message and exit
> > > >   --foo [FOO]  foo help
> > > >   --goo GOOgoo help
> > > >
> > > > D:\Works\Python>py test.py --foo 1 --goo 2
> > > > 1 ['2']
> >
> > So the square bracket means optional, not list? My misunderstanding:-(
> 
> To be clear, the brackets in the print output do mean a list, and it is 
> because nargs=1 produces a list rather than the default (no nargs) which is 
> to produce a single value. This is not normally visible to the end user (it's 
> just a difference in how your program consumes the one mandatory argument), 
> so it's not reflected in the help output. Square brackets in the help output 
> mean an optional argument.

Yes, I have noticed my misunderstanding. I thought [FOO] in "--foo [FOO]" is a 
list until Chris had reminded me:-) Thank you for clarifying it in detail.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Does the argparse generate a wrong help message?

2019-12-27 Thread jfong
Chris Angelico於 2019年12月28日星期六 UTC+8上午11時30分47秒寫道:
> On Sat, Dec 28, 2019 at 2:26 PM  wrote:
> >
> > The codes in test.py are:
> > -
> > import argparse
> > parser = argparse.ArgumentParser()
> > parser.add_argument('--foo', nargs='?', help='foo help')
> > parser.add_argument('--goo', nargs=1, help='goo help')
> > args = parser.parse_args()
> > print(args.foo, args.goo)
> > -
> >
> > But I get the following result:
> > -
> > D:\Works\Python>py test.py -h
> > usage: test.py [-h] [--foo [FOO]] [--goo GOO]
> >
> > optional arguments:
> >   -h, --help   show this help message and exit
> >   --foo [FOO]  foo help
> >   --goo GOOgoo help
> >
> > D:\Works\Python>py test.py --foo 1 --goo 2
> > 1 ['2']
> > -
> >
> > It seems to me that the help message should be:
> > usage: test.py [-h] [--foo FOO] [--goo [GOO]]
> >
> > Do I had missed something?
> >
> 
> Can you elaborate on why you expect this? You've declared one of them
> to have a single mandatory argument, and the other a single optional
> argument. This corresponds to what I'm seeing.
> 
> ChrisA

So the square bracket means optional, not list? My misunderstanding:-(

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Does the argparse generate a wrong help message?

2019-12-27 Thread jfong
The codes in test.py are:
-
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', nargs='?', help='foo help')
parser.add_argument('--goo', nargs=1, help='goo help')  
args = parser.parse_args()
print(args.foo, args.goo)
-

But I get the following result:
-
D:\Works\Python>py test.py -h
usage: test.py [-h] [--foo [FOO]] [--goo GOO]

optional arguments:
  -h, --help   show this help message and exit
  --foo [FOO]  foo help
  --goo GOOgoo help

D:\Works\Python>py test.py --foo 1 --goo 2
1 ['2']
-

It seems to me that the help message should be:
usage: test.py [-h] [--foo FOO] [--goo [GOO]]

Do I had missed something?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: python 2 to 3 converter

2019-12-08 Thread jfong
Greg Ewing於 2019年12月9日星期一 UTC+8上午6時18分32秒寫道:
> On 8/12/19 9:30 pm, songbird wrote:
> >wouldn't it make more sense to just go back and fix the
> > converter program than to have to manually convert all this
> > python2 code?
> 
> Anything that isn't already fixed by 2to3 is probably
> somewhere between very difficult and impossible to fix
> using an automated process. It sounds like an interesting
> project, but be aware that it's probably an AI-complete
> problem.
> 
> -- 
> Greg

Even string is hard to be handled by the AI:-)

Quoted from https://portingguide.readthedocs.io/en/latest/strings.html
" ... This means that you need to go through the entire codebase, and decide 
which value is what type. Unfortunately, this process generally cannot be 
automated."

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How execute at least two python files at once when imported?

2019-11-06 Thread jfong
Igor Korot於 2019年11月7日星期四 UTC+8上午12時34分35秒寫道:
> Hi,
> 
> On Wed, Nov 6, 2019 at 10:22 AM Spencer Du  wrote:
> >
> > Hi
> >
> > Sorry if I haven't stated my requirements clearly.
> >
> > I just wanted a way to import at least two python files in parallel and I 
> > wanted to know how this can be done or a reason why its bad as stated in 
> > another post.
> 
> This is not a requirements.
> 
> Let me rephrase my question - what problem are you trying to solve?
> 
> Also, as I said before - I believe there is a language barrier.
> 
> Find some python forum in your native language and ask your question there.
> 
> Thank you.
> 
> >
> > Thanks
> > Spencer
> > --
> > https://mail.python.org/mailman/listinfo/python-list

If the OP is a Chinese, from my experience, I doubt there is a chance he can 
express his problem clearly enough for us who want to help to understand. There 
is not only the language barrier, but the causes of China education system. 
Starts from the very beginning in primary school, students are not allowed to 
think independently and logically. So after growing up, they just lost the 
ability of expressing things in a logic way.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the difference between running a script under command box and interpreter?

2019-11-04 Thread jfong
Grant Edwards於 2019年11月5日星期二 UTC+8上午12時41分24秒寫道:
> On 2019-11-04, Dennis Lee Bieber  wrote:
> > Using
> >
> >from module import *
> >
> > is often the worst thing one can do.
> 
> I agree 100%.
> 
> Unfortunately, most of the official standard library documentation is
> written assuming you do _exactly_that_.
> 
> Though it makes the documetnation more succinct, I think it encourages
> bad behavior and causes a lot of problems.
> 
> -- 
> Grant Edwards   grant.b.edwardsYow! I wonder if I could
>   at   ever get started in the
>   gmail.comcredit world?


I don't use this phrase in my files, but sometime I use it under REPL. 

I don't think it's bad showing in the document, at least it will teach someone 
who was bitten by this phrase something unique in Python:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the difference between running a script under command box and interpreter?

2019-11-03 Thread jfong
Chris Angelico於 2019年11月4日星期一 UTC+8上午10時19分50秒寫道:
> On Mon, Nov 4, 2019 at 1:01 PM  wrote:
> >
> > Chris Angelico於 2019年11月4日星期一 UTC+8上午8時43分07秒寫道:
> > > Ah, that's a fair point. If you specifically WANT that behaviour, what
> > > you can do is invoke the script interactively:
> > >
> > > python3 -i test.py
> > >
> > > That'll run the script as normal, and then drop you into the REPL. All
> > > your interactive globals *are* that module's globals.
> > >
> > > ChrisA
> >
> > It surprises me that REPL has essential different behavior in these two 
> > situations.
> >
> 
> Not really. In each case, the REPL lets you interactively execute code
> as part of a module. If you start with "-i somescript.py", it starts
> out by running the contents of that script; otherwise, you start with
> nothing (as if you ran "-i empty-file.py"). The REPL does the same
> thing every time; it's a difference between creating the functions
> directly and importing them.
> 
> ChrisA

I mean, taking this simple example:
---test.py---
def main():
print(rule)
if __name__ == '__main__:
rule = 1
main()
---

case 1:
py -i test.py
1
>>> globals()
>>> main.__globals__

case 2:
py
>>> from test import *
>>> globals()
>>> main.__globals__

The result is much different. In case 1, the REPL and the module seems in the 
same global space:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the difference between running a script under command box and interpreter?

2019-11-03 Thread jfong
Chris Angelico於 2019年11月4日星期一 UTC+8上午8時43分07秒寫道:
> On Mon, Nov 4, 2019 at 11:36 AM  wrote:
> >
> > Peter J. Holzer於 2019年11月4日星期一 UTC+8上午3時59分36秒寫道:
> > > On 2019-11-01 04:24:38 -0700, jf...@ms4.hinet.net wrote:
> > > > > The globals are your current module's namespace, and functions defines
> > > > > in a module are bound to that module's namespace.
> > > > >
> > > > > Strip your test.py back. A lot. Try this:
> > > > >
> > > > > def main():
> > > > >   print(rule)
> > > > >
> > > > > Now, let's use that:
> > > > >
> > > > > Python 3.7.4 (default, Sep 28 2019, 13:34:38)
> > > > > [Clang 8.0.0 (clang-800.0.42.1)] on darwin
> > > > > Type "help", "copyright", "credits" or "license" for more 
> > > > > information.
> > > > > >>> import test
> > > > > >>> test.main()
> > > > > Traceback (most recent call last):
> > > > >   File "", line 1, in 
> > > > >   File "/Users/cameron/tmp/d1/test.py", line 2, in main
> > > > > print(rule)
> > > > > NameError: name 'rule' is not defined
> > >
> > > [Explanation snipped]
> > >
> > > > I didn't noticed that the interpreter has its own globals. Thanks for 
> > > > reminding.
> > >
> > > It's not really "the interpreter" (I think you mean the REPL) which has
> > > it's own globals. Every module/file has its own globals.
> > >
> > > The same thing happens non-interactively:
> > >
> > > % cat test.py
> > > def main():
> > > print(rule)
> > >
> > > % cat foo.py
> > > #!/usr/bin/python3
> > >
> > > from test import *
> > >
> > > rule = 42
> > > main()
> > >
> > > % ./foo.py
> > > Traceback (most recent call last):
> > >   File "./foo.py", line 6, in 
> > > main()
> > >   File "/home/hjp/tmp/test.py", line 2, in main
> > > print(rule)
> > > NameError: name 'rule' is not defined
> > >
> > > The "rule" identifier in main() refers to a "rule" variable in the
> > > module test. If you set a variable "rule" somewhere else (in foo.py or
> > > the REPL, ...), that has no effect. How should python know that you want
> > > to set the rule variable in the test module?
> > >
> > >   hp
> > >
> > > --
> > >_  | Peter J. Holzer| Story must make more sense than reality.
> > > |_|_) ||
> > > | |   | h...@hjp.at |-- Charles Stross, "Creative writing
> > > __/   | http://www.hjp.at/ |   challenge!"
> >
> >
> > I innocently thought that when import module through "from test import *", 
> > I am working on test's globals under REPL. I didn't noticed the REPL has 
> > its own globals.
> >
> 
> Ah, that's a fair point. If you specifically WANT that behaviour, what
> you can do is invoke the script interactively:
> 
> python3 -i test.py
> 
> That'll run the script as normal, and then drop you into the REPL. All
> your interactive globals *are* that module's globals.
> 
> ChrisA

It surprises me that REPL has essential different behavior in these two 
situations.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the difference between running a script under command box and interpreter?

2019-11-03 Thread jfong
Peter J. Holzer於 2019年11月4日星期一 UTC+8上午3時59分36秒寫道:
> On 2019-11-01 04:24:38 -0700, jf...@ms4.hinet.net wrote:
> > > The globals are your current module's namespace, and functions defines 
> > > in a module are bound to that module's namespace.
> > > 
> > > Strip your test.py back. A lot. Try this:
> > > 
> > > def main():
> > >   print(rule)
> > > 
> > > Now, let's use that:
> > > 
> > > Python 3.7.4 (default, Sep 28 2019, 13:34:38)
> > > [Clang 8.0.0 (clang-800.0.42.1)] on darwin
> > > Type "help", "copyright", "credits" or "license" for more information.
> > > >>> import test
> > > >>> test.main()
> > > Traceback (most recent call last):
> > >   File "", line 1, in 
> > >   File "/Users/cameron/tmp/d1/test.py", line 2, in main
> > > print(rule)
> > > NameError: name 'rule' is not defined
> 
> [Explanation snipped]
> 
> > I didn't noticed that the interpreter has its own globals. Thanks for 
> > reminding.
> 
> It's not really "the interpreter" (I think you mean the REPL) which has
> it's own globals. Every module/file has its own globals.
> 
> The same thing happens non-interactively:
> 
> % cat test.py 
> def main():
> print(rule)
> 
> % cat foo.py 
> #!/usr/bin/python3
> 
> from test import *
> 
> rule = 42
> main()
> 
> % ./foo.py 
> Traceback (most recent call last):
>   File "./foo.py", line 6, in 
> main()
>   File "/home/hjp/tmp/test.py", line 2, in main
> print(rule)
> NameError: name 'rule' is not defined
> 
> The "rule" identifier in main() refers to a "rule" variable in the
> module test. If you set a variable "rule" somewhere else (in foo.py or
> the REPL, ...), that has no effect. How should python know that you want
> to set the rule variable in the test module?
> 
>   hp
> 
> -- 
>_  | Peter J. Holzer| Story must make more sense than reality.
> |_|_) ||
> | |   | h...@hjp.at |-- Charles Stross, "Creative writing
> __/   | http://www.hjp.at/ |   challenge!"


I innocently thought that when import module through "from test import *", I am 
working on test's globals under REPL. I didn't noticed the REPL has its own 
globals.

>>> How should python know that you want to set the rule variable in the test 
>>> module?

My 'wrong' answer will be, at the time I raised my question, that when import 
two different modules either has 'rule' variable, REPL will see the second 
imported one. No kidding:-) 

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the difference between running a script under command box and interpreter?

2019-11-01 Thread jfong
Cameron Simpson於 2019年11月1日星期五 UTC+8下午5時28分42秒寫道:
> On 31Oct2019 22:03, Jach Fong  wrote:
> >Cameron Simpson於 2019年11月1日星期五 UTC+8下午12時13分45秒寫道:
> >> On 31Oct2019 20:44, Jach Fong  wrote:
> >> >The script test.py is something like this:
> >> >---test.py
> >> >from pyeds import fsm
> >> >...
> >> >class Rule_Parse:
> >> >def __init__(self):
> >> >...
> >> >self.current_char = ''
> >> >...
> >> >def main(input_str):
> >> >for c in input_str:
> >> >...
> >> >rule.current_char = c
> >> >...
> >> >
> >> >if __name__ == '__main__':
> >> >input_str = '(NNS(acoustics) & RB(not)) | JJ(muted)'
> >> >rule = Rule_Parse()
> >> >main(input_str)
> >> >...
> >> >
> >> >---
> >> >The test.py can run correctly under command box:
> >> >D:\Works\Python\pyeds-master\src>py test.py
> >> >
> >> >but fails when running under interpreter:
> >> >D:\Works\Python\pyeds-master\src>py
> >> >Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 
> >> >bit (Intel)] on win32
> >> >Type "help", "copyright", "credits" or "license" for more information.
> >>  from test import *
> >>  input_str = "(NNS(acoustics) & RB(not)) | JJ(muted)"
> >>  rule = Rule_Parse()
> >>  main(input_str)
> >> >Traceback (most recent call last):
> >> >  File "", line 1, in 
> >> >  File "D:\Works\Python\pyeds-master\src\test.py", line 229, in main
> >> >rule.current_char = c
> >> >NameError: name 'rule' is not defined
> >> 
> >> >
> >> >I did check the globals using dir() and the 'rule' is there, no doubt.
> >>
> >> It matters how you checked this. This isn't apparent.
> [...]
> >Yes, the 'if' body is not executed when I import test.py under 
> >interpreter, that's why I manually execute them there.
> >What puzzles me is that the globals() has a 'rule' object in both 
> >cases. Why this one doesn't work?
> 
> I think I have misinterpreted what you've done.
> 
> The globals are your current module's namespace, and functions defines 
> in a module are bound to that module's namespace.
> 
> Strip your test.py back. A lot. Try this:
> 
> def main():
>   print(rule)
> 
> Now, let's use that:
> 
> Python 3.7.4 (default, Sep 28 2019, 13:34:38)
> [Clang 8.0.0 (clang-800.0.42.1)] on darwin
> Type "help", "copyright", "credits" or "license" for more information.
> >>> import test
> >>> test.main()
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "/Users/cameron/tmp/d1/test.py", line 2, in main
> print(rule)
> NameError: name 'rule' is not defined
> 
> What's happening here?
> 
> When we call main it tries to print "rule" from its module's globals.  
> 
> The first time you call it that doesn't exist, and we get your error.
> 
> Setting rule=1 in the interpreter's space doesn't help (the stuff below 
> if from the same session continued from above):
> 
> >>> rule=1
> >>> test.main()
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "/Users/cameron/tmp/d1/test.py", line 2, in main
> print(rule)
> NameError: name 'rule' is not defined
> 
> But if we define rule in the "test" module things improve:
> 
> >>> test.rule=2
> >>> test.main()
> 2
> 
> Importing main from test doesn't change where it looks for its globals:
> 
> >>> from test import main as my_main
> >>> my_main()
> 2
> 
> That value (2) is still coming out of the test module.
> 
> Cheers,
> Cameron Simpson 

I didn't noticed that the interpreter has its own globals. Thanks for reminding.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the difference between running a script under command box and interpreter?

2019-10-31 Thread jfong
Cameron Simpson於 2019年11月1日星期五 UTC+8下午12時13分45秒寫道:
> On 31Oct2019 20:44, Jach Fong  wrote:
> >The script test.py is something like this:
> >---test.py
> >from pyeds import fsm
> >...
> >...
> >class Rule_Parse:
> >def __init__(self):
> >...
> >self.current_char = ''
> >...
> >...
> >def main(input_str):
> >for c in input_str:
> >...
> >rule.current_char = c
> >...
> >
> >if __name__ == '__main__':
> >input_str = '(NNS(acoustics) & RB(not)) | JJ(muted)'
> >rule = Rule_Parse()
> >main(input_str)
> >...
> >
> >---
> >The test.py can run correctly under command box:
> >D:\Works\Python\pyeds-master\src>py test.py
> >
> >but fails when running under interpreter:
> >D:\Works\Python\pyeds-master\src>py
> >Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit 
> >(Intel)] on win32
> >Type "help", "copyright", "credits" or "license" for more information.
>  from test import *
>  input_str = "(NNS(acoustics) & RB(not)) | JJ(muted)"
>  rule = Rule_Parse()
>  main(input_str)
> >Traceback (most recent call last):
> >  File "", line 1, in 
> >  File "D:\Works\Python\pyeds-master\src\test.py", line 229, in main
> >rule.current_char = c
> >NameError: name 'rule' is not defined
> 
> >
> >I did check the globals using dir() and the 'rule' is there, no doubt.
> 
> It matters how you checked this. This isn't apparent.
> 
> >I also tried "py -m pdb test.py" and step through it, no problem too.
> 
> This:
>   py test.py
> and this:
>   py -m pdb test
> 
> both run test.py with __name__ set to "__main__" to indicate that 
> test.py is the main programme.
> 
> When you "import test", the module's __name__ is from the import 
> ("test") i.e. not the main programme.
> 
> The bottom of your module has an if statement whose body only runs when 
> this is the main programme.
> 
> The core issue is that the global "rule" is _only_ defined inside that 
> if statement.
> 
> You might set it unconditionally to None at the start of the file, but 
> that would only change the failure mode.
> 
> You might set it unconditionally to Rule_Parse() at the top of the file 
> but that pointlessly instantiates an instance of Rule_Parse which might 
> never be needed (maybe that is cheap, but many other classes are not).  
> The basic intent of an import is to define various classes and other 
> names, but _not_, generally, to create class instances and do 
> significant work.
> 
> This is really an example illustrating one reason why global variables 
> are considered things to avoid almost all of the time. Had main() 
> required "rule" as a parameter then it would not have been possible to 
> call it without at least providing a rule. The same applies with most 
> other functions: if they all require their external state via parameters 
> then you can't miss things out. (You can, of course, always pass 
> incorrect values, but that is usually easier to debug.)
> 
> Avoid globals; they are usually a source of bugs.
> 
> Cheers,
> Cameron Simpson 

Yes, the 'if' body is not executed when I import test.py under interpreter, 
that's why I manually execute them there.

What puzzles me is that the globals() has a 'rule' object in both cases. Why 
this one doesn't work?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


What's the difference between running a script under command box and interpreter?

2019-10-31 Thread jfong
The script test.py is something like this:
---test.py
from pyeds import fsm
...
...
class Rule_Parse:
def __init__(self):
...
self.current_char = ''
...
...
def main(input_str):
for c in input_str:
...
rule.current_char = c
...

if __name__ == '__main__':
input_str = '(NNS(acoustics) & RB(not)) | JJ(muted)'
rule = Rule_Parse()
main(input_str)
...

---
The test.py can run correctly under command box:
D:\Works\Python\pyeds-master\src>py test.py

but fails when running under interpreter:
D:\Works\Python\pyeds-master\src>py
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from test import *
>>> input_str = "(NNS(acoustics) & RB(not)) | JJ(muted)"
>>> rule = Rule_Parse()
>>> main(input_str)
Traceback (most recent call last):
  File "", line 1, in 
  File "D:\Works\Python\pyeds-master\src\test.py", line 229, in main
rule.current_char = c
NameError: name 'rule' is not defined
>>>

I did check the globals using dir() and the 'rule' is there, no doubt.
I also tried "py -m pdb test.py" and step through it, no problem too.

Why?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the purpose the hook method showing in a class definition?

2019-10-20 Thread jfong
Ian Hobson於 2019年10月20日星期日 UTC+8下午6時05分11秒寫道:
> Hi Jach,
> 
> On 20/10/2019 09:34, jf...@ms4.hinet.net wrote:
> > What puzzles me is how a parent's method foo() can find its child's method 
> > goo(), no matter it was overwrote or not? MRO won't explain this and I 
> > can't find document about it also:-(
> 
> This is a generalised description - Python may be slightly different.
> 
> When foo invokes goo the search for goo starts at the class of the 
> object (which is B), not the class of the executing method (i.e not A). 
> It then proceeds to look for goo up the class hierarchy - first in B, 
> then A then Object.
> 
> If that fails the RTS modifies the call, to look for a magic method, and 
> starts again at B. When the magic method is found in Object, you get the 
> "not found" error. If you implement the magic method in A or B it will 
> be run instead.
> 
> Regards
> 
> Ian
> 
> -- 
> This email has been checked for viruses by AVG.
> https://www.avg.com

I see. An obj.method will be resolved according to the MRO of the obj's class, 
no matter where it is located. Thank you.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's the purpose the hook method showing in a class definition?

2019-10-20 Thread jfong
Sibylle Koczian於 2019年10月20日星期日 UTC+8上午2時04分54秒寫道:
> Am 19.10.2019 um 13:11 schrieb jf...@ms4.hinet.net:
> > For the two examples below:
> > (1)
>  class A:
> > ... def foo(self):
> > ... self.goo()
> > ...
>  class B(A):
> > ... def goo(self):
> > ... print(1)
> > ...
> > 
> > (2)
>  class A:
> > ... def foo(self):
> > ... self.goo()
> > ... def goo(self): pass
> > ...
>  class B(A):
> > ... def goo(self):
> > ... print(1)
> > ...
> > 
> > Both can get the same result:
>  b = B()
>  b.foo()
> > 1
> 
> > 
> > What's the benefit of having the hook method goo() in class A in example 2?
> > 
> > --Jach
> > 
> None - as long as nobody tries one of those:
> 
> a = A()
> a.foo()
> 
> or
> 
> class C(A):
>  def foo(self):
>  super().foo()
>  print(2)
> 
> c = C()
> c.foo()

Yes, there will be an attribute error if no goo() was defined. 

What puzzles me is how a parent's method foo() can find its child's method 
goo(), no matter it was overwrote or not? MRO won't explain this and I can't 
find document about it also:-(

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


What's the purpose the hook method showing in a class definition?

2019-10-19 Thread jfong
For the two examples below:
(1)
>>> class A:
... def foo(self):
... self.goo()
...
>>> class B(A):
... def goo(self):
... print(1)
...

(2)
>>> class A:
... def foo(self):
... self.goo()
... def goo(self): pass
...
>>> class B(A):
... def goo(self):
... print(1)
...

Both can get the same result:
>>> b = B()
>>> b.foo()
1
>>>

What's the benefit of having the hook method goo() in class A in example 2?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to handle '-' in the 'from' part in a "from import" statement?

2019-10-08 Thread jfong
jf...@ms4.hinet.net於 2019年10月8日星期二 UTC+8上午10時45分36秒寫道:
> For example:
> from my-dir import test
> 
> I know it can be solved by renaming, but any alternative?
> 
> --Jach

Maybe another (better?) solution is:
import sys
sys.path.append(r'my-dir')
import test

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to handle '-' in the 'from' part in a "from import" statement?

2019-10-08 Thread jfong
dieter於 2019年10月8日星期二 UTC+8下午1時33分20秒寫道:
> jf...@ms4.hinet.net writes:
> > ...
> > But most of the download from Github has a directory named '-master' 
> > which causes a trouble sometimes.
> 
> Those are likely not meant to be imported directly.
> 
> Typically, you have a "setup" step which installs (in some way)
> a "distribution". This step usually ensures that you can use
> "normal" Python import syntax to access all associated packages.
> 
> The "setup" step is typically performed with
> "python setup.py develop" or "python setup.py install" --
> with the "distribution" providing the "setup.py".

Yes, I understand the normal procedure on using a package, but it's not always 
the case.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to handle '-' in the 'from' part in a "from import" statement?

2019-10-07 Thread jfong
DL Neil於 2019年10月8日星期二 UTC+8上午11時02分20秒寫道:
> On 8/10/19 3:45 PM, jf...@ms4.hinet.net wrote:
> > For example:
> > from my-dir import test
> > 
> > I know it can be solved by renaming, but any alternative?
> 
> 
> The manual is your friend:
> - import
> - importlib
> 
> (the latter allows modules to be identified by strings)
> 
> However, Pythons has naming rules. If you try to get around them, sooner 
> or later you'll 'forget' and trip yourself up. Recommend your first idea!
> -- 
> Regards =dn

Yes, I had noticed the naming rules. Thank you.

But most of the download from Github has a directory named '-master' which 
causes a trouble sometimes.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


How to handle '-' in the 'from' part in a "from import" statement?

2019-10-07 Thread jfong
For example:
from my-dir import test

I know it can be solved by renaming, but any alternative?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: exec and globals and locals ...

2019-09-20 Thread jfong
Peter Otten於 2019年9月20日星期五 UTC+8下午3時31分48秒寫道:
> jf...@ms4.hinet.net wrote:
> 
>  x = 3
>  def foo():
> > ... exec("print(globals(), locals()); x = x + 1; print(globals(),
> > locals())") ...
>  foo()
> > {'foo': , '__package__': None, '__builtins__':
> > {, '__loader__':  > {'_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__name__':
> > {'__main__', '__spec__': None, 'x': 3} {} 'foo':  > {0x021C3468>, '__package__': None, '__builtins__':  > {(built-in)>, '__loader__': ,
> > {'__doc__': None, '__name__': '__main__', '__spec__': None, 'x': 3} {'x':
> > {4}
>  def goo():
> > ... print(globals(), locals())
> > ... x = x + 1
> > ... print(globals(), locals())
> > ...
>  goo()
> > {'foo': , '__package__': None, '__builtins__':
> > {, '__loader__':  > {'_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__name__':
> > {'__main__', '__spec__': None, 'goo': , 'x':
> > {3} {}
> > Traceback (most recent call last):
> >   File "", line 1, in 
> >   File "", line 3, in goo
> > UnboundLocalError: local variable 'x' referenced before assignment
> 
> > 
> > Can't figure out what makes it different:-(
> 
> (0) exec() and class definitions use the LOAD_NAME opcode which looks into 
> the local namespace first and falls back to the global namespace. Therefore
> x = x may look up a global x and assign to a local one
> 
> The function body uses either 
> 
> (1) if there is a name binding operation (assignment, augmented assignment, 
> def, ...) LOAD_FAST which only looks into the local namespace. Thus
> x = x will only succeed if x is already defined in the local namespace.
> 
> (2) if there is no binding operation (name appears in an expression, x[...] 
> = ... or attribute assignment) LOAD_GLOBAL which only looks into the local 
> namespace.
> 
> Your first example is case 0, your second is case 1.

Hmm... exec() seems follow a more "LEGB" rule:-)

Thank you.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: exec and globals and locals ...

2019-09-19 Thread jfong
>>> x = 3
>>> def foo():
... exec("print(globals(), locals()); x = x + 1; print(globals(), 
locals())")
...
>>> foo()
{'foo': , '__package__': None, '__builtins__': 
, '__loader__': , '__doc__': None, '__name__': '__main__', 
'__spec__': None, 'x': 3} {}
{'foo': , '__package__': None, '__builtins__': 
, '__loader__': , '__doc__': None, '__name__': '__main__', 
'__spec__': None, 'x': 3} {'x': 4}
>>> def goo():
... print(globals(), locals())
... x = x + 1
... print(globals(), locals())
...
>>> goo()
{'foo': , '__package__': None, '__builtins__': 
, '__loader__': , '__doc__': None, '__name__': '__main__', 
'__spec__': None, 'goo': , 'x': 3} {}
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in goo
UnboundLocalError: local variable 'x' referenced before assignment
>>>

Can't figure out what makes it different:-(

--Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it 'fine' to instantiate a widget without parent parameter?

2019-09-10 Thread jfong
Terry Reedy於 2019年9月10日星期二 UTC+8下午5時16分19秒寫道:
> On 9/10/2019 12:02 AM, jf...@ms4.hinet.net wrote:
> 
> > Got it. The first Tk object is always the default one no matter where it 
> > was  created. The default one is always the one which the widget 
> > constructor refer to when required.
> 
> Or one can call tkinter.NoDefaultRoot() and not worry about default roots.
> 
> -- 
> Terry Jan Reedy

May I say this call has to be at the very beginning, before any widget was 
created using default root? And after this call, the 'parent' argument has to 
be explicitly assigned in the widget constructor?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to correctly use 'in_' argument in tkinter grid()?

2019-09-10 Thread jfong
Peter Otten於 2019年9月10日星期二 UTC+8下午5時04分27秒寫道:
> jf...@ms4.hinet.net wrote:
> 
> > I had tried the following script test.py:
> > 
> > import tkinter as tk
> > 
> > class Demo(tk.Frame):
> > def __init__(self):
> > tk.Frame.__init__(self, name='demo')
> > self.pack()
> > 
> > panel = tk.Frame(self, name='panel')
> > panel.pack()
> > 
> > start = tk.Button(text='Start', name='start')
> > start.grid(in_=panel)
> > 
> > btn = self.nametowidget('panel.start')
> > btn.config(state='disabled')
> > 
> > Demo().mainloop()
> > 
> > 
> > It fails on nametowidget() function. My intention is to use 'in_' to
> > change the parent of 'start' widget from the default Tk object to 'panel',
> > but failed with KeyError: 'start'.
> > 
> > below is part of the snapshot in pdb,
> > ...
> >> d:\works\python\test.py(11)__init__()
> > -> start = tk.Button(text='Start', name='start')
> > (Pdb) !panel.winfo_parent()
> > '.demo'
> > (Pdb) next
> >> d:\works\python\test.py(12)__init__()
> > -> start.grid(in_=panel)
> > (Pdb) !start.winfo_parent()
> > '.'
> > (Pdb) next
> >> d:\works\python\test.py(14)__init__()
> > -> btn = self.nametowidget('panel.start')
> > (Pdb) !start.winfo_parent()
> > '.'
> > 
> > --Jach
> 
> I think that the `in_` argument is used correctly. It's just that your 
> expectation that the name is changed to reflect the layout hierarchy is 
> wrong. 
> 
> To manipulate the start button you can use the `start` variable directly:
> 
> start.config(state='disabled')
> 
> To find all slaves of the panel use
> 
> panel.grid_slaves()
> 
> $ cat grid_in.py
> import tkinter as tk
> 
> class Demo(tk.Frame):
> def __init__(self):
> tk.Frame.__init__(self, name='demo')
> self.pack()
> 
> self.panel = panel = tk.Frame(self, name='panel')
> panel.pack()
> 
> start = tk.Button(text='Start', name='start')
> start.grid(in_=panel)
> 
> for btn in panel.grid_slaves():
> print("disabling", btn._w)
> btn.config(state='disabled')
> 
> Demo() #.mainloop()
> $ python3 grid_in.py 
> disabling .start
> $

Oh, I was misunderstanding the purpose of 'in_'. No wonder it's showing up in 
the .grid() manager:-) Thank you.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it 'fine' to instantiate a widget without parent parameter?

2019-09-09 Thread jfong
Terry Reedy於 2019年9月10日星期二 UTC+8上午11時43分05秒寫道:
> On 9/9/2019 8:30 PM, jf...@ms4.hinet.net wrote:
> > Terry Reedy於 2019年9月9日星期一 UTC+8下午3時06分27秒寫道:
> 
> >> There will only be one default Tk object, but there can be multiple Tk
> >> objects.
> 
>  import tkinter as tk
>  f0 = tk.Frame()
> 
> This causes creation of a default root
> 
>  root0 = tk.Tk()
> 
> This creates another, hence two different objects.
> 
>  f0.master
> > 
>  root0
> > 
> 
>  import tkinter as tk
>  root0 = tk.Tk()
> 
> This creates a root that is set as the default because there was not one 
> already.
> 
>  f0 = tk.Frame()
> 
> The uses the default root which is root0, hence 1 object.
> 
>  f0.master
> > 
>  root0
> > 
> 
> -- 
> Terry Jan Reedy

Got it. The first Tk object is always the default one no matter where it was  
created. The default one is always the one which the widget constructor refer 
to when required.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


How to correctly use 'in_' argument in tkinter grid()?

2019-09-09 Thread jfong
I had tried the following script test.py:

import tkinter as tk

class Demo(tk.Frame):
def __init__(self):
tk.Frame.__init__(self, name='demo')
self.pack()

panel = tk.Frame(self, name='panel')
panel.pack()

start = tk.Button(text='Start', name='start')
start.grid(in_=panel)

btn = self.nametowidget('panel.start')
btn.config(state='disabled')

Demo().mainloop()


It fails on nametowidget() function. My intention is to use 'in_' to change the 
parent of 'start' widget from the default Tk object to 'panel', but failed with 
KeyError: 'start'.

below is part of the snapshot in pdb,
...
> d:\works\python\test.py(11)__init__()
-> start = tk.Button(text='Start', name='start')
(Pdb) !panel.winfo_parent()
'.demo'
(Pdb) next
> d:\works\python\test.py(12)__init__()
-> start.grid(in_=panel)
(Pdb) !start.winfo_parent()
'.'
(Pdb) next
> d:\works\python\test.py(14)__init__()
-> btn = self.nametowidget('panel.start')
(Pdb) !start.winfo_parent()
'.'

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it 'fine' to instantiate a widget without parent parameter?

2019-09-09 Thread jfong
Terry Reedy於 2019年9月9日星期一 UTC+8下午3時06分27秒寫道:
> On 9/8/2019 8:40 PM, jf...@ms4.hinet.net wrote:
> 
> > Thank you. After a quick trace to find out the reason, I found that Tkinter 
> > prevents Tk() be called more than once from widget constructors, so only 
> > one Tk object exists:-)
> 
> There will only be one default Tk object, but there can be multiple Tk 
> objects.
> 
>  >>> import tkinter as tk
>  >>> r1 = tk.Tk()
>  >>> r2 = tk.Tk()
>  >>> r1.tk
> <_tkinter.tkapp object at 0x01F90F2F1D30>
>  >>> r2.tk
> <_tkinter.tkapp object at 0x01F90F328930>
> 
> 
> -- 
> Terry Jan Reedy

>>> import tkinter as tk
>>> f0 = tk.Frame()
>>> root0 = tk.Tk()
>>> f0.master

>>> root0

>>>

>>> import tkinter as tk
>>> root0 = tk.Tk()
>>> f0 = tk.Frame()
>>> f0.master

>>> root0

>>>

Why?

PS. Maybe there is no why, just it is what it is:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it 'fine' to instantiate a widget without parent parameter?

2019-09-08 Thread jfong
David於 2019年9月8日星期日 UTC+8下午8時14分03秒寫道:
> On Sun, 8 Sep 2019 at 21:05,  wrote:
> > David於 2019年9月8日星期日 UTC+8下午6時44分55秒寫道:
> > > On Sun, 8 Sep 2019 at 20:25,  wrote:
> 
> > > > If I have two widgets created this way:
> > > > t0 = tkinter.Text()
> > > > t1 = tkinter.Text()
> > > > How many Tk objects will there be?
> 
> > Sorry, didn't make it clear. I mean 
> 
> Sorry I didn't read more carefully.
> But I think that the method I demonstrated can give
> the answer to your question.
> 
> >>> import tkinter
> >>> t0 = tkinter.Text()
> >>> t1 = tkinter.Text()
> >>> t0.master
> 
> >>> t1.master
> 
> >>> t0.master is t1.master
> True
> >>>

Thank you. After a quick trace to find out the reason, I found that Tkinter 
prevents Tk() be called more than once from widget constructors, so only one Tk 
object exists:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it 'fine' to instantiate a widget without parent parameter?

2019-09-08 Thread jfong
David於 2019年9月8日星期日 UTC+8下午6時44分55秒寫道:
> On Sun, 8 Sep 2019 at 20:25,  wrote:
> >
> > If I have two widgets created this way:
> > t0 = tkinter.Text()
> > t1 = tkinter.Text()
> > How many Tk objects will there be?
> 
> $ python3
> Python 3.5.3 (default, Sep 27 2018, 17:25:39)
> [GCC 6.3.0 20170516] on linux
> Type "help", "copyright", "credits" or "license" for more information.
> >>> import tkinter
> >>> t0 = tkinter.Text()
> >>> t1 = tkinter.Text()
> >>> t0 is t1
> False
> >>> t0
> 
> >>> t1
> 
> >>>

Sorry, didn't make it clear. I mean  

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it 'fine' to instantiate a widget without parent parameter?

2019-09-08 Thread jfong
Terry Reedy於 2019年9月8日星期日 UTC+8下午5時31分34秒寫道:
> On 9/7/2019 9:44 PM, jf...@ms4.hinet.net wrote:
> > I know it is valid, according to the Tkinter source, every widget 
> > constructor has a 'master=None' default. What happens on doing this?
> 
> Tkinter creates a default Tk object and uses that as the master.
> 
>  >>> t = tkinter.Text()
>  >>> t.master
> 
> 
> > In what circumstance, we do it this way? and will it cause any trouble?
> 
> I believe it is OK if you always do it that way within a single 
> application.  But I prefer to have an explicit reference and use that 
> for .after calls and some others.
> 
> 
> -- 
> Terry Jan Reedy

If I have two widgets created this way:
t0 = tkinter.Text()
t1 = tkinter.Text()
How many Tk objects will there be?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Is it 'fine' to instantiate a widget without parent parameter?

2019-09-07 Thread jfong
I know it is valid, according to the Tkinter source, every widget constructor 
has a 'master=None' default. What happens on doing this? In what circumstance, 
we do it this way? and will it cause any trouble?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to record the console's content in the interpreter?

2019-08-23 Thread jfong
eryk sun於 2019年8月24日星期六 UTC+8上午2時53分56秒寫道:
> On 8/23/19, jf...@ms4.hinet.net  wrote:
> >
> > it won't show output from print command, and "print" is the most
> > command used in a module when a response was needed
> 
> ConEmu is an alternate console for Windows that allows logging all
> console output to a file:
> 
> https://conemu.github.io/en/AnsiLogFiles.html

Thank you for introducing this alternate console for Windows. I have downloaded 
the portable version and will give it a try soon.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to record the console's content in the interpreter?

2019-08-23 Thread jfong
Terry Reedy於 2019年8月23日星期五 UTC+8下午7時27分50秒寫道:
> On 8/23/2019 3:42 AM, jf...@ms4.hinet.net wrote:
> 
> > Say I like to record everything showing in the console into a file
> > after I start a debug session, and stop it when finished. It's not
> > a console redirection. I still need to see what is going on during
> > the session.
> 
> > After a quick try on IPython 6.5.0, I saw only the commands I had typed, 
> > not include the output of those commands:-(
> 
> IDLE saves exactly what you see in the window, including with a shell 
> session.  One can also select and paste into a new editor window and 
> then save.
> 
> 
> 
> -- 
> Terry Jan Reedy

IDLE is the closest one to the command console I currently use. The mouse used 
in its shell really helps on my requirement:-) Thank you for reminding.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to record the console's content in the interpreter?

2019-08-23 Thread jfong
Manfred Lotz於 2019年8月23日星期五 UTC+8下午6時08分11秒寫道:
> On Fri, 23 Aug 2019 00:42:26 -0700 (PDT)
> jf...@ms4.hinet.net wrote:
> 
> > Manfred Lotz於 2019年8月23日星期五 UTC+8下午2時58分48秒寫道:
> > > On Thu, 22 Aug 2019 21:48:33 -0700 (PDT)
> > > jf...@ms4.hinet.net wrote:
> > >   
> > > > Cameron Simpson於 2019年8月23日星期五
> > > > UTC+8下午12時09分54秒寫道:  
> > > > > On 22Aug2019 19:38, Jach Fong  wrote:
> > > > > >Say I like to record everything showing in the console into a
> > > > > >file after I start a debug session, and stop it when finished.
> > > > > >It's not a console redirection. I still need to see what is
> > > > > >going on during the session.
> > > > > 
> > > > > If you're in a terminal you can run the 'script" command. This
> > > > > starts a new shell inside a session which records itself to the
> > > > > file "typescript" (by default). See "man script" for further
> > > > > details.
> > > > > 
> > > > > Cheers,
> > > > > Cameron Simpson 
> > > > 
> > > > Mine is Windows:-( No 'script' command?
> > > > 
> > > > --Jach  
> > > 
> > > If I understand you correctly you want to save an interactive
> > > session!?
> > > 
> > > Then you could use ipython. In ipython the lines get numbererd. If
> > > your last line is, for example: In [100] you could do this:
> > > 
> > > save mysave 1-100
> > > 
> > > in the ipython shell.
> > > 
> > > -- 
> > > Manfred  
> > 
> > After a quick try on IPython 6.5.0, I saw only the commands I had
> > typed, not include the output of those commands:-(
> > 
> 
> Sorry, that's true.
> 
> I found only this. After starting ipython type:
> 
> %logstart -o
> 
> Then you get also command output. The log file name is: ipython_log.py
> 
> But it doesn't seem to show output from print command.
> 
> 
> -- 
> Manfred

You are right, it won't show output from print command, and "print" is the most 
command used in a module when a response was needed for the user:-(

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to record the console's content in the interpreter?

2019-08-23 Thread jfong
Manfred Lotz於 2019年8月23日星期五 UTC+8下午2時58分48秒寫道:
> On Thu, 22 Aug 2019 21:48:33 -0700 (PDT)
> jf...@ms4.hinet.net wrote:
> 
> > Cameron Simpson於 2019年8月23日星期五 UTC+8下午12時09分54秒寫道:
> > > On 22Aug2019 19:38, Jach Fong  wrote:  
> > > >Say I like to record everything showing in the console into a file
> > > >after I start a debug session, and stop it when finished. It's not
> > > >a console redirection. I still need to see what is going on during
> > > >the session.  
> > > 
> > > If you're in a terminal you can run the 'script" command. This
> > > starts a new shell inside a session which records itself to the
> > > file "typescript" (by default). See "man script" for further
> > > details.
> > > 
> > > Cheers,
> > > Cameron Simpson   
> > 
> > Mine is Windows:-( No 'script' command?
> > 
> > --Jach
> 
> If I understand you correctly you want to save an interactive session!?
> 
> Then you could use ipython. In ipython the lines get numbererd. If your
> last line is, for example: In [100] you could do this:
> 
> save mysave 1-100
> 
> in the ipython shell.
> 
> -- 
> Manfred

After a quick try on IPython 6.5.0, I saw only the commands I had typed, not 
include the output of those commands:-(

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to record the console's content in the interpreter?

2019-08-22 Thread jfong
Cameron Simpson於 2019年8月23日星期五 UTC+8下午12時09分54秒寫道:
> On 22Aug2019 19:38, Jach Fong  wrote:
> >Say I like to record everything showing in the console into a file
> >after I start a debug session, and stop it when finished. It's not
> >a console redirection. I still need to see what is going on during
> >the session.
> 
> If you're in a terminal you can run the 'script" command. This starts a 
> new shell inside a session which records itself to the file "typescript" 
> (by default). See "man script" for further details.
> 
> Cheers,
> Cameron Simpson 

Mine is Windows:-( No 'script' command?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


How to record the console's content in the interpreter?

2019-08-22 Thread jfong
Say I like to record everything showing in the console into a file after I 
start a debug session, and stop it when finished. It's not a console 
redirection. I still need to see what is going on during the session.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Which editor is suited for view a python package's source?

2019-08-20 Thread jfong
Nick Sarbicki於 2019年8月20日星期二 UTC+8下午1時33分32秒寫道:
> Yes the community edition works fine.
> 
> It seems to require a 64 bit version of Windows 7 or higher (I'm not sure
> as I haven't used Windows in years).
> 
> On Tue, 20 Aug 2019, 03:27 ,  wrote:
> 
> > Nick Sarbicki於 2019年8月19日星期一 UTC+8下午5時33分27秒寫道:
> > > PyCharm takes you to the source code within the editor for any
> > > variables/functions/classes/modules if you ctrl+click on what you want to
> > > see. It allows you to browse the relevant bits of code quickly, as well
> > as
> > > let you change them in your local environment if need be.
> > >
> > > That way you don't have to download the source separately, you can just
> > use
> > > it as a normal dependency.
> > >
> > > But if you want to view the source of a project in isolation I imagine
> > any
> > > common editor will suffice. Personally I'll tend to look where the source
> > > is hosted (GitHub, GitLab etc) instead of downloading it. But I can
> > > understand why some may not trust this.
> > >
> > > On Mon, 19 Aug 2019, 10:17 ,  wrote:
> > >
> > > > I like to download one package's source and study it in an editor. It
> > > > allows me to open the whole package as a project and let me jump from a
> > > > reference in one file to its definition in another file back and
> > forth. It
> > > > will be even better if it can handle the import modules too. (Maybe
> > this is
> > > > too much:-)
> > > >
> > > > Can anyone recommend such a tool?
> > > >
> > > > --Jach
> > > > --
> > > > https://mail.python.org/mailman/listinfo/python-list
> > > >
> >
> > There is a free community version of PyCharm. Will it support the
> > cross-reference of viewing different files in different subdirectory? and
> > what Windows versions it requires?
> >
> > --Jach
> > --
> > https://mail.python.org/mailman/listinfo/python-list
> >

Then, I can only download the older version 2016.2.3 for my old 32 bit 
system:-( 

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Which editor is suited for view a python package's source?

2019-08-19 Thread jfong
Nick Sarbicki於 2019年8月19日星期一 UTC+8下午5時33分27秒寫道:
> PyCharm takes you to the source code within the editor for any
> variables/functions/classes/modules if you ctrl+click on what you want to
> see. It allows you to browse the relevant bits of code quickly, as well as
> let you change them in your local environment if need be.
> 
> That way you don't have to download the source separately, you can just use
> it as a normal dependency.
> 
> But if you want to view the source of a project in isolation I imagine any
> common editor will suffice. Personally I'll tend to look where the source
> is hosted (GitHub, GitLab etc) instead of downloading it. But I can
> understand why some may not trust this.
> 
> On Mon, 19 Aug 2019, 10:17 ,  wrote:
> 
> > I like to download one package's source and study it in an editor. It
> > allows me to open the whole package as a project and let me jump from a
> > reference in one file to its definition in another file back and forth. It
> > will be even better if it can handle the import modules too. (Maybe this is
> > too much:-)
> >
> > Can anyone recommend such a tool?
> >
> > --Jach
> > --
> > https://mail.python.org/mailman/listinfo/python-list
> >

There is a free community version of PyCharm. Will it support the 
cross-reference of viewing different files in different subdirectory? and what 
Windows versions it requires? 

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Which editor is suited for view a python package's source?

2019-08-19 Thread jfong
I like to download one package's source and study it in an editor. It allows me 
to open the whole package as a project and let me jump from a reference in one 
file to its definition in another file back and forth. It will be even better 
if it can handle the import modules too. (Maybe this is too much:-)

Can anyone recommend such a tool?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a simple way to wrap a built-in function for the whole package?

2019-08-02 Thread jfong
Batuhan Taskaya於 2019年8月3日星期六 UTC+8上午5時27分49秒寫道:
> functools.partial is a better option
> 
> On Fri, Aug 2, 2019, 1:25 AM Cameron Simpson  wrote:
> 
> > On 31Jul2019 19:16, Jach Fong  wrote:
> > >I get a package from Pypi. The package has many modules using built-in
> > open() function. I like to redefine all the open() there with the default
> > encoding 'utf-8', but not for code outside the package. Maybe I can put my
> > def statement at the beginning of every module of this package, but just
> > wondering is there a simple way of doing it?
> >
> > I would define something like this in the __init__.py file of the
> > package (or in some utils.py file in the package):
> >
> >   def open8(path):
> > return open(path, encoding='utf-8')
> >
> > and just:
> >
> >   from . import open8
> >
> > and use "open8" throughout the code instead of "open"?
> >
> > What not alias "open"? Because I would want it evident that in this code
> > we're doing a slightly special flavour of open. By using a distinct name
> > I avoid confusion about the unusual semantics.
> >
> > Cheers,
> > Cameron Simpson 
> > --
> > https://mail.python.org/mailman/listinfo/python-list
> >

Totally agree:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a simple way to wrap a built-in function for the whole package?

2019-08-01 Thread jfong
Cameron Simpson於 2019年8月2日星期五 UTC+8上午6時25分00秒寫道:
> On 31Jul2019 19:16, Jach Fong  wrote:
> >I get a package from Pypi. The package has many modules using built-in 
> >open() function. I like to redefine all the open() there with the default 
> >encoding 'utf-8', but not for code outside the package. Maybe I can put my 
> >def statement at the beginning of every module of this package, but just 
> >wondering is there a simple way of doing it?
> 
> I would define something like this in the __init__.py file of the 
> package (or in some utils.py file in the package):
> 
>   def open8(path):
> return open(path, encoding='utf-8')
> 
> and just:
> 
>   from . import open8
> 
> and use "open8" throughout the code instead of "open"?
> 
> What not alias "open"? Because I would want it evident that in this code 
> we're doing a slightly special flavour of open. By using a distinct name 
> I avoid confusion about the unusual semantics.
> 
> Cheers,
> Cameron Simpson 

Instead of changing open() to open8() throughout the code, I prefer change it  
directly to open(encoding='utf-8'). Anyway, using "from . import open" is a 
good idea, thank you.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Is there a simple way to wrap a built-in function for the whole package?

2019-07-31 Thread jfong
I get a package from Pypi. The package has many modules using built-in open() 
function. I like to redefine all the open() there with the default encoding 
'utf-8', but not for code outside the package. Maybe I can put my def statement 
at the beginning of every module of this package, but just wondering is there a 
simple way of doing it?

Best Regards,
Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-07 Thread jfong
eryk sun於 2019年7月7日星期日 UTC+8下午3時51分57秒寫道:
> On 7/6/19, jf...@ms4.hinet.net  wrote:
> >
> > I turn off the anti-virus and tried v3.6.8, get the same result. Usually the
> > anti-virus program will warn me if something was blocked.
> 
> In case the executable is corrupt, clear your browser cache and
> download the 32-bit version again:
> 
> https://www.python.org/ftp/python/3.6.8/python-3.6.8.exe
> 
> Try to run the installer from an elevated command prompt. If it fails
> to run, check again for log files in your %TEMP% directory, which
> typically expands to "C:\Users\\AppData\Local\Temp".
> 
> If the installer is still not running -- not even enough to create a
> single log file -- then apparently something is configured incorrectly
> or missing on your computer that's causing it to fail hard. I'd have
> to run it under a debugger to find the cause.
> 
> Anyway, if you're stuck with ancient 3.4, you can at least install
> "pywin32-221.win32-py3.4.exe" from the old SourceForge repo:
> 
> https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221

I had overlooked your suggestion of installing it under elevated command 
prompt. At the last moment I was noticed and gave it a try. Guess what? I run 
Python-3.6.8.exe successfully and installed it. A real surprise!

Thank you for everything you had done to help.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-07 Thread jfong
eryk sun於 2019年7月7日星期日 UTC+8下午3時51分57秒寫道:
> On 7/6/19, jf...@ms4.hinet.net  wrote:
> >
> > I turn off the anti-virus and tried v3.6.8, get the same result. Usually the
> > anti-virus program will warn me if something was blocked.
> 
> In case the executable is corrupt, clear your browser cache and
> download the 32-bit version again:

I have its MD5 checked after each download.
 
> https://www.python.org/ftp/python/3.6.8/python-3.6.8.exe
>
> Try to run the installer from an elevated command prompt. If it fails
> to run, check again for log files in your %TEMP% directory, which
> typically expands to "C:\Users\\AppData\Local\Temp".
> 
> If the installer is still not running -- not even enough to create a
> single log file -- then apparently something is configured incorrectly
> or missing on your computer that's causing it to fail hard. I'd have
> to run it under a debugger to find the cause.

It's very possible there is some problem in my system. A few months ago  
suddenly I can't login to my email account through ThunderBird. Now I have to 
remove my password from its settings and manually type-in every time when I log 
in.

Using a debugger is a big burden to me because I am not familiar with the 
internal of Windows well.

> Anyway, if you're stuck with ancient 3.4, you can at least install
> "pywin32-221.win32-py3.4.exe" from the old SourceForge repo:
> 
> https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221

Thank you for the link. I will try it later and hope it will run:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-06 Thread jfong
eryk sun於 2019年7月7日星期日 UTC+8下午12時00分47秒寫道:
> On 7/6/19, jf...@ms4.hinet.net  wrote:
> >
> > In TEMP, there is only one file "chrome_installer.log" dated at the time of
> > doing the upgrade (strange?, why chrome?). No errors in it.
> 
> So the installer doesn't even execute. Do you maybe have an
> anti-malware program that's blocking its execution?  Definitely try
> the 3.6.8 installer. I didn't pay attention to the fact that you were
> trying to install a very outdated version of 3.6. There may have been
> bugs in the installer that were fixed. Always use the most recent
> version possible.

I turn off the anti-virus and tried v3.6.8, get the same result. Usually the 
anti-virus program will warn me if something was blocked.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-06 Thread jfong
eryk sun於 2019年7月7日星期日 UTC+8上午10時13分34秒寫道:
> On 7/6/19, jf...@ms4.hinet.net  wrote:
> >
> > According to the info you give, I have done the following steps:
> > 1. Upgrade to SP2 first.
> > 2. Install the CRT update.
> > But the result is still the same, nothing happens after double click the
> > file python-3.6.1.exe.
> 
> Did you reboot after installing the updates? Afterward, did you
> confirm in the system properties that you're running SP2? Did you
> check that "%SystemRoot%\System32\ucrtbase.dll" exists, plus a bunch
> of "api-ms-win-crt-*.dll" DLLs in the same directory?
> 
> > I deeply appreciate your help. It looks like that Vista has to live with
> > Python 3.4 for its rest of life:-)
> 
> That is not true in general for Vista. It's particular to your
> computer. Check the installer logs in your %TEMP% directory for
> errors, which will typically be an HRESULT error code that starts with
> 0x8, such as 0x80070002.
> 
> Try downloading and installing the 64-bit version:
> 
> https://www.python.org/ftp/python/3.6.8/python-3.6.8-amd64.exe

Yes, it's SP2 showing up in Start->Computer->Properities window. Also in 
System32 directory, there is ucrtbase.dll and a bunch of api-ms-win-crt-*.dll 
too.

In TEMP, there is only one file "chrome_installer.log" dated at the time of 
doing the upgrade (strange?, why chrome?). No errors in it.

I can't. My Vista is 32bit. Anyway I will give v3.6.8 a try later.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-06 Thread jfong
eryk sun於 2019年7月6日星期六 UTC+8下午6時26分42秒寫道:
> On 7/6/19, jf...@ms4.hinet.net  wrote:
> > eryk sun於 2019年7月6日星期六 UTC+8下午2時13分23秒寫道:
> >
> >> Major versions of Python support Windows versions that have extended
> >> support from Microsoft at the time of the first release. For Vista,
> >> extended support ended on 2017-04-11. Python 3.6 was released on
> >> 2016-12-23, so it supports Vista. Python 3.7, on the other hand, does
> >> not because it was released on 2018-06-27.
> >
> > I tried the python-3.6.1.exe, downloaded from www.python.org. Its
> > release date is March 21, 2017. But it doesn't run, Vista has no response at
> > all.
> 
> Starting with version 3.5, Python requires the Universal C Runtime,
> which is an OS component that was introduced in Windows 10 and
> backported to previous versions, including Windows Vista (service pack
> 2). Python's installer should attempt to install the CRT update, but
> from what I've seen this isn't reliable.
> 
> Ideally, it shouldn't be necessary to manually install the CRT update
> since Windows Update includes it. Enable optional updates, and keep
> your system updated. That said, if you can't or won't use Windows
> Update, then you can download and install standalone updates.
> 
> CRT Update
> https://support.microsoft.com/en-us/help/3118401
> 
> The above requires Vista service pack 2 (SP2). The system properties
> dialog should say whether SP1 or SP2 is installed. Your system should
> be running SP2 if Windows Update is enabled. If you're not even
> running SP1, you'll have to install SP1 and then SP2. The system
> properties dialog will tell you whether you're running 32-bit or
> 64-bit Windows.
> 
> x86 32-bit SP1
> https://www.microsoft.com/en-us/download/details.aspx?id=30
> x64 64-bit SP2
> https://www.microsoft.com/en-us/download/details.aspx?id=21299
> 
> x86 32-bit SP2
> https://www.microsoft.com/en-us/download/details.aspx?id=16468
> x64 64-bit SP2
> https://www.microsoft.com/en-us/download/details.aspx?id=17669

According to the info you give, I have done the following steps:
1. Upgrade to SP2 first.
2. Install the CRT update.
But the result is still the same, nothing happens after double click the file 
python-3.6.1.exe.

I deeply appreciate your help. It looks like that Vista has to live with Python 
3.4 for its rest of life:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-06 Thread jfong
Michael Torrie於 2019年7月6日星期六 UTC+8下午12時02分02秒寫道:
> On 07/05/2019 09:03 PM, jf...@ms4.hinet.net wrote:
> > From Vista to Win10? That's a three generation gap! Buy a new PC might 
> > be a better solution:-)
> 
> Maybe.  Windows 10 would probably run okay on that machine. It might be
> 10 years old, but if it's 64-bit, Win 10 should run on it.
> 
> You could also buy a hard drive and download the ISO from Microsoft and
> give it a try.  If it works you can buy the license for it (sigh).
> 
> Of course there are also other good alternatives too.

Thank you for your suggestion. This PC was purchased in year 2006 from Dell. 
The CPU is AMD Athlon 64 X2 4000+. I doubt Win10 will support such an old 
CPU:-) and the chipset driver might be a big problem too.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-06 Thread jfong
eryk sun於 2019年7月6日星期六 UTC+8下午2時13分23秒寫道:
> On 7/5/19, jf...@ms4.hinet.net  wrote:
> > Terry Reedy於 2019年7月5日星期五 UTC+8上午12時13分25秒寫道:
> >
> >> Upgrade to 3.7 or 3.8 to get hundreds of bug fixes, let alone new
> >> features.  Both subprocess and multiprocessing have gotten fixes.
> >
> > I can't because my OS is Vista and v3.4 is the last it can run:-( Also
> > the pywin32 can't be installed for it requires v3.5 and up.
> 
> Major versions of Python support Windows versions that have extended
> support from Microsoft at the time of the first release. For Vista,
> extended support ended on 2017-04-11. Python 3.6 was released on
> 2016-12-23, so it supports Vista. Python 3.7, on the other hand, does
> not because it was released on 2018-06-27.

I tried the python-3.6.1.exe, downloaded from www.python.org. Its release 
date is March 21, 2017. But it doesn't run, Vista has no response at all.

--Jach

> Windows 7 has extended support until 2020-01-14, so 3.8 supports it.
> However, system update KB2533623 is required for enhancements to the
> system loader that 3.8 depends on for loading extension modules and
> DLLs.
> 
> > I finally get a solution to switch between two notepads in Python. Here
> > is the codes for someone he may be interested.
> 
> If I have time I'll write a better version since the code you have is
> fragile. But I think you should take others' advice to use a
> cross-platform GUI automation library, so you won't be locked into a
> Windows-only solution.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-05 Thread jfong
Chris Angelico於 2019年7月6日星期六 UTC+8上午10時48分10秒寫道:
> On Sat, Jul 6, 2019 at 12:31 PM  wrote:
> >
> > Terry Reedy於 2019年7月5日星期五 UTC+8上午12時13分25秒寫道:
> > > On 7/3/2019 7:57 PM, jf...@ms4.hinet.net wrote:
> > > > I have the test0.py below. I expect to see 'abcd' showing in the 
> > > > notepad window:
> > > > -
> > > > import subprocess as sp
> > > > p0 = sp.Popen('notepad.exe', stdin=sp.PIPE)
> > > > p0.communicate(input=b'abcd')
> > > > -
> > > > But nothing happens. The notepad is completely empty. What have I 
> > > > missed?
> > > >
> > > > --Jach
> > > >
> > > > PS. I am using python 3.4 on Windows Vista
> > >
> > > Upgrade to 3.7 or 3.8 to get hundreds of bug fixes, let alone new
> > > features.  Both subprocess and multiprocessing have gotten fixes.
> >
> > I can't because my OS is Vista and v3.4 is the last it can run:-( Also 
> > the pywin32 can't be installed for it requires v3.5 and up.
> >
> 
> So... upgrade to a better operating system?
> 
> ChrisA

From Vista to Win10? That's a three generation gap! Buy a new PC might be a 
better solution:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-05 Thread jfong
Terry Reedy於 2019年7月5日星期五 UTC+8上午12時13分25秒寫道:
> On 7/3/2019 7:57 PM, jf...@ms4.hinet.net wrote:
> > I have the test0.py below. I expect to see 'abcd' showing in the notepad 
> > window:
> > -
> > import subprocess as sp
> > p0 = sp.Popen('notepad.exe', stdin=sp.PIPE)
> > p0.communicate(input=b'abcd')
> > -
> > But nothing happens. The notepad is completely empty. What have I missed?
> > 
> > --Jach
> > 
> > PS. I am using python 3.4 on Windows Vista
> 
> Upgrade to 3.7 or 3.8 to get hundreds of bug fixes, let alone new 
> features.  Both subprocess and multiprocessing have gotten fixes.

I can't because my OS is Vista and v3.4 is the last it can run:-( Also the 
pywin32 can't be installed for it requires v3.5 and up.

> subprocess is meant for running an external program in batch mode.  It 
> receives the one input byte string, sends output, and closes.  For 
> interaction, try multiprocessing.
> 
> Or do what IDLE does, which is to open a two-way socket to the parent 
> program.  (Managing this is not fun.)  IDLE was initially written before 
> multiprocessing.  It has been suggested to me that it should switch to 
> multiprocessing.  (But last I read, multiprocessing and tkinter (tcl/tk) 
> do not play well together on macOS.)

Can multiprocessing make debugging of eventloop app easier?

> If the subprocess runs a gui, the user should be able to switch focus by 
> clicking on a subprocess window.

I finally get a solution to switch between two notepads in Python. Here is 
the codes for someone he may be interested.
---
import subprocess, time, ctypes
user32 = ctypes.windll.user32

p0 = subprocess.Popen('notepad.exe')
time.sleep(1)
handle0 = user32.GetForegroundWindow()  # the handler of foreground window
thread0 = user32.GetWindowThreadProcessId(handle0, 0)  # get its thread id

p1 = subprocess.Popen('notepad.exe')
time.sleep(1)
handle1 = user32.GetForegroundWindow()
thread1 = user32.GetWindowThreadProcessId(handle1, 0)

for i in range(3):  # suppose the notepad1 is the foreground window
time.sleep(5)  # delay enough time for typing test
user32.AttachThreadInput(thread1, thread0, True)
user32.SetForegroundWindow(handle0)
time.sleep(5)
user32.AttachThreadInput(thread0, thread1, True)
user32.SetForegroundWindow(handle1)
print('end')

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-03 Thread jfong
Wildman於 2019年7月4日星期四 UTC+8上午11時15分57秒寫道:
> On Thu, 04 Jul 2019 10:36:36 +1000, Cameron Simpson wrote:
> 
> > On 03Jul2019 16:57, Jach Fong  wrote:
> >>I have the test0.py below. I expect to see 'abcd' showing in the notepad 
> >>window:
> >>-
> >>import subprocess as sp
> >>p0 = sp.Popen('notepad.exe', stdin=sp.PIPE)
> >>p0.communicate(input=b'abcd')
> >>-
> >>But nothing happens. The notepad is completely empty. What have I missed?
> >>--Jach
> >>
> >>PS. I am using python 3.4 on Windows Vista
> > 
> > Well I am not a Windows person, but in most GUI environments a desktop 
> > app such as Notepad does not read from its standard input - it reads 
> > keyboard stuff though the GUI interface instead. So it is ignoring your 
> > input data - this approach will generally fail with any desktop app on 
> > any platform.
> > 
> > You may need to investigate generating synthetic keystrokes somehow.
> > 
> > Or alternatively write your data to a text file and hand the name of the 
> > text file to notepad as a file to edit.
> > 
> > Cheers,
> > Cameron Simpson 
> 
> I block googlegroups so I don't see the original post.  I am
> talking to the OP.
> 
> Take a look at the SendKeys module.
> 
> https://pypi.org/project/SendKeys/
> 
> -- 
>  GNU/Linux user #557453
> The cow died so I don't need your bull!

Thank you. But the download there seems is for Python 2.7?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What's wrong on using Popen's communicate method?

2019-07-03 Thread jfong
Chris Angelico於 2019年7月4日星期四 UTC+8上午8時37分13秒寫道:
> On Thu, Jul 4, 2019 at 10:01 AM  wrote:
> >
> > I have the test0.py below. I expect to see 'abcd' showing in the notepad 
> > window:
> > -
> > import subprocess as sp
> > p0 = sp.Popen('notepad.exe', stdin=sp.PIPE)
> > p0.communicate(input=b'abcd')
> > -
> > But nothing happens. The notepad is completely empty. What have I missed?
> >
> 
> The "communicate" method sends text to the standard input pipe. This
> has nothing to do with the GUI, and most Windows GUI programs take no
> notice of it. You'll need something GUI-aware for this.
> 
> Is Notepad just an example, or are you actually trying to control MS Notepad?
> 
> ChrisA

Yes, the notepad is just an example. My real attempt is to operate the external 
programs through Python. I know there are some "keyboard simulation" packages 
in Pypi which may work on this situation. But I prefer not bother to install 
them if Python's build-ins can do it.

By the way, after Popen invokes an external program, is there a way of making 
it on-foucs when there are multiple Popen instances?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


What's wrong on using Popen's communicate method?

2019-07-03 Thread jfong
I have the test0.py below. I expect to see 'abcd' showing in the notepad window:
-
import subprocess as sp
p0 = sp.Popen('notepad.exe', stdin=sp.PIPE)
p0.communicate(input=b'abcd')
-
But nothing happens. The notepad is completely empty. What have I missed?

--Jach

PS. I am using python 3.4 on Windows Vista
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Which curses version should I use under Windows

2019-06-18 Thread jfong
MRAB於 2019年6月18日星期二 UTC+8下午6時12分50秒寫道:
> On 2019-06-18 04:57, jf...@ms4.hinet.net wrote:
> > Terry Reedy於 2019年6月18日星期二 UTC+8上午11時03分00秒寫道:
> >> On 6/17/2019 10:54 PM, jf...@ms4.hinet.net wrote:
> >> 
> >> > c:\Works\Python34>pip install windows-curses
> >> > DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be 
> >> > the last one supporting it. Please upgrade your Python as Python 3.4 w
> >> > on't be maintained after March 2019 (cf PEP 429).
> >> > Collecting windows-curses
> >> >ERROR: Could not find a version that satisfies the requirement 
> >> > windows-curses (from versions: none)
> >> > ERROR: No matching distribution found for windows-curses
> >> > 
> >> > What to do?
> >> 
> >> What is says, use a newer python.
> >> 
> >> It is quite possible that there is not 3.4 package for windows-curses. 
> >> Look it up on pypi.org.
> >> 
> >> -- 
> >> Terry Jan Reedy
> > 
> > You are right, there is no package for Python 3.4.
> > 
> > In the project description:
> > 
> > '''Adds support for the standard Python curses module on Windows. Based on 
> > https://www.lfd.uci.edu/~gohlke/pythonlibs/#curses. Uses the PDCurses 
> > curses implementation.'''
> > 
> > Do I have to install the curses package mentioned there before install/use 
> > windows-curses? How to use this windows-curses? still "import curses"? I am 
> > so confused!
> > 
> 1. Install a more recent version of Python. Python 3.7 is the current 
> version. (Python 3.4 is no longer supported.)
> 
> 2. Install windows-curses using pip for that version of Python.
> 
> That's it!

It works, thank you.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Which curses version should I use under Windows

2019-06-17 Thread jfong
Terry Reedy於 2019年6月18日星期二 UTC+8上午11時03分00秒寫道:
> On 6/17/2019 10:54 PM, jf...@ms4.hinet.net wrote:
> 
> > c:\Works\Python34>pip install windows-curses
> > DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the 
> > last one supporting it. Please upgrade your Python as Python 3.4 w
> > on't be maintained after March 2019 (cf PEP 429).
> > Collecting windows-curses
> >ERROR: Could not find a version that satisfies the requirement 
> > windows-curses (from versions: none)
> > ERROR: No matching distribution found for windows-curses
> > 
> > What to do?
> 
> What is says, use a newer python.
> 
> It is quite possible that there is not 3.4 package for windows-curses. 
> Look it up on pypi.org.
> 
> -- 
> Terry Jan Reedy

You are right, there is no package for Python 3.4.

In the project description:

'''Adds support for the standard Python curses module on Windows. Based on 
https://www.lfd.uci.edu/~gohlke/pythonlibs/#curses. Uses the PDCurses curses 
implementation.'''

Do I have to install the curses package mentioned there before install/use 
windows-curses? How to use this windows-curses? still "import curses"? I am so 
confused!


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Which curses version should I use under Windows

2019-06-17 Thread jfong
MRAB於 2019年6月18日星期二 UTC+8上午10時08分23秒寫道:
> On 2019-06-18 02:39, jf...@ms4.hinet.net wrote:
> > As many others had encountered, when I import the curses module under 
> > Windows, I got
> > 
> >  ImportError: No module named '_curses'
> > 
> > Search "curses" on the Pypi returns plenty of related packages. Which one 
> > should I use? Is this package still valid on usage? Any comment will be 
> > appreciated.
> > 
> I'd probably go for "windows-curses". Seems to install OK.

Thank you for your prompt reply.

I got the following error:

c:\Works\Python34>pip install windows-curses
DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last 
one supporting it. Please upgrade your Python as Python 3.4 w
on't be maintained after March 2019 (cf PEP 429).
Collecting windows-curses
  ERROR: Could not find a version that satisfies the requirement windows-curses 
(from versions: none)
ERROR: No matching distribution found for windows-curses

What to do?
-- 
https://mail.python.org/mailman/listinfo/python-list


Which curses version should I use under Windows

2019-06-17 Thread jfong
As many others had encountered, when I import the curses module under Windows, 
I got

ImportError: No module named '_curses'

Search "curses" on the Pypi returns plenty of related packages. Which one 
should I use? Is this package still valid on usage? Any comment will be 
appreciated.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: tkinter.tix "Control" widget don't work with StringVar?

2019-06-01 Thread jfong
MRAB於 2019年6月2日星期日 UTC+8上午10時18分36秒寫道:
> On 2019-06-02 02:28, jf...@ms4.hinet.net wrote:
> > Below is a simplified version of the sample script downloaded from its 
> > package.
> > When run it, the entry field display '0' instead of 'P'.
> > PS. I am using Python 3.4.4, Windows 32bit
> > 
> > test0.py
> >   1 from tkinter import tix as Tix
> >   2
> >   3 root = Tix.Tk()
> >   4
> >   5 demo_maker = Tix.StringVar()
> >   6 demo_maker.set('P')
> >   7
> >   8 c = Tix.Control(root, label='Engine Maker: ',
> >   9variable=demo_maker,
> > 10options='entry.width 10 label.width 20 label.anchor e')
> > 11 c.pack(side=Tix.TOP, anchor=Tix.W)
> > 12
> > 13 root.mainloop()
> > 
> > 
> > I run it under pdb, try to figure out where the problem is:
> > 
> > D:\Works\Python>py -m pdb test0.py
> >> d:\works\python\test0.py(1)()
> > -> from tkinter import tix as Tix
> > (Pdb) tbreak 13
> > Breakpoint 1 at d:\works\python\test0.py:13
> > (Pdb) cont
> > Deleted breakpoint 1 at d:\works\python\test0.py:13
> >> d:\works\python\test0.py(13)()
> > -> root.mainloop()
> > (Pdb) !c['value']
> > '0'
> > (Pdb) !demo_maker.get()
> > 'P'
> > (Pdb) quit
> > 
> > If I change line 8 to "c = Tix.Control(root, label='Engine Maker: ', 
> > value='P',", the result is very interest:
> > 
> > D:\Works\Python>py -m pdb test0.py
> >> d:\works\python\test0.py(1)()
> > -> from tkinter import tix as Tix
> > (Pdb) tbreak 13
> > Breakpoint 1 at d:\works\python\test0.py:13
> > (Pdb) cont
> > Deleted breakpoint 1 at d:\works\python\test0.py:13
> >> d:\works\python\test0.py(13)()
> > -> root.mainloop()
> > (Pdb) !c['value']
> > '0'
> > (Pdb) !demo_maker.get()
> > '0'
> > (Pdb) quit
> > 
> > Anyone can help?
> > 
>  From the documentation:
> 
> """class tkinter.tix.Control
> The Control widget is also known as the SpinBox widget. The user can 
> adjust the value by pressing the two arrow buttons or by entering the 
> value directly into the entry. The new value will be checked against the 
> user-defined upper and lower limits."""
> 
> In other words, the widget that you're using is for entering a _number_; 
> you can click the up and down buttons to change its value. You usually 
> use it with tix.IntVar.
> 
> You're using it with tix.StringVar, which is for strings, and because 
> it's unable to interpret the value as a number, it's pretending that 
> it's 0 instead. You can, however, set it to, say, '1', or '01', and the 
> widget will then show the number 1.

From the documents, it sounds that this widget was designed for number only. 
But the original example Control.py from 
https://svn.python.org/projects/stackless/trunk/Demo/tix/samples/ works on 
string either by changing its button command. The only thing bothers me is that 
why it fails at the start-up? and I can't figure out the reason:-(
-- 
https://mail.python.org/mailman/listinfo/python-list


tkinter.tix "Control" widget don't work with StringVar?

2019-06-01 Thread jfong
Below is a simplified version of the sample script downloaded from its package.
When run it, the entry field display '0' instead of 'P'.
PS. I am using Python 3.4.4, Windows 32bit

test0.py
 1 from tkinter import tix as Tix
 2 
 3 root = Tix.Tk()
 4 
 5 demo_maker = Tix.StringVar()
 6 demo_maker.set('P')
 7 
 8 c = Tix.Control(root, label='Engine Maker: ',
 9variable=demo_maker,
10options='entry.width 10 label.width 20 label.anchor e')
11 c.pack(side=Tix.TOP, anchor=Tix.W)
12 
13 root.mainloop()


I run it under pdb, try to figure out where the problem is:

D:\Works\Python>py -m pdb test0.py
> d:\works\python\test0.py(1)()
-> from tkinter import tix as Tix
(Pdb) tbreak 13
Breakpoint 1 at d:\works\python\test0.py:13
(Pdb) cont
Deleted breakpoint 1 at d:\works\python\test0.py:13
> d:\works\python\test0.py(13)()
-> root.mainloop()
(Pdb) !c['value']
'0'
(Pdb) !demo_maker.get()
'P'
(Pdb) quit

If I change line 8 to "c = Tix.Control(root, label='Engine Maker: ', 
value='P',", the result is very interest:

D:\Works\Python>py -m pdb test0.py
> d:\works\python\test0.py(1)()
-> from tkinter import tix as Tix
(Pdb) tbreak 13
Breakpoint 1 at d:\works\python\test0.py:13
(Pdb) cont
Deleted breakpoint 1 at d:\works\python\test0.py:13
> d:\works\python\test0.py(13)()
-> root.mainloop()
(Pdb) !c['value']
'0'
(Pdb) !demo_maker.get()
'0'
(Pdb) quit

Anyone can help?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Instance vs Class variable oddity

2019-05-18 Thread jfong
Chris Angelico於 2019年5月18日星期六 UTC+8下午3時09分37秒寫道:
> On Sat, May 18, 2019 at 1:51 PM  wrote:
> >
> > Correct me if I am wrong, please.
> >
> > I always think that the LEGB rule (e.g. the namespace to look up for) was 
> > applied at compile-time, only the binding was resolved "dynamically" at 
> > run-time. For example:
> >
> > def foo():
> > print(x)
> >
> > foo() will cause a NameError. But after
> >
> > x = 5
> >
> > foo() will run correctly.
> 
> This is correct; however, this function will fail with UnboundLocalError:
> 
> x = 1
> def foo():
> print(x)
> x = 2
> 
> Function locals ARE locked in at compile time.
> 
> ChrisA

Thank you. This example proves that the LEGB rule was applied at compile-time, 
and it fails to resolve the binding at run-time.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Instance vs Class variable oddity

2019-05-17 Thread jfong
Correct me if I am wrong, please.

I always think that the LEGB rule (e.g. the namespace to look up for) was 
applied at compile-time, only the binding was resolved "dynamically" at 
run-time. For example:

def foo():
print(x)

foo() will cause a NameError. But after

x = 5

foo() will run correctly.

I also don't think the term "variable" and "attribute" can be used 
exchangeable. Variable apply to an unbound name, and attribute applies to 
bounded name. For example:

foo.x = 3 will create an attribute x of function foo. It's either not a local 
variable, or a global variable. It's more likely a class instance attribute, 
and it's resolved by applying MRO rule dynamically.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


How to debug a function under the (pdb) prompt?

2019-05-10 Thread jfong
For example, there is a file test0.py:
-
1  def foo():
2  for i in range(3):
3  print(i)
4
5  x = 0
-
I start the debug session as below. My question is why the break point at line 
3 didn't work. How to debug the function foo() at this time?

D:\Works\Python>py -m pdb test0.py
> d:\works\python\test0.py(1)()
-> def foo():
(Pdb) tbreak 5
Breakpoint 1 at d:\works\python\test0.py:5
(Pdb) cont
Deleted breakpoint 1 at d:\works\python\test0.py:5
> d:\works\python\test0.py(5)()
-> x = 0
(Pdb) tbreak 3
Breakpoint 2 at d:\works\python\test0.py:3
(Pdb) foo()
0
1
2
(Pdb)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Implement C's Switch in Python 3

2019-03-15 Thread jfong
Sayth Renshaw at 2019/2/3 UTC+8 AM9:52:50 wrote:
> Or perhaps use a 3rd party library like 
> https://github.com/mikeckennedy/python-switch

Thank you for this link. It's a good general implementation.

--Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Quirk difference between classes and functions

2019-02-27 Thread jfong
jf...@ms4.hinet.net於 2019年2月26日星期二 UTC+8下午4時46分04秒寫道:
> ast於 2019年2月26日星期二 UTC+8上午12時25分40秒寫道:
> > Hello
> > 
> > I noticed a quirk difference between classes and functions
> > 
> >  >>> x=0
> >  >>>
> >  >>> class Test:
> >  x = x+1
> >  print(x)
> >  x = x+1
> >  print(x)
> > 
> > 1
> > 2
> >  >>> print(x)
> > 0
> > 
> > Previous code doesn't generate any errors.
> > x at the right of = in first "x = x+1" line is
> > the global one (x=0), then x becomes local
> > 
> > within a function, this is not allowed
> > 
> >  >>> x = 0
> >  >>>
> >  >>> def f():
> >  x = x+1
> > 
> >  >>> f()
> > UnboundLocalError: local variable 'x' referenced before assignment
> > 
> > Since x is written inside the function, it is considered as a local
> > variable and x in x+1 is undefined so this throw an exception
> > 
> > Any comment ?
> 
> May I say that the LEGB rule apply to run time, not compile time?

No. The LEGB apply to compile time where only name and scope are involved.

> 
> >>> x = 1
> >>> def f():
> ... print(x)
> ... print(locals())
> ...
> >>> f()
> 1
> {}
> >>> def g():
> ... print(x)
> ... x = 2
> ... print(locals())
> ...
> >>> g()
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 2, in g
> UnboundLocalError: local variable 'x' referenced before assignment
> >>> class X:
> ... print(x)
> ... x = 2
> ...
> 1
> >>>
> The print(x) difference between class and function was caused by that one was 
> executed and the other was compiled. The LEGB rule must apply to run time to 
> make the language dynamic.

At run time, the binding between name and object can be changed. It's the word 
"dynamic" comes from. 

What happens in class X when print(x) was encountered? I have no idea how the 
LEGB involves there yet:-(

--Jach

> 
> Any comment:-)?
> 
> --Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
Chris Angelico於 2019年2月27日星期三 UTC+8上午11時29分04秒寫道:
> On Wed, Feb 27, 2019 at 2:21 PM  wrote:
> >
> > Chris Angelico於 2019年2月27日星期三 UTC+8上午9時25分11秒寫道:
> > > On Wed, Feb 27, 2019 at 12:21 PM  wrote:
> > > >
> > > > Gregory Ewing at 2019/2/27 AM 5:26:49 wrote:
> > > > > Thomas Jollans wrote:
> > > > > > I imagine there's a justification for the difference in behaviour 
> > > > > > to do
> > > > > > with the fact that the body of a class is only ever executed once, 
> > > > > > while
> > > > > > the body of a function is executed multiple times.
> > > > >
> > > > > I suspect there isn't any deep reason for it, rather it's just
> > > > > something that fell out of the implementation, in particular
> > > > > the decision to optimise local variable access in functions
> > > > > but not other scopes.
> > > > >
> > > > > When compiling a function, the compiler needs to know which
> > > > > variables are local so that it can allocate slots for them in
> > > > > the stack frame. But when executing a class body, the locals
> > > > > are kept in a dict and are looked up dynamically.
> > > >
> > > > If the compiler can do any decision on the variable's name, when it 
> > > > goes to line of print, how it handle it?
> > > >
> > > > x = 0
> > > > def f():
> > > > print(x)
> > > >
> > > > def g():
> > > > print(x)
> > > > x = 1
> > > > print(y)
> > > >
> > >
> > > Not sure what you mean by "decision", but the definition is that since
> > > x is assigned to in g(), it is local to g(). It's not local to f(), so
> > > the global is visible.
> >
> > So, may I say that the Python compiler is a multi-pass one?
> >
> 
> At this point, you're veering away from "Python-the-language" and
> towards "CPython-the-implementation" (or whichever other
> implementation you want to explore). 

Yes, it's a little away:-) I was curious about how the compiled print(x) can be 
influenced by x = 1 after it. Anyway, thank you for your confirmation.

--Jach

> But I would say that, yes, most
> or all Python implementations will use multi-pass compilation. It's
> the easiest way to guarantee correct behaviour. For instance, when you
> reach a "try" statement, you don't know whether there'll be an
> "except" block after it (there might just be a "finally"); the
> bytecode that CPython produces is different for setting up a
> finally-only block than for setting up a try/except. Easiest to find
> out that sort of thing by running multiple passes.
> 
> Plus, depending on how you define "pass", there are additional steps
> such as constant folding and peephole optimization that can be done
> after everything else. So, yeah, it's highly unlikely that there are
> any performant implementations of Python that run a single compilation
> pass.
> 
> ChrisA

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
Chris Angelico於 2019年2月27日星期三 UTC+8上午9時25分11秒寫道:
> On Wed, Feb 27, 2019 at 12:21 PM  wrote:
> >
> > Gregory Ewing at 2019/2/27 AM 5:26:49 wrote:
> > > Thomas Jollans wrote:
> > > > I imagine there's a justification for the difference in behaviour to do
> > > > with the fact that the body of a class is only ever executed once, while
> > > > the body of a function is executed multiple times.
> > >
> > > I suspect there isn't any deep reason for it, rather it's just
> > > something that fell out of the implementation, in particular
> > > the decision to optimise local variable access in functions
> > > but not other scopes.
> > >
> > > When compiling a function, the compiler needs to know which
> > > variables are local so that it can allocate slots for them in
> > > the stack frame. But when executing a class body, the locals
> > > are kept in a dict and are looked up dynamically.
> >
> > If the compiler can do any decision on the variable's name, when it goes to 
> > line of print, how it handle it?
> >
> > x = 0
> > def f():
> > print(x)
> >
> > def g():
> > print(x)
> > x = 1
> > print(y)
> >
> 
> Not sure what you mean by "decision", but the definition is that since
> x is assigned to in g(), it is local to g(). It's not local to f(), so
> the global is visible.

So, may I say that the Python compiler is a multi-pass one?

--Jach
> 
> (Incidentally, "print" is handled exactly the same way. Since neither
> function assigns to print, it's not local, so the built-in is found.)
> 
> ChrisA

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
Gregory Ewing at 2019/2/27 AM 5:26:49 wrote:
> Thomas Jollans wrote:
> > I imagine there's a justification for the difference in behaviour to do
> > with the fact that the body of a class is only ever executed once, while
> > the body of a function is executed multiple times.
> 
> I suspect there isn't any deep reason for it, rather it's just
> something that fell out of the implementation, in particular
> the decision to optimise local variable access in functions
> but not other scopes.
> 
> When compiling a function, the compiler needs to know which
> variables are local so that it can allocate slots for them in
> the stack frame. But when executing a class body, the locals
> are kept in a dict and are looked up dynamically.

If the compiler can do any decision on the variable's name, when it goes to 
line of print, how it handle it?

x = 0
def f():
print(x)

def g():
print(x)
x = 1
print(y)

--Jach

> The compiler *could* be made to treat class bodies the same
> way as functions in this regard, but it would be extra work
> for little or no benefit. Most code in class bodies just
> defines new names without referring to anything else in the
> same scope.
> 
> -- 
> Greg

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
ast於 2019年2月26日星期二 UTC+8上午12時25分40秒寫道:
> Hello
> 
> I noticed a quirk difference between classes and functions
> 
>  >>> x=0
>  >>>
>  >>> class Test:
>  x = x+1
>  print(x)
>  x = x+1
>  print(x)
> 
> 1
> 2
>  >>> print(x)
> 0
> 
> Previous code doesn't generate any errors.
> x at the right of = in first "x = x+1" line is
> the global one (x=0), then x becomes local
> 
> within a function, this is not allowed
> 
>  >>> x = 0
>  >>>
>  >>> def f():
>  x = x+1
> 
>  >>> f()
> UnboundLocalError: local variable 'x' referenced before assignment
> 
> Since x is written inside the function, it is considered as a local
> variable and x in x+1 is undefined so this throw an exception
> 
> Any comment ?

May I say that the LEGB rule apply to run time, not compile time?

>>> x = 1
>>> def f():
... print(x)
... print(locals())
...
>>> f()
1
{}
>>> def g():
... print(x)
... x = 2
... print(locals())
...
>>> g()
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in g
UnboundLocalError: local variable 'x' referenced before assignment
>>> class X:
... print(x)
... x = 2
...
1
>>>
The print(x) difference between class and function was caused by that one was 
executed and the other was compiled. The LEGB rule must apply to run time to 
make the language dynamic.

Any comment:-)?

--Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Ask for help on using asynctk package

2019-02-20 Thread jfong
The file below is a simple script to test this package.
-
# test_asynctk.py

import asynctk as atk

root = atk.AsyncTk()
def delay5S():
btn0.after(5000)
def inc1():
msgs = btn1.cget('text').split()
n = int(msgs[1])
msg = msgs[0] + ' ' + str(n+1) 
btn1.config(text=msg)

btn0 = atk.AsyncButton(root, text='delay 5s', command=delay5S)
btn0.pack()
btn1 = atk.AsyncButton(root, text='increment 0', command=inc1)
btn1.pack()

if __name__ == "__main__":
root.mainloop()
-

After import this script and press the increment button, the following error 
appears. No idea how to use it correctly. Any help?

Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:05:16) [MSC v.1915 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_asynctk
# press the button
>>> Exception in Tkinter callback
Traceback (most recent call last):
  File "H:\WPy-3710Zero\python-3.7.1\lib\tkinter\__init__.py", line 1705, in 
__call__
return self.func(*args)
  File "H:\Works\Python34\asynctk-master\asynctk\_lib.py", line 1615, in 

kw["command"] = lambda *i: asyncio.ensure_future(kw["command"](*i))
  File "H:\Works\Python34\asynctk-master\asynctk\_lib.py", line 1615, in 

kw["command"] = lambda *i: asyncio.ensure_future(kw["command"](*i))
  File "H:\Works\Python34\asynctk-master\asynctk\_lib.py", line 1615, in 

kw["command"] = lambda *i: asyncio.ensure_future(kw["command"](*i))
  [Previous line repeated 995 more times]
RecursionError: maximum recursion depth exceeded

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Problem : Generator

2019-02-15 Thread jfong
Prahallad Achar於 2019年2月15日星期五 UTC+8下午5時27分36秒寫道:
> I get list object instead gen  obj
> 
> On Fri, 15 Feb 2019, 13:57 Chris Angelico  
> > On Fri, Feb 15, 2019 at 6:57 PM Prahallad Achar 
> > wrote:
> > >
> > > How about this
> > > List1=[ 1,2,3,4]
> > > Rever_gen = ( x*x for x in list1, reversed = True)
> > >
> > > Rever_gen gets generator object and iterating it now gets reverse order..
> > >
> > > Am I correct here? Suggest me
> > >
> >
> > How about reversed(list1) ?
> >
> > ChrisA
> > --
> > https://mail.python.org/mailman/listinfo/python-list
> >
Rever_gen = ( x*x for x in reversed(list1))


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to run a module before install?

2019-01-14 Thread jfong
Peter Otten於 2019年1月14日星期一 UTC+8下午4時04分33秒寫道:
> jf...@ms4.hinet.net wrote:
> 
> > I had download a module which has the following directory structure:
> > 
> > [XL-Sudoku-Solver_master]
> >   |__[tests]
> >   |__[xl_sudoku_solver]
> >   |__setup.py   |__ __init__.py
> >   |__problem1.txt   |__ __main__.py
> >   |__README.md  |__ ...
> >   |__ ...
> > 
> > The setup.py file has something like this:
> > -
> > ...
> > setup(
> > name="xl-sudoku-solver",
> > version="0.0.1.post3",
> > packages=['xl_sudoku_solver'],
> > entry_points={
> > "console_scripts": [
> > "xl-sudoku-solver = xl_sudoku_solver.__main__:main"
> > ]
> > },
> > ...
> > 
> > 
> > and the __main__.py has:
> > 
> > ...
> > from . import Solver, load_from_file, load_from_input, load_from_string
> > 
> > def main():
> > ...
> > 
> > if __name__ == '__main__':
> > main()
> > 
> > 
> > The README.md suggest the way of running it:
> > 
> > pip install xl-sudoku-solver
> > $ xl-sudoku-solver --time -f problem1.txt
> > 
> > But I like to run it before install. Is it possible? and how? I had try
> > two ways below but niether works:
> > 
> > 1) h:\Temp\XL-Sudoku-Solver-master>py xl_sudoku_solver --time -f
> > problem1.txt Traceback (most recent call last):
> >   File "C:\Python34\lib\runpy.py", line 170, in _run_module_as_main
> > "__main__", mod_spec)
> >   File "C:\Python34\lib\runpy.py", line 85, in _run_code
> > exec(code, run_globals)
> >   File "xl_sudoku_solver\__main__.py", line 5, in 
> > from . import Solver, load_from_file, load_from_input,
> > load_from_string
> > SystemError: Parent module '' not loaded, cannot perform relative import
> > 
> > 2) h:\Temp\XL-Sudoku-Solver-master>py
> > Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32
> > bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for
> > more information.
>  import xl_sudoku_solver
> 
> > 
> > Can't find the name "main", What to do?
> 
> With h:\Temp\XL-Sudoku-Solver-master as the current working directory try
> 
> h:\Temp\XL-Sudoku-Solver-master>py -m xl_sudoku_solver

Great! it works. Thank you, peter.

By the way, can you explain what these two command difference means? with or 
without a "-m". Or pointing where the document is. Thanks ahead:-)

-- 
https://mail.python.org/mailman/listinfo/python-list


How to run a module before install?

2019-01-13 Thread jfong
I had download a module which has the following directory structure:

[XL-Sudoku-Solver_master]
  |__[tests]
  |__[xl_sudoku_solver]
  |__setup.py   |__ __init__.py
  |__problem1.txt   |__ __main__.py
  |__README.md  |__ ...
  |__ ...

The setup.py file has something like this:
-
...
setup(
name="xl-sudoku-solver",
version="0.0.1.post3",
packages=['xl_sudoku_solver'],
entry_points={
"console_scripts": [
"xl-sudoku-solver = xl_sudoku_solver.__main__:main"
]
},
...


and the __main__.py has:

...
from . import Solver, load_from_file, load_from_input, load_from_string

def main():
...

if __name__ == '__main__':
main()


The README.md suggest the way of running it:

pip install xl-sudoku-solver
$ xl-sudoku-solver --time -f problem1.txt 

But I like to run it before install. Is it possible? and how? I had try two 
ways below but niether works:

1) h:\Temp\XL-Sudoku-Solver-master>py xl_sudoku_solver --time -f problem1.txt
Traceback (most recent call last):
  File "C:\Python34\lib\runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
  File "C:\Python34\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
  File "xl_sudoku_solver\__main__.py", line 5, in 
from . import Solver, load_from_file, load_from_input, load_from_string
SystemError: Parent module '' not loaded, cannot perform relative import

2) h:\Temp\XL-Sudoku-Solver-master>py
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import xl_sudoku_solver
>>>

Can't find the name "main", What to do?


--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-28 Thread jfong
jf...@ms4.hinet.net於 2018年12月28日星期五 UTC+8下午4時04分07秒寫道:
> eryk sun at 2018/12/27 UTC+8 PM 6:58:33 wrote:
> > On 12/27/18, jf...@ms4.hinet.net  wrote:
> > >
> > > I still don't get it. When I change it to using list comprehension, the
> > > problem is still there. (it now has no late-binding variable, right? :-)
> > >
> >  class Too:
> > > ... XS = [15, 15, 15, 15]
> > > ... Z4 = [val for val in XS]
> > > ... Z5 = [XS[0] for val in XS]
> > > ...
> > > Traceback (most recent call last):
> > >   File "", line 1, in 
> > >   File "", line 4, in Too
> > >   File "", line 4, in 
> > > NameError: name 'XS' is not defined
> > >
> > > The problem confuse me is that is XS a local variable of the list
> > > comprehension?
> > 
> > XS is not a local variable in the scope of either comprehension. XS is
> > local to the class statement's scope. For each comprehension, an
> > iterator for the current object referenced by XS gets instantiated
> > (early binding) and passed as an argument to the comprehension scope.
> > If we disassemble the comprehension code, we find that this iterator
> > argument has the creatively illegal name ".0". (The bytecode
> > references it by its fast-locals-array index, not its weird name.)
> > 
> > In the Z5 case, XS is a non-local variable (late binding) in the
> > loop-body expression (left-hand side) of the comprehension. That's
> > common for Python code. In every iteration of the loop, the
> > interpreter looks up the object referenced by the name "XS", which can
> > change at any time (e.g. by another thread).
> 
> In Python document 4.2.2. Resolution of names, the last paragraph:
> 
> "...A class definition is an executable statement that may use and define 
> names. These references follow the normal rules for name resolution with an 
> exception that unbound local variables are looked up in the global namespace. 
> ...The scope of names defined in a class block is limited to the class block; 
> it does not extend to the code blocks of methods – this includes 
> comprehensions and generator expressions since they are implemented using a 
> function scope". 
> 
> These statements reflect the following difference:
> 
> >>> xy = [1,2]
> >>> [dir() for i in xy]
> [['.0', 'i'], ['.0', 'i']]
> >>> [xy[0] for i in xy]
> [1, 1]
> 
> >>> class foo():
> ... xs = [1,2]
> ... z4 = [dir() for i in xs]
> ...
> >>> foo().z4
> [['.0', 'i'], ['.0', 'i']]
> >>> class foo():
> ... xs = [1,2]
> ... z4 = [xs[0] for i in xs]
> ...
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 3, in foo
>   File "", line 3, in 
> NameError: name 'xs' is not defined
> >>>
> 
> and it goes further:
> 
> >>> [dir() for i in xy for j in xy]
> [['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j']]
> >>> class foo():
> ... xs = [1,2]
> ... z5 = [dir() for i in xs for j in xs]
> ...
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 3, in foo
>   File "", line 3, in 
> NameError: name 'xs' is not defined
> >>>
> 
> That's all I had learn so far, although not understand the design decision 
> behind it yet:-(
> 
> --Jach

Anyway, it "looks" weird. Isn't it?

>>> xs = [5,6,7,8]
>>> class foo():
... xs = [1,2,3]
... z4 = [xs[i] for i in xs]
...
>>> foo.z4
[6,7,8]

xs in the "for" statement referenced to class variable xs and xs[i] in the body 
referenced to the global xs with i from locals.

PS. Don't bother to reply. This is just for my own documentary:-)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-28 Thread jfong
eryk sun at 2018/12/27 UTC+8 PM 6:58:33 wrote:
> On 12/27/18, jf...@ms4.hinet.net  wrote:
> >
> > I still don't get it. When I change it to using list comprehension, the
> > problem is still there. (it now has no late-binding variable, right? :-)
> >
>  class Too:
> > ... XS = [15, 15, 15, 15]
> > ... Z4 = [val for val in XS]
> > ... Z5 = [XS[0] for val in XS]
> > ...
> > Traceback (most recent call last):
> >   File "", line 1, in 
> >   File "", line 4, in Too
> >   File "", line 4, in 
> > NameError: name 'XS' is not defined
> >
> > The problem confuse me is that is XS a local variable of the list
> > comprehension?
> 
> XS is not a local variable in the scope of either comprehension. XS is
> local to the class statement's scope. For each comprehension, an
> iterator for the current object referenced by XS gets instantiated
> (early binding) and passed as an argument to the comprehension scope.
> If we disassemble the comprehension code, we find that this iterator
> argument has the creatively illegal name ".0". (The bytecode
> references it by its fast-locals-array index, not its weird name.)
> 
> In the Z5 case, XS is a non-local variable (late binding) in the
> loop-body expression (left-hand side) of the comprehension. That's
> common for Python code. In every iteration of the loop, the
> interpreter looks up the object referenced by the name "XS", which can
> change at any time (e.g. by another thread).

In Python document 4.2.2. Resolution of names, the last paragraph:

"...A class definition is an executable statement that may use and define 
names. These references follow the normal rules for name resolution with an 
exception that unbound local variables are looked up in the global namespace. 
...The scope of names defined in a class block is limited to the class block; 
it does not extend to the code blocks of methods – this includes comprehensions 
and generator expressions since they are implemented using a function scope". 

These statements reflect the following difference:

>>> xy = [1,2]
>>> [dir() for i in xy]
[['.0', 'i'], ['.0', 'i']]
>>> [xy[0] for i in xy]
[1, 1]

>>> class foo():
... xs = [1,2]
... z4 = [dir() for i in xs]
...
>>> foo().z4
[['.0', 'i'], ['.0', 'i']]
>>> class foo():
... xs = [1,2]
... z4 = [xs[0] for i in xs]
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in foo
  File "", line 3, in 
NameError: name 'xs' is not defined
>>>

and it goes further:

>>> [dir() for i in xy for j in xy]
[['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j']]
>>> class foo():
... xs = [1,2]
... z5 = [dir() for i in xs for j in xs]
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in foo
  File "", line 3, in 
NameError: name 'xs' is not defined
>>>

That's all I had learn so far, although not understand the design decision 
behind it yet:-(

--Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-27 Thread jfong
eryk sun於 2018年12月27日星期四 UTC+8下午2時31分58秒寫道:
> On 12/26/18, jf...@ms4.hinet.net  wrote:
> > I saw the code below at stackoverflow. I have a little idea about the scope
> > of a class, and list comprehension and generator expressions, but still
> > can't figure out why Z4 works and Z5 not. Can someone explain it? (in a
> > not-too-complicated way:-)
> >
> > class Foo():
> > XS = [15, 15, 15, 15]
> > Z4 = sum(val for val in XS)
> > try:
> > Z5 = sum(XS[i] for i in range(len(XS)))
> > except NameError:
> > Z5 = None
> >
> > print(Foo.Z4, Foo.Z5)
>  60 None
> 
> Maybe rewriting it with approximately equivalent inline code and
> generator functions will clarify the difference:
> 
> class Foo:
> def genexpr1(iterable):
> for val in iterable:
> yield val
> 
> def genexpr2(iterable):
> for i in iterable:
> yield XS[i]
> 
> XS = [15, 15, 15, 15]
> Z4 = sum(genexpr1(XS))
> try:
> Z5 = sum(genexpr2(range(len(XS
> except NameError:
> Z5 = None
> 
> del genexpr1, genexpr2
> 
> >>> print(Foo.Z4, Foo.Z5)
> 60 None
> 
> In both cases, an iterable is passed to the generator function. This
> argument is evaluated in the calling scope (e.g. range(len(XS))). A
> generator expression has a similar implementation, except it also
> evaluates the iterator for the iterable to ensure an exception is
> raised immediately in the defining scope if it's not iterable. For
> example:
> 
> >>> (x for x in 1)
> Traceback (most recent call last):
>   File "", line 1, in 
> TypeError: 'int' object is not iterable
> 
> genexpr1 is working with local variables only, but genexpr2 has a
> non-local reference to variable XS, which we call late binding. In
> this case, when the generator code executes the first pass of the loop
> (whenever that is), it looks for XS in the global (module) scope and
> builtins scope. It's not there, so a NameError is raised.
> 
> With late-binding, the variable can get deleted or modified in the
> source scope while the generator gets evaluated. For example:
> 
> >>> x = 'spam'
> >>> g = (x[i] for i in range(len(x)))
> >>> next(g)
> 's'
> >>> del x
> >>> next(g)
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 1, in 
> NameError: name 'x' is not defined
> 
> >>> x = 'spam'
> >>> g = (x[i] for i in range(len(x)))
> >>> next(g)
> 's'
> >>> x = 'eggs'
> >>> list(g)
> ['g', 'g', 's']

I still don't get it. When I change it to using list comprehension, the problem 
is still there. (it now has no late-binding variable, right? :-)

>>> class Too:
... XS = [15, 15, 15, 15]
... Z4 = [val for val in XS]
... Z5 = [XS[0] for val in XS]
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 4, in Too
  File "", line 4, in 
NameError: name 'XS' is not defined
>>>

The problem confuse me is that is XS a local variable of the list comprehension?
If it's then Z5 should work, if it's not then Z4 shouldn't work when it's 
written in generator expression.

Or, things is much more complex than I thought:-(


-- 
https://mail.python.org/mailman/listinfo/python-list


Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-26 Thread jfong
I saw the code below at stackoverflow. I have a little idea about the scope of 
a class, and list comprehension and generator expressions, but still can't 
figure out why Z4 works and Z5 not. Can someone explain it? (in a 
not-too-complicated way:-)

class Foo():
XS = [15, 15, 15, 15]
Z4 = sum(val for val in XS)
try:
Z5 = sum(XS[i] for i in range(len(XS)))
except NameError:
Z5 = None

print(Foo.Z4, Foo.Z5)
>>> 60 None


--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Smarter algo, was Re: 03 digression by brute force

2018-12-16 Thread jfong
BlindAnagram at 2018/12/15 UTC+8 PM 8:41:21 wrote:
> On 15/12/2018 09:56, jf...@ms4.hinet.net wrote:
> > Appreciate your thoughtfully analysis on this code. Before generalize it 
> > with arbitrary additions, as Peter suggested:-), a recursive version is 
> > needed. I may give it a try on this Sunday.
> > 
> > 
> > Avi Gross at 2018/12/15 UTC+8 AM8:13:37 wrote:
> >> REAL SUBJECT: Analysis of alternate algorithms.
> >>
> >> Peter & Jach and anyone interested,
> >>
> >> As Peter said in his altered subject line, Jack changed directions from 
> >> tweaking an algorithm to trying something quite different.
> >>
> >> Reminder of the problem. 
> >>
> >> Horizontal View:
> >> SEND + MORE = MONEY
> >>
> >> Vertical View:
> >>   SEND
> >> +MORE
> >> ...
> >> MONEY
> >>
> >> Hard to be precise as I am sticking to plain text in my message. The three 
> >> words above are meant to be right adjusted.
> >>
> >> When solving it horizontally, Jach and I used variants of a brute force 
> >> approach. Substitute all possible combinations. He did it in-line and used 
> >> eval. I did it by making lists of items on both sides and summing the 
> >> int() of each component and comparing. We tried both our algorithms and 
> >> his was slower and he profiled that the cause was that eval() was much 
> >> more expensive as were his use of regular expression functions. For 
> >> comparison, mine used int() and string manipulation functions and sets and 
> >> dictionaries.
> >>
> >> But the real puzzle is meant to be solved in a more vertical way by humans 
> >> using logic. I won't do that here but note we have 4 equations going down 
> >> but 8 unknowns. And the equations are not unique.
> >>
> >> The rightmost column (I will call it the first as our arithmetic proceeds 
> >> from right to left) is meant to represent ONES and provides the equation:
> >>
> >> (D+E== Y) or (D+E == Y + 10)
> >>
> >> Worse, for the next column, you either get a "1" carried from the previous 
> >> addition or not and either pass a "1" along to the next column or not. 4 
> >> Possibilities.
> >>
> >> (N+R==E) or (N+R+1==E) or (N+R==E+10) or (N+R+1==E+10)
> >>
> >> Getting a headache yet?
> >>
> >> For a human, they need a way to come up with additional info in terms of 
> >> constraints.
> >>
> >> There is a guiding inequality that looks like this:
> >>
> >> S is not the same as any of the others. Anytime you solve for another, the 
> >> list of possible values for S shrinks.
> >> Ditto for each other variable.
> >> Or, since anything plus 0 is itself, then D and E adding up to Y (with no 
> >> possible carry) cannot be 0.
> >>
> >> But getting a computer to do this might be a bit harder than blunt-force 
> >> searches. So let's see why Jach's new algorithm was faster.
> >>
> >> The code I am analyzing can be viewed in the archives and will not be 
> >> entered again:
> >>
> >> https://mail.python.org/pipermail/python-list/2018-December/738454.html
> >>
> >> So what did Jach try in his newer version? It is what I call a vertical 
> >> approach but one a computer can do easier than a human can or would. I see 
> >> it is a very specific algorithm that hard codes in these variables as 
> >> global entities that are altered by a set of nested functions. S, E, N, D, 
> >> M, O, R, Y. There are approaches that might be better such as passing a 
> >> dictionary partially filled out from one function to the next as the only 
> >> one that prints the solution is the final function call.
> >>
> >> So his is not a general solution.
> >>
> >> What interests me as a probable reason this is faster is the number of 
> >> situations it tries. The earlier versions asked itertools.permutations() 
> >> to provide all unique combinations of ten tokens in eight positions. So 
> >> there were 10 choices for the first and 9 for the second and so on adding 
> >> up to 10!/2! or 1,814,400  different combinations tried. That approaches 2 
> >> million.
> >>
> >> Jack broke the problem down into evaluating the units column with a loop 
> >> like this:
> >>
> >> itertools.permutations(range(10), 3)
> >>
> >> That is 720 possibilities. He then doubled that to 1,440 to consider a 
> >> carry. Only if the selected values for the three variables in contention 
> >> (plus a carry) does he go on to call to evaluate the tens column.
> >>
> >> It then shrinks a bit more as he no longer gets the permutations of all 10 
> >> digits. He subtracts the three values that might work for the units, so he 
> >> is asking for permutations of 7 digits, two at a time. That is 42, doubled 
> >> again to 84 for carry purposes. And this function is not called 1,440 
> >> times, but quite a bit fewer. 
> >>
> >> So, similarly, of those 84 loops for tens, he only sometimes calls to 
> >> evaluate hundreds. As mentioned, the set of 10 digits shrinks some more 
> >> and this continues upward to functions that evaluate hundreds and 
> >> thousands  and finally the one evaluating ten thousands 

Re: Smarter algo, was Re: 03 digression by brute force

2018-12-15 Thread jfong
Appreciate your thoughtfully analysis on this code. Before generalize it with 
arbitrary additions, as Peter suggested:-), a recursive version is needed. I 
may give it a try on this Sunday.


Avi Gross at 2018/12/15 UTC+8 AM8:13:37 wrote:
> REAL SUBJECT: Analysis of alternate algorithms.
> 
> Peter & Jach and anyone interested,
> 
> As Peter said in his altered subject line, Jack changed directions from 
> tweaking an algorithm to trying something quite different.
> 
> Reminder of the problem. 
> 
> Horizontal View:
> SEND + MORE = MONEY
> 
> Vertical View:
>   SEND
> +MORE
> ...
> MONEY
> 
> Hard to be precise as I am sticking to plain text in my message. The three 
> words above are meant to be right adjusted.
> 
> When solving it horizontally, Jach and I used variants of a brute force 
> approach. Substitute all possible combinations. He did it in-line and used 
> eval. I did it by making lists of items on both sides and summing the int() 
> of each component and comparing. We tried both our algorithms and his was 
> slower and he profiled that the cause was that eval() was much more expensive 
> as were his use of regular expression functions. For comparison, mine used 
> int() and string manipulation functions and sets and dictionaries.
> 
> But the real puzzle is meant to be solved in a more vertical way by humans 
> using logic. I won't do that here but note we have 4 equations going down but 
> 8 unknowns. And the equations are not unique.
> 
> The rightmost column (I will call it the first as our arithmetic proceeds 
> from right to left) is meant to represent ONES and provides the equation:
> 
> (D+E== Y) or (D+E == Y + 10)
> 
> Worse, for the next column, you either get a "1" carried from the previous 
> addition or not and either pass a "1" along to the next column or not. 4 
> Possibilities.
> 
> (N+R==E) or (N+R+1==E) or (N+R==E+10) or (N+R+1==E+10)
> 
> Getting a headache yet?
> 
> For a human, they need a way to come up with additional info in terms of 
> constraints.
> 
> There is a guiding inequality that looks like this:
> 
> S is not the same as any of the others. Anytime you solve for another, the 
> list of possible values for S shrinks.
> Ditto for each other variable.
> Or, since anything plus 0 is itself, then D and E adding up to Y (with no 
> possible carry) cannot be 0.
> 
> But getting a computer to do this might be a bit harder than blunt-force 
> searches. So let's see why Jach's new algorithm was faster.
> 
> The code I am analyzing can be viewed in the archives and will not be entered 
> again:
> 
> https://mail.python.org/pipermail/python-list/2018-December/738454.html
> 
> So what did Jach try in his newer version? It is what I call a vertical 
> approach but one a computer can do easier than a human can or would. I see it 
> is a very specific algorithm that hard codes in these variables as global 
> entities that are altered by a set of nested functions. S, E, N, D, M, O, R, 
> Y. There are approaches that might be better such as passing a dictionary 
> partially filled out from one function to the next as the only one that 
> prints the solution is the final function call.
> 
> So his is not a general solution.
> 
> What interests me as a probable reason this is faster is the number of 
> situations it tries. The earlier versions asked itertools.permutations() to 
> provide all unique combinations of ten tokens in eight positions. So there 
> were 10 choices for the first and 9 for the second and so on adding up to 
> 10!/2! or 1,814,400  different combinations tried. That approaches 2 million.
> 
> Jack broke the problem down into evaluating the units column with a loop like 
> this:
> 
> itertools.permutations(range(10), 3)
> 
> That is 720 possibilities. He then doubled that to 1,440 to consider a carry. 
> Only if the selected values for the three variables in contention (plus a 
> carry) does he go on to call to evaluate the tens column.
> 
> It then shrinks a bit more as he no longer gets the permutations of all 10 
> digits. He subtracts the three values that might work for the units, so he is 
> asking for permutations of 7 digits, two at a time. That is 42, doubled again 
> to 84 for carry purposes. And this function is not called 1,440 times, but 
> quite a bit fewer. 
> 
> So, similarly, of those 84 loops for tens, he only sometimes calls to 
> evaluate hundreds. As mentioned, the set of 10 digits shrinks some more and 
> this continues upward to functions that evaluate hundreds and thousands  and 
> finally the one evaluating ten thousands pretty much prints out an answer it 
> finds. 
> 
> So overall iterations can be shown to drop. We could add code to measure how 
> many times each function is called and come up with an exact value for this 
> built-in problem. I did and the functions were called this many times:
> 
> >>> counting
> {'unit': 1, 'ten': 72, 'hundred': 290, 'thou': 183, '10thou': 196}
> >>> sum(counting.values())
> 742
> 
> But I 

Re: 03 digression by brute force

2018-12-13 Thread jfong
Just for fun:-) On my ooold PC, it takes 0.047 seconds to run the following 
algorithm on the problem 'SNED + MORE == MONEY".

-
import time
import itertools

#S, E, N, D, M, O, R, Y
n = 0
digits = {x for x in range(10)}

def tenThousand(u, Cin):  # Cin == M
global n
if Cin == M:
print(S, E, N, D, '+', M, O, R, E, '==', M, O, N, E, Y)
n += 1

def thousand(u, Cin):  # Cin + S + M == 10 * Cout + O
global S, M, n
rest = digits - set(u)
for g in itertools.permutations(rest, 2):
for Cout in range(2):
if Cin + g[0] + g[1] == 10 * Cout + O:
S = g[0];  M = g[1]
tenThousand(u + g, Cout)

def hundred(u, Cin):  # Cin + E + O == 10 * Cout + N
global O, n
rest = digits - set(u)
for g in itertools.permutations(rest, 1):
for Cout in range(2):
if Cin + E + g[0] == 10 * Cout + N:
O = g[0]
thousand(u + g, Cout)

def ten(u, Cin):  # Cin + N + R == 10 * Cout + E
global N, R, n
rest = digits - set(u)
for g in itertools.permutations(rest, 2):
for Cout in range(2):
if Cin + g[0] + g[1] == 10 * Cout + E:
N = g[0];  R = g[1]
hundred(u + g, Cout)

def unit():  # D + E == 10 * Cout + Y
global D, E, Y, n
n = 0
for g in itertools.permutations(range(10), 3):  # g is a tuple
for Cout in range(2):  # add two items so Cout is 0 or 1
if g[0] + g[1] == 10 * Cout + g[2]:
D = g[0];  E = g[1];  Y = g[2]
ten(g, Cout)
print(n)

if __name__ == '__main__':
start = time.time()
unit()
print(time.time() - start)
-

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-10 Thread jfong
Chris Angelico於 2018年12月10日星期一 UTC+8下午7時09分01秒寫道:
> On Mon, Dec 10, 2018 at 9:46 PM  wrote:
> >
> > Chris Angelico於 2018年12月10日星期一 UTC+8下午6時17分14秒寫道:
> > > On Mon, Dec 10, 2018 at 9:11 PM Antoon Pardon  
> > > wrote:
> > > >
> > > > On 10/12/18 11:03, Chris Angelico wrote:
> > > > > Considering that, in a problem of that description, neither S nor M
> > > > > may represent zero, I don't think there's a problem here.
> > > >
> > > > Not all such problems have that condition.
> > >
> > > They should. Every published set of problems that I've ever solved by
> > > hand has. I went searching online for some, and found this page:
> > >
> > > http://puzzlepicnic.com/genre?alphametic
> > >
> > > which clearly states that exact restriction. The implication is that
> > > you're solving a puzzle in arithmetic (usually addition or long
> > > multiplication), and it is *exactly* as you would have written it with
> > > digits, save that the digits have been replaced with letters (and
> > > carries have been omitted, since that'd make it too easy). You
> > > wouldn't write a leading zero on a number in standard grade-school
> > > arithmetic, so you also won't use a leading zero in anything here.
> > >
> > > ChrisA
> >
> > All I know is that when I write a number 03, there is no any human being 
> > will say it's an illegal number.
> >
> 
> Yet most human beings will agree that you don't write out an
> arithmetic problem as:
> 
>0 1 9 8
>  +   7 1 3
>  =

Python3 gives me the error message is because of the number 0198, not because 
of 0198 + 713.

> > I prefer to buy the reason that this restriction was bring in is because of 
> > the puzzle's author know it will cause trouble without this, not because of 
> > our written habit.
> >
> 
> No, it's a restriction because it is unsatisfactory without it. The
> point of a puzzle is to be fun, and fun means having restrictions that
> fit what people expect.

The fun is from solving the puzzle, not from its restriction, unless the puzzle 
has no fun without this restriction.

--Jach

> ChrisA

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-10 Thread jfong
Chris Angelico於 2018年12月10日星期一 UTC+8下午6時17分14秒寫道:
> On Mon, Dec 10, 2018 at 9:11 PM Antoon Pardon  wrote:
> >
> > On 10/12/18 11:03, Chris Angelico wrote:
> > > Considering that, in a problem of that description, neither S nor M
> > > may represent zero, I don't think there's a problem here.
> >
> > Not all such problems have that condition.
> 
> They should. Every published set of problems that I've ever solved by
> hand has. I went searching online for some, and found this page:
> 
> http://puzzlepicnic.com/genre?alphametic
> 
> which clearly states that exact restriction. The implication is that
> you're solving a puzzle in arithmetic (usually addition or long
> multiplication), and it is *exactly* as you would have written it with
> digits, save that the digits have been replaced with letters (and
> carries have been omitted, since that'd make it too easy). You
> wouldn't write a leading zero on a number in standard grade-school
> arithmetic, so you also won't use a leading zero in anything here.
> 
> ChrisA

All I know is that when I write a number 03, there is no any human being will 
say it's an illegal number.

I prefer to buy the reason that this restriction was bring in is because of the 
puzzle's author know it will cause trouble without this, not because of our 
written habit.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-08 Thread jfong
Avi Gross於 2018年12月9日星期日 UTC+8上午1時40分26秒寫道:
> Jach,
> 
> Just for fun, I looked at the  puzzle you asked about and solved it several
> ways without running into your 03 problem at all. There are more efficient
> solutions than total brute force.
> 
> Anyone not interested, stop here, please. After my explanations, I show a
> python program then the output it produces.
> 
> The comments in the python program (below) explain the solution classes but
> let me suggest a little algebra simplifies the problem so fewer brute force
> iterations are needed.
> 
> The simplistic algorithm can be written as a single list comprehension with
> (in this case) 5 "for" clauses and one "if" clause.
> 
> You are solving for: ab + aa + cd == ce
> 
> So 
> for all digits possible for a
> for all remaining digits possible for b each iteration
> for all remaining digits possible for c each iteration
> for all remaining digits possible for d each iteration
> for all remaining digits possible for e each iteration
> if the condition applies.
> 
> Clearly the above is deeply nested with 10!/5! Iterations or 30,240.
> 
> But a little algebra simplifies the solution so c drops out of the equation
> as shown below in the comments.
> The test becomes:  21*a + b + d - e == 0
> 
> You can apply that as the condition using four loops. You get 32 solutions
> and for each you can let c be any of 10 possibilities for 320 total
> solutions, if I did it right. The number of iterations is now only 5,040 and
> you are evaluating fewer terms with c gone. The full test would have been
> (10*a +b )+ (10*a + a) + (10*c + d) == (10*c + e)
> 
> BUT a tad more analysis shows that all solutions require "a" to be zero. If
> a >=1 then 21*a must be >= 21.
> But b and c cannot be more than 9+8 which is 17 and subtracting e makes it
> no larger. So "a" MUST be zero.
> 
> So the solution can be done with only three loops for b, d, and e. 720
> iterations.
> 
> The commented code is below. It can be done in as little as two lines of
> code if the list comprehension is done in one line but why make it hard to
> read.
> 
> If there is a flaw in my reasoning or the program below, please point it
> out. You said there were 192 solutions. I found 320.
> And, there are more efficient solutions possible but overkill for this
> application.
> 
> Avi
> 
> ### START CODE ##
> # GOAL: find all solutions of a puzzle
> # ab + aa + cd == ce
> # Where each of the letters a through e
> # are UNIQUE values ranging from 0 to 9
> 
> # Make the equation simpler
> # expand ab to 10*a + b
> # expand aa to 10*a + a
> # expand cd to 10*c + d
> # add to get 21*a + b + 10*c + d
> # expand ce to 10*c + e
> # simplify 21*a + b + 10*c + d = 10*c + e
> # the 10*c on both sides cancel.
> # RESULT: 21*a + b + d - e = 0
> # the value of c is not relevant and
> # you can solve without e and then add back
> # all ten possibilities later.
> 
> # Method:
> # Use a set of digits.
> # Use a list comprehension with four loops.
> # Each loop chooses all available values
> # for a,b,d,e by subtracting the set
> # of digits already in use at the time from all digits.
> 
> digits = set(range(10))
> 
> matches = [ (a, b, d, e)
> for a in digits
> for b in (digits - {a})
> for d in (digits -{a,b})
> for e in (digits -{a,b,d})
> if ( 21*a + b + d - e == 0)
> ]
> 
> print("SOLVING FOR: 21*a + b + d - e == 0")
> print(f"matches found in batches of 10: {len(matches)}")
> 
> for (a,b,d,e) in matches:
> solution =  {'a' : a,
> 'b' : b,
> 'c' : 'any digit',
> 'd' : d,
> 'e' : e
>  }
> print(solution)
> 
> # Note the result shows all solutions have 'a' being zero.
> # That was obvious from the equation as there were 21 of them
> # and if a was 1 in 21*a + b + d - e = 0
> # then clearly band d cannot be more than 9+8 so no solution
> # unless a == 0.
> # So you can solve this easier using the above techique by just
> # solving b + d - e = 0
> 
> matches = [ (b, d, e)
> for b in digits
> for d in (digits -{b})
> for e in (digits -{b,d})
> if ( b + d == e)
> ]
> 
> print("\nSOLVING FOR: b + d == e")
> print(f"matches found in batches of 10: {len(matches)}")
> 
> for (b,d,e) in matches:
> solution =  {'a' : '0',
> 'b' : b,
> 'c' : 'any digit',
> 'd' : d,
> 'e' : e
>  }
> print(solution)
> 
> ### END CODE ##
> ### BEGIN OUTPUT ##
> SOLVING FOR: 21*a + b + d - e == 0
> matches found in batches of 10: 32
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 2, 'e': 3}
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 3, 'e': 4}
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 4, 'e': 5}
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 

Re: Why Python don't accept 03 as a number?

2018-12-08 Thread jfong
Grant Edwards於 2018年12月9日星期日 UTC+8上午12時52分04秒寫道:
> On 2018-12-08, Cameron Simpson  wrote:
> > On 07Dec2018 20:24, Jach Fong  wrote:
> >>Ian at 2018/12/8 UTC+8 AM11:28:34 wrote:
> >>> What is it exactly that you're trying to accomplish with this? Perhaps
> >>> there's a better way than using eval.
> >>
> >>This problem comes from solving a word puzzle,
> >>ab + aa + cd == ce
> >>Each character will be translate to a digit and evaluate the correctness,
> >>03 + 00 + 15 == 18
> >
> > Then you should be evaluating the digits and assembling values from 
> > them. Not trying to shoehorn a string through something that _might_ 
> > accept this string and do what you want. In Python 2 it will accept your 
> > string and not do what you want; at least in Python 3 it doesn't accept 
> > your string.
> 
> Just to be clear: you do _not_ want to use eval on the string.
> 
> If you're not the one who created the string, it might wipe your hard
> drive or empty your bank account.  If you _are_ the one who created
> the string, then generate the desired result instead.
> 
> -- 
> Grant

I didn't evaluate the input string directly. It's the translated "digit" string 
been evaluated, so shouldn't have any danger on using eval().

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-08 Thread jfong
Avi Gross at 2018/12/8 UTC+8 PM2:09:20 wrote:
> [[READERS DIGEST CONDENSED ANSWER: use int("string") ]]
> 
> Since we all agree python will not make notations like "05" work
> indefinitely, and the need expressed is how to solve a symbolic puzzle (see
> message below) then it makes sense to look at alternate representations.
> 
> I have a question first. How are you solving your puzzles? 
> 
> ab + aa + cd == ce

Try all the combinations:-)

The only way I can think of is try-error. It takes no more 10 lines to go from 
"ab + aa + cd == ce" to yield one correct answer, such as "03 + 00 + 15 == 18", 
using itertools' permutations(), string's translate() and re.

> Why does 05 ever even appear in your solution?

I don't know. There is total 192 answers for this puzzle anyway.

> Are you generating all possible answers by setting each variable to one of 0
> to 9 then the second to any of the remaining nine choices then the third to
> the remaining 8 and so on? For any method like that, you can presumably make
> each component like
> 
> ab = 10*a + b
> 
> in the loop.
> 
> Similarly for aa and cd and ce. If the equality above is true, you found the
> solution and break out. If there can be multiple solutions, note the
> solution and keep going. But note for the 5 variables above, you are testing
> 10*9*8*7*6 combinations.
> 
> Another idea is to use strings like "05" as bizarrely, the function int()
> seems to be an ex eption that does NOT care about leading whitespace or
> zeroes:
> 
> >>> int("05")
> 5
> >>> int("  0005")
> 5
> 
> And even handles all zeroes:
> 
> >>> int("00")
> 0
> 
> You can also use lstrip() with an argument to remove zeros:
> 
> >>> a = eval("05".lstrip("0"))
>
> >>> a
>
> 5
> 
> If you are in a situation where you only want to remove leading zeroes if
> the following character is a digit and not "o" or "b" or "x", use regular
> expressions or other techniques.

As far as the leading zero problem was concerned, the simplest way is using 
re.sub()

> I will just toss in the possible use of the SymPy module to do actual
> symbolic computations to solve some of these. Perhaps a tad advanced.

I don't know SymPy and if it can shorten the execution time. But I am very 
curious about if there is other algorithm which can apply to this problem:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
I can understand the difficulty of throwing old thing away and accept new one 
in human. There seems have a huge inertia there. This phenomenon appears on 
every aspects, not only on the transition from Python2 to Python3. But, as a 
new comer of Python like me, I have no difficulty to accept it because of 03 is 
a valid number in my daily life and never had the experience of treating 010 as 
8:-)

MBAB wrote:
> We could just wait until all the old C programmers have died. :-)

Yes, it's the nature way.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
Ian at 2018/12/8 UTC+8 AM11:28:34 wrote:
> What is it exactly that you're trying to accomplish with this? Perhaps
> there's a better way than using eval.

This problem comes from solving a word puzzle,
ab + aa + cd == ce
Each character will be translate to a digit and evaluate the correctness,
03 + 00 + 15 == 18

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
MRAB at 2018/12/8 UTC+8 AM10:04:51 wrote:
> Before Python 3, a leading 0 in an integer literal would indicate an 
> octal (base 8) number.

So, the reason is historical.

> The old form is now invalid in order to reduce the chance of bugs.

I encounter this problem on trying to do something like this:
eval('03 + 00 + 15')
It takes me some efforts to get rid of those leading zeros:-(

Hope someday 03 can be accepted as a valid decimal number in Python 3.

Thank you for explaining.

--Jach


-- 
https://mail.python.org/mailman/listinfo/python-list


Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
>>> 00
0
>>> 03
  File "", line 1
03
 ^
SyntaxError: invalid token
>>>

Any particular reason?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it dangeous when using custom metaclass?

2018-10-17 Thread jfong
dieter at 2018/10/17 UTC+8 PM 1:15:01 wrote:
> jf...@ms4.hinet.net writes:
> > Gregory Ewing at 2018/10/16 UTC+8 PM 2:01:01 wrote
> >> jf...@ms4.hinet.net wrote:
> >> > class Structure(metaclass=StructureMeta): ...
> >> > 
> >> > class PolyHeader(Structure): ...
> >> > 
> >> > As my understanding, the metaclass's __init__ was called when a class was
> >> > created. In the above example, both the Structure and PolyHeader called 
> >> > it.
> >> > My question is: because the PolyHeader inherited Structure, is it 
> >> > reasonable
> >> > for PolyHeader to call this __init__ again? Will it cause any possible
> >> > trouble?
> >> 
> >> It's reasonable for both to call it, because they're distinct
> >> instances of StructureMeta, each of which need to be initialised.
> >
> > The PolyHeader is already initialized by inheritance. Is there any way to 
> > bypass this __init__?
> 
> If there were any, you should find it described in metaclass related 
> documentation.
> 
> Likely, you can ensure that followup calls of "__init__" effectively
> behave as "no-op"s: let the first call place a marker in the initialized
> object and check in later calls whether it is already there.

Hard to find the document of type.__init__. I can only guess it does nothing, 
at least no thing serious, to avoid trouble the metaclass's __init__ may cause 
in a class hierarchy:-)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is it dangeous when using custom metaclass?

2018-10-16 Thread jfong
Gregory Ewing at 2018/10/16 UTC+8 PM 2:01:01 wrote
> jf...@ms4.hinet.net wrote:
> > class Structure(metaclass=StructureMeta): ...
> > 
> > class PolyHeader(Structure): ...
> > 
> > As my understanding, the metaclass's __init__ was called when a class was
> > created. In the above example, both the Structure and PolyHeader called it.
> > My question is: because the PolyHeader inherited Structure, is it reasonable
> > for PolyHeader to call this __init__ again? Will it cause any possible
> > trouble?
> 
> It's reasonable for both to call it, because they're distinct
> instances of StructureMeta, each of which need to be initialised.

The PolyHeader is already initialized by inheritance. Is there any way to 
bypass this __init__?

> Whether it will cause a problem depends on what StructureMeta's
> __init__ is supposed to do. Presumably you want a given structure
> class to start allocating its offsets where its base class left
> off, in which case you may need to do something like this:
> 
> class StructureMeta(type):
>  def __init__(self, clsname, bases, clsdict):
>  if bases:
> offset = bases[0].offset # assuming there isn't more than one base
>  else:
> offset = 0
>  ...
> 
> (BTW, why do you use setattr() to set the offset attribute
> instead of just doing self.offset = offset?)

No particular reason, just follows the same code pattern ahead of it where the 
attribute names are from a list:-)

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Is it dangeous when using custom metaclass?

2018-10-15 Thread jfong
class StructureMeta(type):
def __init__(self, clsname, bases, clsdict):
offset = 0
...
...
setattr(self, 'struct_size', offset)

class Structure(metaclass=StructureMeta):
...
...

class PolyHeader(Structure):
...
...

As my understanding, the metaclass's __init__ was called when a class was 
created. In the above example, both the Structure and PolyHeader called it. My 
question is: because the PolyHeader inherited Structure, is it reasonable for 
PolyHeader to call this __init__ again? Will it cause any possible trouble?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to run/debug a script file its name has characters such as space, (, etc.

2018-10-12 Thread jfong
Chris Angelico於 2018年10月12日星期五 UTC+8下午4時39分37秒寫道:
> On Fri, Oct 12, 2018 at 6:26 PM  wrote:
> >
> > I saw a directory where all its filenames are something like this:
> > ...
> > 1a PSG (Entry and PopUp).py
> > 1b PSG (Format).py
> > 1c PSG (persistent form and bind key).py
> > ...
> >
> > Just wondering how these file can run and debugged under Windows?
> >
> 
> Put the file name inside double quotes. You can probably do this by
> tab-completing the name - type 1c and then hit the tab key - your
> shell should fill out the rest of the name with whatever quoting is
> necessary.
> 
> ChrisA

After using Windows so many years, I don't know this trick the double quotes 
and tab can do in the shell. It really embarrass me:-(  Thanks you, Chris.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


How to run/debug a script file its name has characters such as space, (, etc.

2018-10-12 Thread jfong
I saw a directory where all its filenames are something like this:
...
1a PSG (Entry and PopUp).py
1b PSG (Format).py
1c PSG (persistent form and bind key).py
...

Just wondering how these file can run and debugged under Windows?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


  1   2   3   >